我正在尝试用Java进行AES加密。我有以下功能:
public static String encrypt(String plainText, String key) throws Exception {
if (plainText == null || plainText.length() == 0) {
return plainText;
}
// get aes key
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
// encrypt
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] bytes = cipher.doFinal(plainText.getBytes("UTF-8"));
//encode
String encoded = Base64.encodeToString(bytes, Base64.NO_PADDING | Base64.NO_WRAP);
return encoded;
}
我的目标是能够每次使用给定键以相同的方式加密某些文本。也就是说,如果我多次使用相同的两个参数调用此函数,我希望每次调用都返回相同的字符串。我会提前说,我知道密码学不应该如何完成,但我的项目需要这个功能。
不幸的是,事实并非如此。第7行中生成的密钥似乎每次都以不同方式加密我的字符串。我假设在这个库的较低层发生了某种额外的随机自动腌制,阻止了我实现目标。
有没有人在Java中知道如何每次使用给定键将给定字符串加密到相同的值?感谢。
更新/澄清:这不是为了安全。这是为了加密数据,以便对可能与处理应用程序本身有关的某些人进行模糊处理。该信息不是高度敏感,但我确实希望它被加密,然后由相同的密钥解密。我和其他人一起使用各种语言的图书馆,例如Ruby及其库允许它们每次以相同的方式使用给定键加密值。我们都希望使用相同加密算法的相同参数:密钥长度:128位 经营方式:CBC 初始化向量:无(全零)
如果没有设置初始化向量,它可能是随机分配的吗?我必须检查一下。
答案 0 :(得分:1)
是的,Java - 或者更确切地说是在CBC模式实现中提供AES的安全提供程序 - 可能默认为随机IV(之后必须检索并包含密文),如果您没有明确指定它安全的,随机的密文。
如果你想使用零IV,你必须明确指定它:
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]);
这比ECB模式稍微安全一些,因为初始密文块中不同消息中的任何重复都会立即被攻击者看到。
如果您想要一个没有随机IV的更安全模式 - 这是CBC模式获得CPA安全性所必需的 - 那么您可以检查合成IV(SIV)模式或GCM-SIV。对于这些模式,整个消息需要与前一个消息相同才能将信息泄露给攻击者。但速度较慢,不包含在标准VM中,密文可能比AES / CBC大(包含IV /标签与填充要求)。