Javaキーストア-詳細

10443 ワード

Øriginally posted on my blog
Java KeyStoreは、鍵の材料と関連する証明書を暗号化および完全性保護の方法で格納するために使用されます.Javaのすべてのもののように、このメカニズムは挿入可能であるため、さまざまな選択肢があります.そこには、異なるタイプと、それらを初期化する方法、鍵のロード、証明書などを説明する文章がたくさんあります.しかしながら、これらの鍵ライブラリが鍵材料をどのように格納および保護するかに関する詳細な技術情報が欠けている.この文章は最も重要なKeyStoreの重要な細部を一つに集中しようとしている.
各キー・ストレージには、ストレージ全体を保護するための全体的なパスワードがあり、バックエンドでサポートされている場合、各秘密鍵または秘密鍵エントリにエントリ別に入力されたパスワードを選択できます.
Javaキーストア(JKS)
元のSun JKS(Javaキーストア)形式は独自のバイナリ形式のファイルで、非対称の秘密鍵と関連するX.509証明書しか保存できません.
Individual private key entries are protected with a simple home-spun stream cipher—basically the password is salted (160-bits) and hashed with SHA-1 in a trivial chained construction until it has generated enough output bytes to XOR into the private key. It then stores a simple authenticator tag consisting of SHA-1(password + private key bytes) — that's the unencrypted private key bytes. In other words, this is an Encrypt-and-MAC scheme with homespun constructions both based on simple prefix-keyed SHA-1. (This scheme has OID 1.3.6.1.4.1.42.2.17.1.1).
リポジトリ全体は、元の鍵ライブラリパスワードのUTF-16バイトのSHA 1ハッシュ、後に「Mighty Aphrodite」というフレーズのUTF-8バイト(I(冗談ではない)、後に符号化された鍵ストレージエントリのバイトを含むローカル回転プレフィックスキーハッシュ構造の完全性によって再び保護される.
この説明の各セクションで、画面上で恐怖と迷いを同時に叫ばせなかった場合は、これがどんなに悪いかを完全に理解していない可能性があります.証明書を保存するためにのみ使用しても、使用しないでください.改ざん防止機能は暗号化よりも悪いものです.
JCEキーストア(JCEKS)
Sunはその後、Javaパスワード拡張(JCE)によりJVMのパスワード機能を更新した.このようにして、JCEKSという新しい独自鍵格納フォーマットも導入した.
JCEKS uses "PBEWithMD5AndTripleDES"to encrypt individual key entries, with a 64-bit random salt and 200,000 iterations of PBKDF1 to derive the key. TripleDES is used with 3 keys ("encrypt-decrypt-encrypt") in CBC mode. There is no separate integrity protection of individual keys, which is fine if the archive as a whole is integrity protected, but it means that access control is effectively at the level of the whole keystore. This is not terrible from a crypto point of view, but can definitely be improved—neither MD5 nor TripleDES are considered secure any more, and it's been a long time since anyone recommended them for new projects. However, it would also not be a trivial effort to break it.
JCEKSは、JKSと同じでたらめな「Mighty Aphrodite」プレフィックス・キー・ハッシュを使用して、アーカイブ全体を保護します.これらのキー・リポジトリのいずれも厳密な整合性保護がないと仮定したほうがいいです.
PKCS#12
これらのプライベート・キー・ライブラリに加えて、Javaは「標準」PKCS#12フォーマットのキー・ライブラリもサポートしています.「標準」の周囲に引用符を付けるのは、確かに標準フォーマットですが、非常に柔軟なフォーマットであるため、実際には異なるソフトウェアでサポートされている「キー・バッグ」フォーマットと暗号化アルゴリズムの間には大きな違いがあります.たとえば、Javaから対称SecretKeyオブジェクトをPKCS#12鍵格納領域に格納すると、OpenSSLはそれらを読み取ることができません.なぜなら、それらは袋タイプ(「secretBag」-OUD 1.2.84.1359.1.12.0.1.5)を使用しているからです.
Javaは、PKCS#12標準形式のバージョン3を使用しています.前述の「secretBag」形式で秘密鍵を格納し、「PKCS#8で覆われた鍵袋」形式(OID 1.2.84013549.12.10.10.1.2)で非対称秘密鍵を格納します.これは、ディスク上のバイトの形式のみを示します.いずれの場合も、実際の鍵材料は、何らかの形式の暗号化(PBE)を使用していますパターン暗号化されています.デフォルトでは、「PBEWithSHA 1 AndDESede」-「DESede」は、暗号化-復号化-暗号化モードのTripleDESの別の名前であるため、JCEKSで使用されるパターンと非常に似ていますが、ハッシュSHA-1が使用されているのとは異なり、デフォルトでは160ビットの塩と50000回の反復が使用されています.
乙ut,there is an important improvement in the PKCS#12 implementation—you get to choose the encryption algorithm!By passing in a PasswordProtection parameter(from Java 8 onwards)when saving a key you can specify a particular(password-based) cipher to use. I haven't checked exactly what ciphers are allowed, but you can at least specify a stronger PBE mode, such as "PBEWithHmacSHA512AndAES_256", which will derive a 256-bit AES key using salted PBKDF2 and then encrypt the stored key using AES/CBC/PKCS5Padding with that key. You can also increase the number of iterations of PBKDF2 used. For example:
import java.io.FileOutputStream;
import java.security.KeyStore;
import java.security.KeyStore.PasswordProtection;
import java.security.KeyStore.SecretKeyEntry;
import java.security.SecureRandom;

import javax.crypto.SecretKey;
import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class scratch {
    public static void main(String... args) throws Exception {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(null, null); // Initialize a blank keystore

        SecretKey key = new SecretKeySpec(new byte[32], "AES");

        char[] password = "changeit".toCharArray();
        byte[] salt = new byte[20];
        new SecureRandom().nextBytes(salt);
        keyStore.setEntry("test", new SecretKeyEntry(key),
            new PasswordProtection(password,
                "PBEWithHmacSHA512AndAES_128",
                new PBEParameterSpec(salt, 100_000)));

        keyStore.store(new FileOutputStream("/tmp/keystore.p12"), password);
    }
}

上記のPBEモードにはHmacSHA 512が含まれていますが、これはパスワードから派生した鍵にのみ適用されます.単一のエントリレベルでは完全性保護されていません.
また、鍵ライブラリと単一の鍵パスワードは同じであるべきであることに注意してください.JavaにおけるPKCS#12の基本的な制限ではないと思いますが、コマンドライン「keytool」などのユーティリティなどの標準Javaツールでは、ショップ用のパスワードと個別の鍵を使用して、異なるパスワードを持つPKCS#12鍵ライブラリを処理できません.これらのツールを使用する必要がない場合は、鍵ごとに異なるパスワードを使用できます.
以前のエントリと比較して、PKCS#12鍵格納フォーマットは、証明書を実際に暗号化しています.ハードコーディングアルゴリズム「PBEWithSHA 1 AndRC 2_40」を使用します.この操作を実行します.これは50000輪の塩漬けPBKDF 1を使用して40ビットのkey for RC 2 encryption.RC 2 is an old stream cipher that I certainly wouldn't recommend.The 40ビットのkey isが小さすぎて、深刻な安全性を提供できません.これはなぜ50000輪のPBKDF 1を使ってパスワードを保護し、自分が暴力的に解読されやすい鍵を生成するのか知りたいです.派生鍵を暴力的に解読する速度は実際には元のパスワードよりも速いかもしれません.私はそれがいくつかの参加した意思決定と互換性を維持していると仮定するしかありませんが、意思決定に参加した各方面は深く残念に思っています.
PKCS#12鍵ストレージ全体の完全性は「HmacPBESHA 1」保護されています.これはHMAC-SHA 1です.100,000回塩漬けされたPBKDF 2-HMAC-SHA 1反復を使用した店舗パスワードから派生した鍵を使用します.これらはハードコーディングされているので変更できません.ここでSHA-1以外の機能を使用できるのは良い選択ですが、PKCS#12は他のMACの使用を許可しているようです.HMACの使用についてSHA-1しばらくはいいですが、削除したほうがいいです.反復回数を調整できるのもいいです.
全体的にPKCS#12鍵ストレージは、Sunが設計した任意の固有のオプションよりもはるかに優れています.AESとSHA 2を使用して独自のPasswordProtectionインスタンスを指定し、高い反復回数と良好なランダム塩を使用すると、現代の基準でも実際にはかなり信頼できる設計になります.唯一の本当に醜い部分は、信頼できる証明書の40ビットRC 2プラスです密ですが、証明書の機密性に関心がない場合は、この詳細を無視して曖昧に処理することができます.少なくとも、HMAC-SHA 1を使用することは、少なくとも1つの体面の完全性保護です.
PKCS#11
There's not much to say about PKCS#11. It is a standard interface, intended for use with hardware security tokens of various kinds: in particular Hardware Security Modules (HSMs). These range from 50 Euro USB sticks up to network-attached behemoths that cost tens or hundreds of thousands of dollars. The hardware is usually proprietary and closed, so it's hard to say exactly how your keys will be stored. Generally, though, there are significant protections against access to keys from either remote attackers or even those with physical access to the hardware and a lot of time on their hands. This isn't a guarantee of security, as there are lots of ways that keys might accidentally leak from the hardware, as the recent ROCA vulnerability in Infineon hardware demonstrated. Still, a well-tested HSM is probably a pretty secure option for high-value keys.
各ベンダーによって異なるため、PKCS#11鍵ストレージの設定方法については詳しく説明しません.PKCS#12の場合、インタフェースは標準化されていますが、この標準内には大きな変化の余地があります.ほとんどの場合、HSMはセキュリティハードウェアで鍵を生成し、秘密鍵材料(バックアップ用かもしれません)をエクスポートしません.
サマリ
HSMまたはPKCS#12キー・ライブラリを使用して、キーの保存時に手動のPasswordProtectionパラメータを指定します.プライベート・キー・ライブラリの使用は避けてください.
Alternatively, farm out key management to somebody else and use a Key Management System (KMS) like Hashicorp Vault.
from: https://dev.to//neilmadden/java-keystoresthe-gory-details-dnj