我想用 AES 加密实现一个自定义密钥,我找到了以下实现和有关这样做的详细信息。 .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
byte[] key = (SALT2 + username + my_custom_secret_key).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
但我有以下疑问:
byte[] my_key = (SALT2 + username + my_custom_secret_key).getBytes("UTF-8");
SecretKeySpec secretKeySpec = new SecretKeySpec(my_key, "AES");
如果我要使用典型的示例代码,例如:
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey secretKey = keyGen.generateKey();
解答你的疑惑:
- 我应该如何/在哪里存储我的密钥,即“mysecretkey_123456”?
那要看。我在看的似乎是密码而不是密钥。因此,建议将其存储在您的头脑中或密码管理器中。
- 为什么需要使用 SHA-1/2 对“(SALT2 + 用户名 + 密码)”的组合进行“散列”并将 byte[] 数组传递给 SecretKeySpec?
这是因为 AES 密钥正好由 16、24 或 32 个字节组成,对于攻击者来说应该是随机的。密码既没有一致的长度,也没有所需的随机性。
代码段的作用是创建密码散列函数或基于密码的密钥派生函数 (PBKDF)。当然,仅使用 SHA-1 并不能解决问题,您应该使用 PBKDF2 或 bcrypt、scrypt 或 Argon2 之一。然后使用高工作因子(或迭代计数)配置这些功能之一以提供关键强化。PBKDF2 - 尽管不是最强大的 - 是 Java 运行时环境的一部分,使其相对容易部署。
如果您调用的“明文密钥”my_custom_secret_key
已经具有128 位或更多的强度,那么您可以使用基于密钥的密钥派生函数,例如 HKDF。
- 为什么我不能将明文密钥作为 byte[] 发送?
谁说你不能?代码示例似乎弄错了密钥和密码,所以我认为这就是混淆的来源。您通常会使用字节作为高熵密钥。
char[]
建议使用密码;这是因为String
在使用a来验证密码或派生密钥后,您无法销毁 a 的内容。char[]
另一方面,可以通过在使用后直接用零填充来清除A。这byte[]
当然适用于存储在 a 中的密钥。
- 我试图确保“密钥”是动态的,以便它基于 salt+username+my_custom_secret_key,这样相同的加密字符串就会有不同的输出。
只要盐足够大且足够随机,这就会起作用,例如SecureRandom
每次需要盐进行加密时都会重新生成16 个字节。
这样,生成的密钥将始终足够随机,并且在使用安全模式时您的加密将是安全的(即在 Java 中构建的任何模式但ECB,最好是 GCM 模式加密之类的)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句