【问题标题】:How to perform AES encryption with custom secret key stored in keystore?如何使用存储在密钥库中的自定义密钥执行 AES 加密?
【发布时间】:2017-10-27 13:59:09
【问题描述】:

我想使用 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();
  1. 我应该如何/在哪里存储我的密钥,即“mysecretkey_123456”
  2. 为什么需要使用 SHA-1/2 对“(SALT2 + 用户名 + 密码)”的组合进行“散列”并将 byte[] 数组传递给 SecretKeySpec?
  3. 为什么我不能将明文密钥作为 byte[] 发送?
  4. 我正在尝试确保“密钥”是动态的,以便它基于 salt+username+my_custom_secret_key,以便相同的加密字符串具有不同的输出。

Java AES and using my own Key

https://www.securecoding.cert.org/confluence/display/java/MSC61-J.+Do+not+use+insecure+or+weak+cryptographic+algorithms

How to generate SALT value in Java?

【问题讨论】:

    标签: java encryption cryptography


    【解决方案1】:

    解答你的疑惑:

    1. 我应该如何/在哪里存储我的密钥,即“mysecretkey_123456”?

    这取决于。我正在查看的似乎是密码而不是密钥。因此,建议将其存储在您的头脑中或密码管理器中。

    1. 为什么需要使用 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。

    1. 为什么我不能将明文密钥作为 byte[] 发送?

    谁说你不能?代码示例似乎弄错了密钥和密码,所以我认为这就是混乱的来源。您通常会使用字节作为高熵密钥。

    对于密码,建议使用char[];这是因为在您使用String 验证密码或派生密钥之后,您无法销毁它的内容。另一方面,char[] 可以在使用后直接用零填充来清除。当然,这同样适用于存储在 byte[] 中的密钥。

    1. 我正在尝试确保“密钥”是动态的,以便它基于 salt+username+my_custom_secret_key,以便相同的加密字符串具有不同的输出。

    只要盐足够大且足够随机,这将起作用,例如每次需要盐进行加密时都会重新生成 16 个字节 SecureRandom

    这样生成的密钥将始终足够随机,并且在使用安全模式时您的加密将是安全的(即在 Java ECB 中构建的任何模式,最好是 GCM 模式加密之类的)。

    【讨论】:

    • 我想在 2 个 java 程序之间共享我所谓的 AES“自定义密码”,以便我们可以使用相同的密钥来加密和解密数据。出于安全原因,如何保护/存储我的“自定义密码”?
    • 我想使用“密码”而不是密钥的原因是因为我希望每次使用都会更改密文。即基于每次服务器启动,或每个用户的会话,或每个用户的事务。
    • 在系统密钥存储区、拇指驱动器上、受保护帐户上,在启动期间将其输入到加密的配置文件中。在这里要讨论完整的密钥管理有点多。当您需要完全自主的应用程序时,您可能只能混淆密码。最后,您需要将其存储在某个地方并再次对其进行加密会导致鸡蛋问题。
    • 你用盐来做这个。不同的盐,不同的派生密钥。
    • 在这种情况下,我应该将(SALT2 + 用户名 + 密码)还是散列(SALT2 + 用户名 + 密码)作为 byte[] 数组发送到 SecretKeySpec,为什么?哪种方法更好?
    猜你喜欢
    • 1970-01-01
    • 2011-01-03
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-13
    • 1970-01-01
    相关资源
    最近更新 更多