我想用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();
答案 0 :(得分:2)
回答你的怀疑:
- 我应该如何/在哪里存储我的密钥,即" mysecretkey_123456"?
醇>
这取决于。我所看到的似乎是密码而不是密钥。因此,建议将其存放在头脑或密码管理器中。
- 为什么需要"哈希" "(SALT2 +用户名+密码)"的组合使用SHA-1/2并将byte []数组传递给SecretKeySpec?
醇>
这是因为AES密钥恰好包含16,24或32个字节,对于攻击者来说应该是随机的。密码既不具有一致的长度,也不具有所需的随机性。
代码段的作用是创建密码散列函数或基于密码的密钥派生函数(PBKDF)。当然只是使用SHA-1不会削减它,你应该使用PBKDF2或bcrypt,scrypt或Argon2之一。然后使用高工作因子(或迭代计数)配置其中一个功能,以提供密钥加强。 PBKDF2 - 尽管不是最好的 - 是Java运行时环境的一部分,使其部署起来相对容易。
如果你的"明文密钥"名为my_custom_secret_key
已经具有128位或更多的强度,那么您可以使用基于密钥的密钥派生函数,例如HKDF。
- 为什么我不能将明文密钥发送为byte []?
醇>
谁说你不能?代码示例似乎弄错了密钥和密码,所以我认为混淆来自哪里。您通常会使用字节作为高熵密钥。
建议使用char[]
的密码;这是因为在您使用它来验证密码或导出密钥后,您无法销毁String
的内容。另一方面,char[]
可以通过在使用后直接填充零来清除。这同样适用于存储在byte[]
中的密钥。
- 我正在努力确保"键"是动态的,因此它基于salt + username + my_custom_secret_key,因此相同的加密字符串将具有不同的输出。
醇>
只要盐很大且足够随机,只要每次加密需要一个盐就会重新生成16个字节SecureRandom
,这将会起作用。
这样生成的密钥将始终足够随机,并且在使用安全模式时(即,使用Java 但 ECB中的任何模式构建,最好是像GCM模式加密一样),加密将是安全的。 / p>