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

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

问题描述

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

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 中的以下陈述是否也适用于 RSAOAEP?

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 问题的更多信息,请参阅 Maarten 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.

解决方案是通过提供 OAEPParameterSpecCipher.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 与 Java 默认 RSA 与 OAEP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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