0

我在 Groovy(JDK 1.6) 中使用带有填充的 AES 得到“BadPaddingException:给定最终块未正确填充”异常。

我在尝试使用从属性文件中解密加密的字符串值(独立于加密过程运行)运行 decode() 方法时遇到此错误。加密是单独完成的,并存储在单独进程中的属性文件中。

当加密(编码方法)和解密(解码方法)像在主方法中一样一起运行时,这可以正常工作。

我已经为此浏览了 stackoverflow 问题,其中 1 个人说我在解密时遇到了错误的密钥问题。

我查看了存储在文件中的 iv 内容,它们是相同的,存储在密钥库中的 Secretkey 也是相同的。

那么,我是否在 Cipher.init(..) 步骤中失败了,其中密码代码在幕后使用了 SecureRandom。还是我没有正确存储密钥或 iv 填充?

我已将 iv 和 SecretKey 存储在单独的文件中,以便它们可以在单独的过程中重复用于解密,而与加密何时完成无关。

iv 值示例: 在加密期间:加密 iv 创建:[-8, 95, -47, -35, 77, 25, 113, -110, 95, 51, 71, -110, -92, -63, -95, -17]secretKey:javax.crypto.spec.SecretKeySpec@16c11

解密时:读取iv:[-8, 95, -47, -35, 77, 25, 113, -110, 95, 51, 71, -110, -92, -63, -95, -17] secretKey: javax.crypto.spec.SecretKeySpec@16c11

TIA 寻求帮助,维杰

class AESCodec extends ... {

public static final String IV_FILE="C:/keystore/iv-file"    
private static final String RANDOM_ALGORITHM = "SHA1PRNG";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";


static encode = { String target ->
    def cipher = getCipher(Cipher.ENCRYPT_MODE)
    return cipher.doFinal(target.bytes).encodeBase64()
}

static decode = { String target ->
    //println "target:"+target
    println "enter decode with target:"+target
    def cipher = getCipher(Cipher.DECRYPT_MODE)
    println "decode cipher:"+cipher
    return new String(cipher.doFinal(target.decodeBase64()))//<============== failing here when running decode independently
}

private String secretPassword

private String getSecretKey() {
    return "secret12"
}

private static getPassword() { new AESCodec().getSecretKey().getChars() }

private static byte[] iv

static SecretKey secretKey
/*
* Get key from Keystore where it is stored after creation
*/
private static SecretKey createKey(Integer mode) {
    println "createKey() mode values 1=encrypt,2=decrypt mode:"+mode
    if (secretKey == null) {
        if (mode== Cipher.ENCRYPT_MODE) {
            println "inside encrypt mode in createKey()"
            byte[] salt = "DYKSalt".getBytes()
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
            KeySpec spec = new PBEKeySpec(getPassword(), salt, 65536, 256)
            SecretKey tmp = factory.generateSecret(spec)
            SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES")
            secretKey = secret
            println 'inside encrypt secretKey:'+secretKey
            //store it in keystore
            KeyStore ks = KeyStore.getInstance("JCEKS")
            ks.load(null, null);
            KeyStore.SecretKeyEntry skEntry = new KeyStore.SecretKeyEntry(secretKey)
            //key alias and passwd
            ks.setEntry("alias", skEntry,
              new KeyStore.PasswordProtection("fggd".toCharArray()))
            FileOutputStream fos = null
            try {
                fos = new FileOutputStream(AsymmetricCipher.KEYSTORE_DIR+"aes.keystore")
                //keystore passwd
                ks.store(fos, "fggd".toCharArray())
            } finally {

                fos?.close()

            }


        } else if (mode== Cipher.DECRYPT_MODE) {


            InputStream inputStream = getKeystoreAsStream(AsymmetricCipher.KEYSTORE_DIR+"aes.keystore")

            BufferedInputStream fis = null
            try {

                fis = new BufferedInputStream(inputStream)
                println "fis:"+fis
                //keystore passwd
                KeyStore ks = KeyStore.getInstance("JCEKS")
                //get key store
                ks.load(fis, "fggd".toCharArray())

                //get key from keystore
                Entry entry = ks.getEntry("alias", new KeyStore.PasswordProtection("fggd".toCharArray()))
                KeyStore.SecretKeyEntry secretKeystoreEntry = (KeyStore.SecretKeyEntry)entry
                secretKey = secretKeystoreEntry.getSecretKey()
                println " returned secretKey from decrypt mode"
            } finally {

                fis?.close()

            }

        }

    } else {


    }

    return secretKey
}


private SecretKey getKey() {

    return secretKey
}

private static getCipher(mode) {


  SecretKey secret = createKey(mode)
  Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
  println "secret:"+secret.getEncoded()
  println "cipher:"+cipher

  if (mode == Cipher.DECRYPT_MODE) {
      //get iv
      iv = readIvFromFile(IV_FILE)
      println "decrypt iv created from file:"+iv
      IvParameterSpec ivspec = new IvParameterSpec(iv);
      println "ivspec:"+ivspec
      cipher.init(mode, secret,ivspec)
      //cipher.init(mode, secret)
  } else {

      //save that to IV_FILE
      byte[] iv = generateIv();
      println "encrypt iv created:"+iv
      IvParameterSpec ivspec = new IvParameterSpec(iv);
      println "ivspec:"+ivspec
      cipher.init(mode, secret,ivspec)
      //iv = cipher.getIV()
      AlgorithmParameters params = cipher.getParameters()
      iv = params.getParameterSpec(IvParameterSpec.class).getIV()
      saveToFile(IV_FILE,iv)
  }


  return cipher

}

private static byte[] generateIv() throws NoSuchAlgorithmException {
    SecureRandom random = SecureRandom.getInstance(RANDOM_ALGORITHM);
    byte[] iv = new byte[16];
    random.nextBytes(iv);
    return iv;
}


public static void saveToFile(String fileName,
    byte[] iv) throws IOException {
    println "saveToFile() fileName:"+fileName
    FileOutputStream oout = 
      new FileOutputStream(fileName);

    try {
      oout.write(iv);

    } catch (Exception e) {
      throw new IOException("Unexpected error", e);
    } finally {

        oout?.flush()
        oout?.close()
    }
}

private static byte[] readIvFromFile(String keyFileName)
throws IOException {
    println "readIvFromFile() keyFileName:"+keyFileName

    InputStream inputStream = AsymmetricCipher.getFile(keyFileName)

    try {

      iv = IOUtils.toByteArray(inputStream);

      println "read iv:"+iv
      return iv;
    } catch (Exception e) {
        throw new RuntimeException("Spurious serialisation error ", e);
    } finally {
        inputStream = null
        //oin?.close();
    }

}


static void main(String[] args) {

  String message="This is just an example";

  if(args) {

      def encryptedValue =  encode(args[0])
      println "encryptedValue:"+encryptedValue //byte[]

      String encryptedValue1=(String)(encryptedValue)
      println "encryptedValue1:"+encryptedValue1



      def decryptedValue = decode(encryptedValue1)
      println "decryptedValue:"+decryptedValue
      def decryptedValueStr = (String)decryptedValue


  }

//
}

}

4

1 回答 1

0

看看:http ://code.google.com/p/encryption-utils/source/browse/#svn%2Ftrunk%2Fsrc%2Fmain%2Fjava%2Fcom%2Fgoogle%2Fcode%2Fencryptionutils

这是我为简单加密编写的一个小库。希望它能给你一些方向。

于 2012-04-19T01:00:05.020 回答