大多数加密算法(包括河豚)处理二进制数据,这意味着它将接收二进制数据并拆分已由算法转换的二进制数据(使用提供的规范)。
二进制数据,如您所知,字符串数据是 !=,但是二进制数据可以表示为字符串数据(使用十六进制、base64 等)。
如果我们查看您的示例代码,我们可以看到这一行:
byte encrypted[] = cipher.doFinal(input.getBytes());
这是它一步一步做的事情:
它首先使用平台的默认字符集(不推荐,但不相关)将字符串数据转换为等效的二进制数据。
它将二进制数据(以字节数组的形式)传递给方法 doFinal()。
doFinal() 方法正在通过此行之前的语句中指定的规范(Blowfish,加密)处理此字节数组。
doFinal() 语句返回一个字节数组,该数组表示已处理(在您的情况下为加密)数据。
由于加密操作的性质,数据最初来自字符串的事实不再相关,这并不能说明数据的来源或类型。加密字节数组现在包含可能不是有效字符集编码字符串的数据。尝试使用字符集来解码字符串很可能会导致垃圾输出,因为二进制数据不再是有效的字符串。
但是,二进制数据可以通过输出实际字节的VALUE来直接表示,而不是 charset 等效映射是什么(例如,一个字节可能有 97 的值,用十六进制表示为:0x61 但通过 ASCII 解码得到字符'一个')。
考虑此代码以十六进制输出您的加密数据:
KeyGenerator keyGenerator = KeyGenerator.getInstance("Blowfish");
SecretKey secretKey = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
String input = "password";
byte encrypted[] = cipher.doFinal(input.getBytes());
StringBuilder str = new StringBuilder();
for(byte b:encrypted){
str.append(String.format("%02x", b));
}
String encData = str.toString();
System.out.println(encData);
PS:不要在没有任何参数的情况下使用 getBytes() !提供您自己的字符集,例如 UTF-8。执行以下操作:
byte encrypted[] = cipher.doFinal(input.getBytes(Charset.forName("UTF-8")));