【问题标题】:Bad Padding Exception - RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING in pkcs11错误填充异常 - pkcs11 中的 RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING
【发布时间】:2014-07-13 17:25:47
【问题描述】:

我的应用程序正在访问 e-Token 以解密来自服务器的响应

来自服务器的会话密钥使用 :-

加密

RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING

我正在使用 SunPKCS11 Provider 来实现对加密令牌的访问。 每当我尝试使用上述机制解密它时,即使用 RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING 我得到:-

**javax.crypto.BadPaddingException: doFinal() failed  
    at sun.security.pkcs11.P11RSACipher.implDoFinal(P11RSACipher.java:328)  
    at sun.security.pkcs11.P11RSACipher.engineDoFinal(P11RSACipher.java:353)  
    at javax.crypto.Cipher.doFinal(DashoA13*..)

以下是我的代码:-

private static final String TRANSFORMATION = "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING";
private static final String SECURITY_PROVIDER = "BC";
private static final String DIGEST_ALGORITHM = "SHA-256";
private static final String MASKING_FUNCTION = "MGF1";

报错的代码sn-p如下:-

private byte[] decryptSecretKeyData(byte[] encryptedSecretKey, byte[] iv, PrivateKey privateKey) throws Exception {

        try {
            Cipher rsaCipher = Cipher.getInstance(TRANSFORMATION, SECURITY_PROVIDER);

            System.out.println("Cipher block initialized"); - **Printed**
            PSource pSrc = (new PSource.PSpecified(iv));
            System.out.println("PSource inisitialized"); - **Printed**


            rsaCipher.init(Cipher.DECRYPT_MODE, privateKey,
                    new OAEPParameterSpec(DIGEST_ALGORITHM, MASKING_FUNCTION,
                            MGF1ParameterSpec.SHA256, pSrc));


            System.out.println("Here after cipher initilaization");  - **Not Printed***

            return rsaCipher.doFinal(encryptedSecretKey);
        } catch (GeneralSecurityException e) {
            System.out.println("GeneralSecurityException is "+e.getMessage());
            throw new Exception("Failed to decrypt AES secret key using RSA.", e);
        }
    }

我被困在这里,无法解密 OAEP 转换。

【问题讨论】:

  • 检查privateKey.getClass().toString()的值;知道那是什么钥匙。查看异常堆栈跟踪也非常有用。
  • 我得到 sun.security.pkcs11.P11Key$P11PrivateKey 作为 privateKey.getClass().toString() 的值,而 privateKy.getAlgorithm() 的值是 RSA。
  • BouncyCastle 必须是 P11Key.P11RSAPrivateKey 才能使用它。这可能是关于如何创建密钥库的问题。
  • 我的私钥与 P11Key$P11PrivateKey 相同,我正在创建 Keystore 作为 ks = KeyStore.getInstance("PKCS11", UserProvider);其中 Userprovider 是私有静态 final Provider UserProvider = new sun.security.pkcs11.SunPKCS11("C:\\Users\\manishs525\\pkcs11.cfg");

标签: java encryption bouncycastle smartcard pkcs#11


【解决方案1】:

您从加密狗获得一个不可提取的私钥P11Key.P11PrivateKey。它不能在 PKCS11 提供程序之外使用,因此,应使用 SunPKCS11 提供程序进行具有该密钥的操作。

很遗憾,SunPKCS11 提供程序不支持 OAEP 填充,这使其更加困难。 加密仍然可以使用 BouncyCastle 完成,但解密可以在没有填充和 SunPKCS11 提供程序的情况下完成。 keyLength 参数是以位为单位的 RSA 密钥模数长度(1024,2048 等)。

private void testEncryption(byte[] plainText, PrivateKey privateKey, PublicKey publicKey, int keyLength) throws GeneralSecurityException {

    System.out.println("Plain text: " + DatatypeConverter.printHexBinary(plainText));

    Provider bcProvider = new BouncyCastleProvider();
    Cipher rsaCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING", bcProvider);
    rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);
    byte[] cipherText = rsaCipher.doFinal(plainText);

    System.out.println("Cipher text: " + DatatypeConverter.printHexBinary(cipherText));

    Provider pkcs11provider = new SunPKCS11("C:\\Users\\manishs525\\pkcs11.cfg");
    Cipher rsaCipher2 = Cipher.getInstance("RSA/ECB/NoPadding", pkcs11provider);
    rsaCipher2.init(Cipher.DECRYPT_MODE, privateKey);
    byte[] paddedPlainText = rsaCipher2.doFinal(cipherText);

    /* Ensure leading zeros not stripped */
    if (paddedPlainText.length < keyLength / 8) {
        byte[] tmp = new byte[keyLength / 8];
        System.arraycopy(paddedPlainText, 0, tmp, tmp.length - paddedPlainText.length, paddedPlainText.length);
        System.out.println("Zero padding to " + (keyLength / 8));
        paddedPlainText = tmp;
    }           

    System.out.println("OAEP padded plain text: " + DatatypeConverter.printHexBinary(paddedPlainText));

    OAEPParameterSpec paramSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1,
            PSource.PSpecified.DEFAULT);
    RSAPadding padding = RSAPadding.getInstance(RSAPadding.PAD_OAEP_MGF1, keyLength / 8, new SecureRandom(), paramSpec);
    byte[] plainText2 = padding.unpad(paddedPlainText);

    System.out.println("Unpadded plain text: " + DatatypeConverter.printHexBinary(plainText2));
}

注意事项:

  • JDK1.7 之前的 SunPKCS11 未实现 RSA/ECB/NoPadding。
  • 此示例已使用 BouncyCastle 1.50 和 JDK 1.7 进行了测试

【讨论】:

  • 您好 divanov,我已从 safenet 客户端将 .p12 文件导入到 Aladdin safenet 电子令牌中。但是在代码中进行上述更改后,我收到以下错误,因为 GeneralSecurityException 是 No such算法:RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING,但是如果我使用文件路径中的相同 .p12 文件来解密 AES 密钥,那么它工作得很好。在电子令牌中导入时,相同的 .p12 文件也用于数字签名并且工作正常,但不能用于解密 AES 密钥。是否与导入 .p12 文件有关。
  • 是的,SunPKCS11 提供程序不支持 OAEP 填充。如果 OAEP 对您至关重要,则需要在解密后额外删除 OAEP 填充。
  • 您能否提供一些参考资料以在解密后额外删除 OAEP 填充。
  • 这段代码对我不起作用。我不得不将配置更改为new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT)
【解决方案2】:

我发现问题是 SunJCE 的密码“RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING”的实现与其他实现不兼容(BouncyCastle/IAIK/PKCS11 )

在设置 AlgorithmParameters(使用 OAEPParameterSpec)时会引发异常(javax.crypto.BadPaddingException)

参考: Problems with Cipher "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING" Bug Details

【讨论】:

  • 在您的情况下,您使用 BC 进行 RSA-OAEP 加密,使用 SunPKCS11 进行解密,它不支持 OAEP。当然,填充不兼容是非常糟糕的,但是您始终可以使用 SunJCE 提供程序而不是 BC 进行加密,因为它们都支持 RSA-OAEP。对于解密,您使用 NoPadding 作为 SunPKCS11 提供程序唯一支持的选项。所以在实践中你不会受到这个问题的影响。真正的问题是如何执行 OAEP 取消填充。
  • 您好 divanov 根据link,我的观察是我们不能使用 PKCS11 来解密 SunJCE 完成的 OAEP 填充。如果我在这里错了,请纠正我?
  • SunPKCS11 不支持 RSA-OAEP,因此您对 SunPKCS11 唯一能做的就是 RSA-NOPADDING。这也被列为链接中的解决方法。
  • @divanov 我试图使用 'RSA/ECB/NoPadding' 解密,使用的加密机制是 Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING","SunJCE");' ,我面临的错误是 No such algorithm: RSA/ECB/NoPadding 。另请参阅此Bug。是不是不支持 NoPadding 而是支持 RSA/ECB/PKCS1Padding
  • @divanov 在使用 RSA/ECB/NoPadding 进行解密时,它给了我`线程“主”java.security.NoSuchAlgorithmException 中的异常:没有这样的算法:javax.crypto.Cipher 的 RSA/ECB/NoPadding .getInstance(DashoA13*..).
猜你喜欢
  • 2015-11-16
  • 2020-03-17
  • 1970-01-01
  • 2019-05-27
  • 2021-11-16
  • 2015-08-31
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
相关资源
最近更新 更多