我在 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
}
//
}
}