2

My application is accessing e-Token for decrypting the response coming from the server

The session key from the server is encrypted using :-

RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING

I am using SunPKCS11 Provider for implementing the access to crypto token. Whenever i try to decrypt this using the above mechanishm i.e. with RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING i am getting :-

**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*..)

The following is my code :-

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";

The code snippet where the error is coming is as follows :-

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);
        }
    }

I am Stuck in here and unable to decrypt the OAEP Transformation.

Manish Sahni
  • 488
  • 2
  • 7
  • 21
  • 1
    Check value of privateKey.getClass().toString(); to know what kind of key is that. It also would be very useful to see exception stack trace. – divanov May 24 '14 at 12:53
  • I am getting sun.security.pkcs11.P11Key$P11PrivateKey as the value for privateKey.getClass().toString() and for privateKy.getAlgorithm() value is coming as RSA. – Manish Sahni May 24 '14 at 17:09
  • It has to be `P11Key.P11RSAPrivateKey` for BouncyCastle to be able to make a use of it. This is probably something about how key store is created. – divanov May 24 '14 at 17:40
  • My private key is coming as the same P11Key$P11PrivateKey and i am creating Keystore as ks = KeyStore.getInstance("PKCS11", UserProvider); where Userprovider is private static final Provider UserProvider = new sun.security.pkcs11.SunPKCS11("C:\\Users\\manishs525\\pkcs11.cfg"); – Manish Sahni May 24 '14 at 18:23

2 Answers2

7

You obtain a non-extractable private key P11Key.P11PrivateKey from the dongle. It cannot be used outside PKCS11 provider, thus, SunPKCS11 provider should be used for operations with that key.

Unfortunately SunPKCS11 provider doesn't support OAEP padding, making it more difficult. Encryption still can be done with BouncyCastle, but decryption can be done with no padding and SunPKCS11 provider. keyLength parameter is RSA key modulus length in bits (1024,2048 etc).

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));
}

Notes:

  • RSA/ECB/NoPadding is not implemented for SunPKCS11 before JDK1.7.
  • This example was tested with BouncyCastle 1.50 and JDK 1.7
divanov
  • 6,173
  • 3
  • 32
  • 51
  • Hi divanov , I have imported a .p12 file into the Aladdin safenet e-token from the safenet client.However after making the mentioned changes in the code i am getting the following error as GeneralSecurityException is No such algorithm: RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING , However if i use the same .p12 file from the file path for decrypting AES secret key , then it works perfectly fine. Also the same .p12 file when imported in the e-token is used for digital signature and works fine but can't be used for decrypting the AES Secret key. Is it something related to importing the .p12 file. – Manish Sahni May 25 '14 at 09:41
  • Yes, SunPKCS11 provider doesn't support OAEP padding. If OAEP is crucial for you, then there is a need to make OAEP padding removal additionally after decryption. – divanov May 25 '14 at 19:31
  • Can you provide some references to do the removal of OAEP padding additionally after decryption. – Manish Sahni May 25 '14 at 19:53
  • 2
    This code did not work for me. I had to change the configuration to `new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT)` – mjspier Jul 24 '15 at 12:51
0

I have found the issue is that the implementation of SunJCE's Cipher "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING" is not compatible with other implementations (BouncyCastle/IAIK/PKCS11)

When setting AlgorithmParameters (with OAEPParameterSpec) an exception is thrown (javax.crypto.BadPaddingException)

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

Manish Sahni
  • 488
  • 2
  • 7
  • 21
  • In your case you use BC for RSA-OAEP encryption and SunPKCS11 for decryption, which doesn't support OAEP. Of course it's very bad that padding is not compatible, but you always can use SunJCE provider instead of BC to do encryption as both of them support RSA-OAEP. And for decryption, you use NoPadding as the only supported option for SunPKCS11 provider. So in practice you are not affected by this problem. The real problem is how to perform OAEP unpadding. – divanov May 27 '14 at 10:39
  • Hi divanov as per the [link](https://bugs.openjdk.java.net/browse/JDK-7038158?page=com.atlassian.jira.plugin.system.issuetabpanels%3aworklog-tabpanel) , my observation is that we cannot use the PKCS11 for decrypting the OAEP padding done by SunJCE.Please correct me if i am wrong here ? – Manish Sahni May 28 '14 at 06:54
  • SunPKCS11 doesn't support RSA-OAEP, so the only thing you can do with SunPKCS11 is RSA-NOPADDING. Which is also listed as workaround in the link. – divanov May 28 '14 at 08:48
  • @divanov i was trying to decrypt using 'RSA/ECB/NoPadding' and the encryption mechanism used was Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING","SunJCE");' , the error i am facing is **No such algorithm: RSA/ECB/NoPadding** . Also refer this [Bug](http://bugs.java.com/view_bug.do?bug_id=2205522). Is it that it does not support NoPadding instead it supports **RSA/ECB/PKCS1Padding** – Manish Sahni May 28 '14 at 09:37
  • @divanov while using RSA/ECB/NoPadding for decryption it gives me `Exception in thread "main" java.security.NoSuchAlgorithmException: No such algorithm: RSA/ECB/NoPadding at javax.crypto.Cipher.getInstance(DashoA13*..). – Manish Sahni May 28 '14 at 11:32
  • @divanov Whereas when i use **RSA/ECB/PKCS1Padding** for decryption then i am getting `Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_ENCRYPTED_DATA_INVALID at sun.security.pkcs11.wrapper.PKCS11.C_Decrypt(Native Method) at sun.security.pkcs11.P11RSACipher.implDoFinal(P11RSACipher.java:306) ... 4 more` I am using JDK 1.6 and Aladdin e-token in my test environment. – Manish Sahni May 28 '14 at 11:37
  • If you use JDK 1.6 and e-token then you are bound to use PKCS#1 instead of OAEP. – divanov May 28 '14 at 11:38
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/54622/discussion-between-manish-sahni-and-divanov). – Manish Sahni May 28 '14 at 11:41