有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

加密Bouncy Castle vs Java默认RSA with OAEP

有人能解释一下为什么这段代码在解密密钥时在最后一行抛出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" 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

不管怎样,我都希望外行能解释一下两者的区别


共 (1) 个答案

  1. # 1 楼答案

    有关更多信息的类似问题,请参见Maarten Bodewesthisthis的回答

    转换字符串的“模式”部分无效。问题在于不同的提供者使用不同的默认值。这是不幸的,而且肯定是次优的。我们应该责怪太阳/甲骨文吗?除了对结果不满之外,我没有别的意见

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

    解决方案是通过向Cipher.init(...)方法提供一个^{}来更全面地指定这些隐藏参数,如下例所示:

    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的默认设置