Bouncy Castle vs Java默认RSA与OAEP [英] Bouncy Castle vs Java default RSA with OAEP

查看:955
本文介绍了Bouncy Castle vs Java默认RSA与OAEP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以向我解释为什么这个代码在解密密钥时会在最后一行抛出 javax.crypto.BadPaddingException:解密错误吗?

Can someone explain to me why this code throws javax.crypto.BadPaddingException: Decryption error on the final line when it's decrypting the key?

// 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?

Is the following statement from https://stackoverflow.com/a/27886397/66722 also true for RSA with OAEP?


RSA / ECB / PKCS1Padding实际上没有实现ECB模式加密。
它应该被称为RSA / None / PKCS1Padding,因为它只能用于加密单个明文块(或者实际上是一个密钥)的

这只是Sun / Oracle的一个命名错误。

"RSA/ECB/PKCS1Padding" actually doesn't implement ECB mode encryption. It should have been called "RSA/None/PKCS1Padding" as it can only be used to encrypt a single block of plaintext (or, indeed a secret key). This is just a naming mistake of Sun/Oracle.

如果是这样,我希望这些转换是等效的,我上面的测试通过。两者都指定了相同的填充,为什么 BadPaddingException

If so, I would expect these transformations to be equivalent and my test above to pass. The same padding has been specified in both, so why the BadPaddingException?

无论哪种方式,我都会感谢外行人的解释有什么区别。

Either way, I would appreciate a layman's explanation of what the difference is.

推荐答案

有关更多信息的类似Stackoverflow问题,请参阅Marten Bodewes 回答这个这个

For similar Stackoverflow questions with more information please see Maarten Bodewes answers to this and this.

转换字符串的模式部分无效。问题是不同提供商使用的默认值不同。这是不幸的,非常不理想。我们应该责怪Sun / Oracle吗?除了对结果不满意之外,我没有任何意见。

The "mode" part of the transformation string has no effect. The problem is different defaults used by different providers. This is unfortunate and very definitely suboptimal. Should we blame Sun/Oracle? I have no opinion beyond being dissatisfied with the result.

OAEP是一个相当复杂的结构,有两个不同的哈希函数作为参数。密码转换字符串允许您指定其中一个,您已指定为SHA-256。但是,MGF1函数也通过哈希函数进行参数化,您无法在密码转换字符串中指定。 Oracle提供程序默认为SHA1,而BouncyCastle提供程序默认为SHA-256。因此,实际上,存在一个对互操作性至关重要的隐藏参数。

OAEP is a fairly complicated construction with two different hash functions as parameters. The Cipher transform string lets you specify one of these, which you have specified as SHA-256. However, the MGF1 function also is parameterized by a hash function which you cannot specify in the cipher transformation string. The Oracle provider defaults to SHA1 whereas the BouncyCastle provider defaults to SHA-256. So, in effect, there is a hidden parameter that is critical for interoperability.

解决方案是通过提供 OAEPParameterSpec Cipher.init(...)方法,如下例所示:

The solution is to specify more fully what these hidden parameters are by supplying an OAEPParameterSpec to the Cipher.init(...) method as in the following example:

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的默认值。

The first one is effectively a no-op, because those are already the defaults for Bouncycastle.

这篇关于Bouncy Castle vs Java默认RSA与OAEP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆