我按如下方式创建加密密码(在Scala中,使用有弹性的城堡)
def encryptCipher(secret:SecretKeySpec, iv:IvParameterSpec):Cipher = {
val e = Cipher.getInstance("AES/GCM/NoPadding")
e.init(Cipher.ENCRYPT_MODE, secret, iv)
}
您会看到生成密钥规范的缓慢操作已得到解决。但是,为每个消息本身调用init太慢了。
我目前正在处理5万条消息,调用init方法会增加近4秒钟的时间。
有没有一种方法可以用新的IV重新初始化,而这种IV不会很费时?
在标准库中没有标准的方法可以执行此操作,但是如果您使用的是AES,则有一个很好的解决方法:
IV的目的是消除将相同的纯文本加密为相同的密文的可能性。
您可以Cipher.update(byte[])
在加密之前使用一个随机块大小的字节数组来“更新”(如中所述)(解密时使用相同的块)。这几乎与使用与IV相同的随机块完全相同。
为此,请运行此代码段(使用上面的方法来生成完全相同的密文-但这只是为了与其他平台兼容,因此无需计算特定的IV即可确保其安全。
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecureRandom secureRandom = new SecureRandom();
byte[] keyBytes = new byte[16];
secureRandom.nextBytes(keyBytes);
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
byte[] plain = new byte[256];
secureRandom.nextBytes(plain);
// first init using random IV (save it for later)
cipher.init(Cipher.ENCRYPT_MODE, key, secureRandom);
byte[] realIv = cipher.getIV();
byte[] expected = cipher.doFinal(plain);
// now init using dummy IV and encrypt with real IV prefix
IvParameterSpec nullIv = new IvParameterSpec(new byte[16]);
cipher.init(Cipher.ENCRYPT_MODE, key, nullIv);
// calculate equivalent iv
Cipher equivalentIvAsFirstBlock = Cipher.getInstance("AES/CBC/NoPadding");
equivalentIvAsFirstBlock.init(Cipher.DECRYPT_MODE, key, nullIv);
byte[] equivalentIv = equivalentIvAsFirstBlock.doFinal(realIv);
cipher.update(equivalentIv);
byte[] result = cipher.doFinal(plain);
System.out.println(Arrays.equals(expected, result));
解密部分比较容易,因为将块解密的结果与先前的密文进行XOR(请参阅块密文操作模式),您只需要在密文后面附加真实的IV,然后将其扔掉即可:
// Encrypt as before
IvParameterSpec nullIv = new IvParameterSpec(new byte[16]);
cipher.init(Cipher.DECRYPT_MODE, key, nullIv);
cipher.update(realIv);
byte[] result = cipher.doFinal(encrypted);
// result.length == plain.length + 16
// just throw away the first block
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句