我正在尝试解密从后端服务器收到的字符串"~9?8?m???=?T?G"
,后端服务器使用OpenSSL使用AES-256-CBC加密字符串。有代码块:
public static String decryptText(String textToDecrypt) {
try {
byte[] base64TextToDecrypt = Base64.encodeBase64(textToDecrypt.getBytes("UTF-8"));
byte[] guid = "fjakdsjkld;asfj".getBytes("UTF-8");
byte[] iv = new byte[16];
System.arraycopy(guid, 0, iv, 0, guid.length);
IvParameterSpec ips = new IvParameterSpec(iv);
byte[] secret = DECRYPTION_SECRET_HASH.getBytes("UTF-8");
SecretKeySpec secretKey = new SecretKeySpec(secret, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// decryption pass
cipher.init(Cipher.DECRYPT_MODE, secretKey, ips);
byte[] converted = cipher.doFinal(base64TextToDecrypt);
System.out.println(new String(converted));
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Decipher error for " + textToDecrypt, e);
}
return "";
}
不幸的是,当我到达
时byte[] converted = cipher.doFinal(base64TextToDecrypt);
语句抛出以下异常:
javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
有什么想法吗?
答案 0 :(得分:7)
你应该解码字符串,而不是编码字符串的平台特定表示,就在方法的开头。
byte[] base64TextToDecrypt = Base64.decodeBase64(textToDecrypt);
或更确切地说:
byte[] bytesToDecrypt = Base64(base64TextToDecrypt);
如果您正确命名变量。
一般情况下,每次(您觉得必须)使用String.getBytes(): byte[]
方法或String(byte[])
构造函数时,您可能会做错事。您应首先考虑您要执行的操作,如果您 需要使用它,请指定character-encoding。
在您的情况下,converted
变量中的输出可能是字符编码的。所以你可以使用以下片段:
String plainText = new String(converted, Charset.forName("UTF8"));
System.out.println(plainText);
而不是你现在拥有的。
答案 1 :(得分:3)
非常感谢@owlstead,我能够找到解决方案。我错误地将Base64编码为已经Base64编码的字符串。以下是代码块。
public static String decryptText(String textToDecrypt) {
try {
byte[] decodedValue = Base64.decodeBase64(textToDecrypt.getBytes());
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ips = new IvParameterSpec(iv);
byte[] input = textToDecrypt.getBytes();
Cipher cipher = Cipher.getInstance(ENCRYPTION_METHOD);
// decryption pass
cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY, ips);
byte[] plainText = cipher.doFinal(decodedValue);
return new String(plainText);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Decipher error for " + textToDecrypt, e);
}
return "";
}
相应的加密就像这样
public static String encryptText(String textToEncrypt) {
try {
byte[] guid = "1234567890123456".getBytes("UTF-8");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ips = new IvParameterSpec(iv);
// The secret key from the server needs to be converted to byte array for encryption.
byte[] secret = ENCRYPTION_SECRET_HASH.getBytes("UTF-8");
// we generate a AES SecretKeySpec object which contains the secret key.
// SecretKeySpec secretKey = new SecretKeySpec(secret, "AES");
Cipher cipher = Cipher.getInstance(ENCRYPTION_METHOD);
cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY, ips);
byte[] cipherText = cipher.doFinal(textToEncrypt.getBytes());
byte[] base64encodedSecretData = Base64.encodeBase64(cipherText);
String secretString = new String(base64encodedSecretData);
return secretString;
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Encryption error for " + textToEncrypt, e);
}
return "";
}
答案 2 :(得分:0)
在加密和解密字符串时,请记住以下几点,
加密:
使用toByteArray(Charsets.UTF-8)将字符串转换为byteArray,并始终使用UTF-8指定字符集。
使用cipher.doFinal(byteArray)加密上述byteArray。
现在这还不够,您需要使用Base64.encode(encryptedByteArray,Base64.DEFAULT)为该加密的byteArray进行base64编码
请记住,这再次返回byteArray,如果要转换为字符串,请使用toString(Charsets.UTF-8),最重要的是再次将字符集指定为UTF-8,然后根据需要处理或存储在DB中希望。
解密:
1。获取加密的字符串,解密时的第一步是使用base64.decode(encryptedString.toByteArray(Charsets.UTF-8),Base64.DEFAULT)解码加密的字符串
现在使用cipher.dofinal(decodedByteArray)解密解码的byteArray。
使用toString(Charsets.UTF-8)将解密的byteArray转换为String。注意:始终指定字符集。这将返回原始字符串。
我知道我没有共享任何代码,但请相信我,在加密和解密字符串时,流程是重要的一部分。