我获取一个数据字符串=“ AkhilRanjanBiharabcdefghijklmnopMovedtoChennai18”,先对其进行加密,然后再对其进行解密。我返回解密的字符串是“AkhilRanjanBiharÙ†+™¸„ À–ýæó @Movedtoñhennai18”,这对于前16个字符和最后16个字符几乎没问题,但是中间的16个字符绝对是垃圾。可能出什么问题了?
我的加密代码:-
public String encrypt(String value) {
log.info("This method is not going to be used");
String key = "theabcd@heymaths";
initVector = "{{{{{{{{{{{{{{{{";
String encryptedStr="";
byte[] encrBytes =null;
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes());
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
encrBytes = cipher.doFinal(value.getBytes());
encryptedStr = new String(encrBytes);
} catch (Exception ex) {
ex.printStackTrace();
}
String strToBeEncoded = encryptedStr +"::"+initVector;
encrBytes = strToBeEncoded.getBytes();
//String encoded = Base64.encodeBase64String(encrBytes);
String encoded = Base64.getEncoder().encodeToString(encrBytes);
String urlEncoded = null;
try {
urlEncoded = java.net.URLEncoder.encode(encoded, CHARSET);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return urlEncoded;
}
解密代码:-
public String decrypt(String encrypted) {
String decryptedStr = null;
byte[] base64Bytes = null;
String urlDecoded = null;
String key = HmCommonProperty.getProperty("abcd_crypt_key");
if(key == null || key.isEmpty()) {
key = securityKey;
}
String encryptionMech = HmCommonProperty.getProperty("abcd_crypt_algo");
if(encryptionMech == null || encryptionMech.isEmpty()) {
encryptionMech = CRYPT_MECHANISM;
}
try {
//Url and Base64 decoding
urlDecoded = java.net.URLDecoder.decode(encrypted, CHARSET);
//base64Bytes = Base64.decodeBase64(urlDecoded);
base64Bytes = Base64.getDecoder().decode(urlDecoded);
//Generating IV
String str = new String(base64Bytes);
String[] bodyIVArr = str.split("::");
initVector = bodyIVArr[1];
String bodyStr = bodyIVArr[0];
//AES Decryption
Cipher cipher = Cipher.getInstance(encryptionMech);
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes());
System.out.println("initVector Length -> "
+iv.getIV().length);
System.out.println("input length -> "
+bodyStr.getBytes().length);
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] decryptedBytes = cipher.doFinal(bodyStr.getBytes());
decryptedStr = new String(decryptedBytes);
} catch (Exception ex) {
ex.printStackTrace();
log.error("Error occurred while decryption abcd data",ex);
}
return decryptedStr;
}
答案 0 :(得分:1)
您的加密数据是字节序列。如果需要将其编码为字符串,则应使用base64或旨在对任意字节数组进行编码的类似编码。假装您的任意字节数组是有效的字符串编码,即使使用ISO_8859_1
,也会造成麻烦。
替换
encryptedStr = new String(encrBytes)
使用
encryptedStr = Base64.getEncoder().encodeToString(encrBytes)
并替换
bodyStr.getBytes()
与
Base64.getDecoder().decode(bodyStr)
另请参阅:How to correctly and consistely get bytes from a string for AES encryption?
答案 1 :(得分:0)
您的错误在这里:
encryptedStr = new String(encrBytes);
strToBeEncoded.getBytes();
这些方法使用平台默认字符集,并且当您从byte[]
转换为String
并返回到byte[]
时,通常该过程有损案件。唯一不会造成损失的方法是,如果平台默认字符集为"ISO_8859_1"
。
我将11个此类呼叫全部更改为:
encryptedStr = new String(encrBytes, StandardCharsets.ISO_8859_1);
strToBeEncoded.getBytes(StandardCharsets.ISO_8859_1);
(我没有更改CHARSET
)。我现在得到的输出是:
initVector长度-> 16
输入长度-> 48
AkhilRanjanBiharabcdefghijklmnopMovedtoChennai18
奖金警告1:加密使用硬编码的"AES/CBC/NoPadding"
,但是解密是动态的(当然也应该使用"AES/CBC/NoPadding"
)。
奖金警告2:机会很小,但是"::"
很有可能出现在encrBytes
内部,从而使str.split("::");
陷入困境。一种解决方案是搜索"::"
的 last 最后出现的地方,然后仅对此进行拆分。