Java 如何使用存储在密钥库中的自定义密钥执行AES加密?

Java 如何使用存储在密钥库中的自定义密钥执行AES加密?,java,encryption,cryptography,Java,Encryption,Cryptography,我想用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 Secret

我想用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
  • 为什么不能将明文密钥作为字节[]发送
  • 我试图确保“密钥”是动态的,因此它基于salt+用户名+我的自定义密钥,这样相同的加密字符串将有不同的输出

  • 解答您的疑问:

  • 我应该如何/在哪里存储我的密钥,即“mysecretkey_123456”
  • 那要看情况。我看到的似乎是密码而不是钥匙。因此,建议将其存储在您的大脑或密码管理器中

  • 为什么需要使用SHA-1/2对“(SALT2+用户名+密码)”的组合进行“散列”,并将byte[]数组传递给SecretKeySpec 这是因为AES密钥正好由16、24或32个字节组成,攻击者应将这些字节视为随机字节。密码既没有一致的长度,也没有所需的随机性

    代码段所做的是创建密码散列函数或基于密码的密钥派生函数(PBKDF)。当然,仅仅使用SHA-1并不能解决这个问题,您应该使用PBKDF2或bcrypt、scrypt或Argon2中的一种。然后配置其中一个具有高工作系数(或迭代次数)的函数,以提供关键增强。PBKDF2——虽然不是最好的——是Java运行时环境的一部分,使其相对容易部署

    如果称为
    my\u custom\u secret\u key
    的“明文密钥”已具有128位或更高的强度,则可以使用基于密钥的密钥派生函数,如HKDF

  • 为什么不能将明文密钥作为字节[]发送
  • 谁说你不能?代码示例似乎弄错了密钥和密码,所以我认为这就是混淆的原因。通常使用字节作为高熵密钥

    对于密码,建议使用
    char[]
    ;这是因为在使用
    字符串验证密码或导出密钥后,无法销毁该字符串的内容。另一方面,
    char[]
    可以在使用后直接用零填充来清除。当然,这同样适用于存储在
    字节[]中的键

  • 我试图确保“密钥”是动态的,因此它基于salt+用户名+我的自定义密钥,这样相同的加密字符串将有不同的输出
  • 只要salt足够大且足够随机,即每次加密需要salt时都会重新生成16字节
    SecureRandom


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

    解答您的疑问:

  • 我应该如何/在哪里存储我的密钥,即“mysecretkey_123456”
  • 那要看情况。我看到的似乎是密码而不是钥匙。因此,建议将其存储在您的大脑或密码管理器中

  • 为什么需要使用SHA-1/2对“(SALT2+用户名+密码)”的组合进行“散列”,并将byte[]数组传递给SecretKeySpec 这是因为AES密钥正好由16、24或32个字节组成,攻击者应将这些字节视为随机字节。密码既没有一致的长度,也没有所需的随机性

    代码段所做的是创建密码散列函数或基于密码的密钥派生函数(PBKDF)。当然,仅仅使用SHA-1并不能解决这个问题,您应该使用PBKDF2或bcrypt、scrypt或Argon2中的一种。然后配置其中一个具有高工作系数(或迭代次数)的函数,以提供关键增强。PBKDF2——虽然不是最好的——是Java运行时环境的一部分,使其相对容易部署

    如果称为
    my\u custom\u secret\u key
    的“明文密钥”已具有128位或更高的强度,则可以使用基于密钥的密钥派生函数,如HKDF

  • 为什么不能将明文密钥作为字节[]发送
  • 谁说你不能?代码示例似乎弄错了密钥和密码,所以我认为这就是混淆的原因。通常使用字节作为高熵密钥

    对于密码,建议使用
    char[]
    ;这是因为在使用
    字符串验证密码或导出密钥后,无法销毁该字符串的内容。另一方面,
    char[]
    可以在使用后直接用零填充来清除。当然,这同样适用于存储在
    字节[]中的键

  • 我试图确保“密钥”是动态的,因此它基于salt+用户名+我的自定义密钥,这样相同的加密字符串将有不同的输出
  • 只要salt足够大且足够随机,即每次加密需要salt时都会重新生成16字节
    SecureRandom


    这样,生成的密钥将始终是随机的,并且在使用安全模式时,您的加密将是安全的(即,除ECB之外的任何Java内置模式,最好是类似GCM模式加密的模式)。

    我想在两个Java程序之间共享我所谓的AES“自定义密码”,以便我们可以使用相同的密钥加密和解密数据。出于安全原因,我如何保护/存储我的“自定义密码”?我之所以想使用“密码”而不是密钥,是因为我