Javaの非対称暗号化:店舗の公開/秘密鍵の好ましい方法
-
27-09-2019 - |
質問
このコードは、公開/秘密鍵のペアを生成します:
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair keypair = keyGen.genKeyPair();
PrivateKey privateKey = keypair.getPrivate();
PublicKey publicKey = keypair.getPublic();
私が知りたいのですが何が通常の公開鍵を格納しない方法です。
のオプション1:ストアの
バイトbyte[] privateKeyBytes = privateKey.getEncoded();
byte[] publicKeyBytes = publicKey.getEncoded();
// ... write to file
// convert bytes back to public/private keys
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
私は好きではないことは、このようなPKCS8EncodedKeySpec
やX509EncodedKeySpec
など、具体的な実装にコードを結びつけることです。
のオプション2:係数を格納し、指数の
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(publicKey, RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = fact.getKeySpec(privateKey,RSAPrivateKeySpec.class);
// store modulus and exponent as BigIntegers
BigInteger modulus = pub.getModulus());
BigInteger exponent = pub.getPublicExponent());
// ... write to file
// recreate public key (the same applies to the private key)
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
二番目のオプションは、実装が簡単ですが、それはあまりパフォーマンスの可能性があれば、私は知りません。
任意のアドバイス?
解決
は、当社のアプリケーションでは、我々は、DER形式で公開鍵と秘密鍵を格納します。我々の場合には、秘密鍵は、それらのパスワードを持っていません。
Javaで何かに、より簡単に使用可能な秘密鍵を変換するには:
openssl pkcs8 -topk8 -nocrypt -in key.pem -inform PEM -out key.der -outform DER
そして、あなたがして直接RSA秘密鍵を取得することができます:
public static RSAPrivateKey getPrivateKey(File privateKeyFile) throws IOException, GeneralSecurityException {
byte[] keyBytes = new byte[(int)privateKeyFile.length()];
FileInputStream fis = new FileInputStream(privateKeyFile);
fis.read(keyBytes);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(spec);
return privKey;
}
は、公開鍵は似てます:
openssl rsa -in private.pem -pubout -outform DER -out public.der
と、それを読むために:
public static RSAPublicKey getPublicKey(File publicKeyFile) throws IOException, GeneralSecurityException {
byte[] keyBytes = new byte[(int)publicKeyFile.length()];
FileInputStream fis = new FileInputStream(publicKeyFile);
fis.read(keyBytes);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
RSAPublicKey pubKey = (RSAPublicKey)factory.generatePublic(publicKeySpec);
return pubKey;
}
多くの人が、その後キーストアを格納します。我々の目的のために、我々はいくつかの異なる言語で複数のアプリケーション間で共有するために同じキーを必要とし、ディスク上のファイルを複製したくありませんでした。
あなたがそれらを毎回再生成するのではなく、シングルトンやキャッシュのいくつかの並べ替えでは、これらのキーを格納するためにそうしているので、はいずれの場合も、パフォーマンスは、大きな関心事ではありません。
他のヒント
あなたが実際にあなたがそれを実現するかどうか、両方のケースでバイトを保存しています。私は、正しい答えが最も自然な形で、より高いレベルのオブジェクトを格納することです@Brian M.カーの答えは、中で示唆されているとします。公開鍵の場合には、明白な選択肢であるPKCS#1のRSAPublicKeyのASN.1構造として、DER符号化され、又はX509 SubjectPublicKeyInfoでASN.1構造として、DER符号化されました。後者は、Sunのプロバイダは、太陽のクラスX509EncodedKeySpecの支援をあなたを与えるものです。同様に、あるPKCS8EncodedKeySpecは、秘密鍵のフォーマットをサポートしています。これらの両方のフォーマットは標準で、例えばopensslのサポートされています。 Sunは傾向がある - 傾向が見られた:( - 自分自身を定義ではなく、既存の規格をサポートするために、
。、その後、私はあなたが(古いものは、例えば、弱になったとき)の暗号化を変更したいとき、それは壊れていないことを消耗そうであるフォーマットを選択することになります。
私は一緒に多分フォーマットを説明する文字列、「RSA」と、BASE64として符号化されたバイト格納しますので。