誰かが私に、このコードがキーを復号化するときに最後の行にjavax.crypto.BadPaddingException: Decryption error
をスローする理由を説明できますか?
// Given an RSA key pair...
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
KeyPair keyPair = keyGen.genKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
// ... and an AES key:
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256);
SecretKey aesKey = keyGenerator.generateKey();
// When I encrypt the key with this Bouncy Castle cipher:
Cipher encryptionCipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding", "BC");
encryptionCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedKey = encryptionCipher.doFinal(aesKey.getEncoded());
// Then trying to decrypt the key with this cipher...
Cipher decryptionCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
decryptionCipher.init(Cipher.DECRYPT_MODE, privateKey);
// ... throws `javax.crypto.BadPaddingException: Decryption error` here:
decryptionCipher.doFinal(encryptedKey);
https://stackoverflow.com/a/27886397/66722 の次のステートメントはOAEPを使用するRSAにも当てはまりますか?
「RSA/ECB/PKCS1Padding」は、実際にはECBモードの暗号化を実装していません。プレーンテキスト(または実際には秘密鍵)の単一ブロックの暗号化にのみ使用できるため、「RSA/None/PKCS1Padding」と呼ばれるべきでした。これは、Sun/Oracleの名前の間違いにすぎません。
もしそうなら、私はこれらの変換が同等であり、上記の私のテストに合格することを期待します。両方で同じパディングが指定されているのに、なぜBadPaddingException
?
いずれにせよ、違いが何であるかについての素人の説明をいただければ幸いです。
詳細についての同様のStackoverflowの質問については、 Maarten Bodewes 回答 this および this を参照してください。
変換文字列の「モード」部分は効果がありません。問題は、さまざまなプロバイダーによって使用されるさまざまなデフォルトです。これは残念なことであり、間違いなく最適ではありません。 Sun/Oracleのせいにする必要がありますか?結果に不満がある以外に意見はありません。
OAEPは、パラメーターとして2つの異なるハッシュ関数を使用するかなり複雑な構造です。暗号変換文字列を使用すると、SHA-256として指定したこれらのいずれかを指定できます。ただし、MGF1関数は、暗号変換文字列で指定できないハッシュ関数によってもパラメーター化されます。 OracleプロバイダーのデフォルトはSHA1ですが、BouncyCastleプロバイダーのデフォルトはSHA-256です。したがって、実際には、相互運用性にとって重要な隠れたパラメータがあります。
解決策は、次の例のようにCipher.init(...)
メソッドに OAEPParameterSpec
を指定することにより、これらの非表示パラメーターが何であるかをより完全に指定することです。
Cipher encryptionCipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding", "BC");
OAEPParameterSpec oaepParameterSpec = new OAEPParameterSpec("SHA-256", "MGF1",
MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
encryptionCipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParameterSpec);
// ...
// ...
// ...
Cipher decryptionCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
oaepParameterSpec = new OAEPParameterSpec("SHA-256", "MGF1",
MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
decryptionCipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParameterSpec);
最初のものは、Bouncycastleのデフォルトであるため、事実上何もしません。