Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7038158

Problems with Cipher "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING"

XMLWordPrintable

      FULL PRODUCT VERSION :
      java version "1.6.0_24"
      Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
      Java HotSpot(TM) Client VM (build 19.1-b02, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      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)


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Encrypt data with SunJCE Provider and "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING"
      Try to decrypt the data e.g. with BouncyCastleProvider

      Initialize the Cipher explicit with AlgorithmParameters (OAEPParameterSpec)

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Data encrypted with SunJCE provider and "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING" should be able to decrypt with other implementations

      No exception when setting AlgorithmParameters
      ACTUAL -
      BouncyCastle cannot decrypt the data.

      javax.crypto.BadPaddingException when setting AlgorithmParameters

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      javax.crypto.BadPaddingException: data hash wrong
      at org.bouncycastle.jce.provider.JCERSACipher.engineDoFinal(Unknown Source)
      at javax.crypto.Cipher.doFinal(DashoA13*..)
      at com.secunet.BugReport.testSHA256_1(BugReport.java:72)
      at com.secunet.BugReport.main(BugReport.java:31)


      javax.crypto.BadPaddingException: java.security.DigestException: Length must be at least 32 for SHA-256digests
      at sun.security.rsa.RSAPadding.mgf1(RSAPadding.java:452)
      at sun.security.rsa.RSAPadding.padOAEP(RSAPadding.java:377)
      at sun.security.rsa.RSAPadding.pad(RSAPadding.java:229)
      at sun.security.rsa.RSAPadding.pad(RSAPadding.java:211)
      at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
      at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
      at javax.crypto.Cipher.doFinal(DashoA13*..)
      at com.secunet.BugReport.testSHA256_2(BugReport.java:93)
      at com.secunet.BugReport.main(BugReport.java:33)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package com.secunet;

      import java.security.AlgorithmParameters;
      import java.security.KeyPair;
      import java.security.KeyPairGenerator;
      import java.security.Security;
      import java.security.spec.AlgorithmParameterSpec;
      import java.security.spec.MGF1ParameterSpec;
      import java.util.Arrays;

      import javax.crypto.Cipher;
      import javax.crypto.spec.OAEPParameterSpec;
      import javax.crypto.spec.PSource;

      //Note: you must have http://www.bouncycastle.org/download/bcprov-jdk16-146.jar in classpath
      import org.bouncycastle.jce.provider.BouncyCastleProvider;

      public class BugReport {
          
          public static final String data = "1234567890";

          public static void main(String [] args) {
              try {
                  Security.addProvider(new BouncyCastleProvider());
                  
                  KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
                  kpg.initialize(1024);
                  KeyPair kp = kpg.generateKeyPair();

                  testSHA1(kp);
                  System.out.println();
                  testSHA256_1(kp);
                  System.out.println();
                  testSHA256_2(kp);

              }
              catch (Throwable e) {
                  e.printStackTrace();
              }
              finally {
                  System.out.println("END");
              }
          }

          public static void testSHA1(KeyPair kp) {
              try {
                  Cipher ce = Cipher.getInstance("RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING", "SunJCE");
                  ce.init(Cipher.ENCRYPT_MODE, kp.getPublic());
                  byte [] encryptedData = ce.doFinal(data.getBytes());

                  Cipher cd = Cipher.getInstance("RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING", "BC");
                  cd.init(Cipher.DECRYPT_MODE, kp.getPrivate());
                  byte [] decryptedData = cd.doFinal(encryptedData);

                  if (!Arrays.equals(data.getBytes(), decryptedData))
                      throw new RuntimeException("Decrypt Faild, data not equal");
                  System.out.println("OK: SHA-1 test");
              }
              catch (Exception e) {
                  e.printStackTrace(System.out);
                  System.out.println("ERROR: SHA-1 test");
              }
          }
          
          public static void testSHA256_1(KeyPair kp){
              try{
              Cipher ce = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING", "SunJCE");
              ce.init(Cipher.ENCRYPT_MODE, kp.getPublic());
              byte [] encryptedData = ce.doFinal(data.getBytes());
              
              Cipher cd = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING", "BC");
              cd.init(Cipher.DECRYPT_MODE, kp.getPrivate());
              byte [] decryptedData = cd.doFinal(encryptedData);
              
              if (!Arrays.equals(data.getBytes(), decryptedData))
                  throw new RuntimeException ("Decrypt Faild, data not equal");
              System.out.println("OK: SHA-256 test");
              }catch(Exception e){
                  e.printStackTrace(System.out);
                  System.out.println("ERROR: SHA-256 test");
              }
          }
          
          public static void testSHA256_2(KeyPair kp){
              try{
                  
              AlgorithmParameters algp = AlgorithmParameters.getInstance("OAEP", "SunJCE");
              AlgorithmParameterSpec paramSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256,
                      PSource.PSpecified.DEFAULT);

              algp.init(paramSpec);
              Cipher ce = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING", "SunJCE");
              ce.init(Cipher.ENCRYPT_MODE, kp.getPublic(), algp);
              byte [] encryptedData = ce.doFinal(data.getBytes());
              
              Cipher cd = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING", "BC");
              cd.init(Cipher.DECRYPT_MODE, kp.getPrivate());
              byte [] decryptedData = cd.doFinal(encryptedData);
              
              if (!Arrays.equals(data.getBytes(), decryptedData))
                  throw new RuntimeException ("Decrypt Faild, data not equal");
              System.out.println("OK: SHA-256 with parameter test");
              }catch(Exception e){
                  e.printStackTrace(System.out);
                  System.out.println("ERROR: SHA-256 with parameter test");
              }
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Do the OAEP padding (PKCS#1 V2.1) manually and use cipher "RSA/ECB/NOPADDING"

            kdriver Kevin Driver
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: