Java AES-256加密:从我的固定字符串生成256位(32字节)的密钥
我想用AES256加密Java AES-256加密:从我的固定字符串生成256位(32字节)的密钥,java,encryption,cryptography,aes,Java,Encryption,Cryptography,Aes,我想用AES256加密文本,我想用我的电子邮件test@gmail.com作为密钥进行加密 这就是我所尝试的: String key = "test@gmail.com"; SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); byte iv[] = SOME_RANDOM_32_BYTES; IvParameterSpec ivSpec = new IvParameterSpec(iv); Ciph
文本
,我想用我的电子邮件test@gmail.com
作为密钥进行加密
这就是我所尝试的:
String key = "test@gmail.com";
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
byte iv[] = SOME_RANDOM_32_BYTES;
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] encryptedResult = cipher.doFinal(text.getBytes("UTF-8"));
当我运行上述代码时,我得到了InvalidKeyException:
java.security.InvalidKeyException: Key length not 128/192/256 bits.
我在网上查过,原因是我的密钥不是128/192/256位。我的问题是,如何从电子邮件字符串test@gmail.com
?您可以散列密钥字符串(test@gmail.com
)使用SHA256将其设置为256bit值
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(yourEmail.getBytes());
byte[] encryptionKey = md.digest();
这可能有多种原因。其中一个在下面。
通常,当您的JRE中没有更新策略时,会出现此错误。
Java默认为AES提供128,对于256,我们必须使用Java提供的新策略。您不应该烘焙自己的加密(除非您对此非常了解。)
您应该使用现有(且经过审核的)加密库
另外,您不应使用可猜测的字符串(如您的电子邮件地址)作为密码。请查看有关如何选择好密码的建议
我已经说过了,下面是更多的细节
实现基于密码的加密的正确方法是使用KDF()从密码生成加密密钥。以下是一些可用于此任务的KDF:,和
关键派生函数包括防御已知攻击的机制,如彩虹表和字典攻击,尤其是“salt”和功因子。Argon2等现代KDF还试图通过使用更适合该任务的硬件来防止攻击者获得优势
一般来说,这是如何使用的:
选择工作系数(您能承受的最大值)
使用一种特殊的方法来产生盐
使用您选择的密码、salt和功因子生成加密密钥和密钥
使用
使用生成的加密密钥加密要保护的数据
使用生成的密码计算加密消息的密码
序列化salt、功因子、计算数据和加密数据。(可选地,指示所选加密方案的标识符,如果这些标识符不固定,也应包括在内。)
加密消息是在步骤7中生成的序列化数据。如果任何一个步骤出错(这很容易),您的加密代码可能会以可怕的方式被破坏
也许现在你明白了为什么应该使用现有的库了
注意:当前的最佳实践是使用AEAD(关联数据的身份验证加密),而不是如上所述的加密然后MAC。如果您感兴趣,请查看此链接:我不打算在此讨论。可能重复@KonstantinV.Salikhov,我检查了您提供的链接,他在那里询问如何使用他的密码生成密钥,但在公认的解决方案中,我没有看到他的密码在哪里使用?@user842225关于链接,假设存在一个局部变量password
。它用于以下行:KeySpec spec=new-PBEKeySpec(密码,salt,65536256)代码>。当然,这个可能的副本假设密码是秘密的——在你的情况下,它不会是。这是一个错误的建议!正确的方法是使用密钥派生函数派生密钥。