org.apache.commons.codec.digest.Crypt 导致 Invalid salt value 异常

org.apache.commons.codec.digest.Crypt leads to Invalid salt value exception

以下代码随机但并非总是在一台计算机上导致 java.lang.IllegalArgumentException,而不是用于测试的其他计算机。异常的原因是 Invalid salt value: $+E3Vebci/+lhkquntg==。使用 SHA512 ($) 调用 Crypt.crypt() 时。我可以看到地穴有一个模式来检查有效盐:“^\$([56])\$(rounds=(\d+)\$)?([\.\/a-zA-Z0-9]{1,16}).*“.

JDK是openjdk 15.0.1 2020-10-20,commons-codec是1.15版本。

我只是想知道为什么这种情况随机发生在一台 Windows 10 计算机上而不是另一台计算机上(M1 上的 macOS Big Sur)。然后我应该以不同的方式创建盐以避免出现此异常吗?从网上搜索时没有找到类似的东西。

byte bytes[] = new byte[13]; 
secureRandom.nextBytes(bytes); // java.security.SecureRandom
String saltBytes = new String(Base64.getEncoder().encode(bytes));
String salt = "$" + saltBytes;
String hashedPassword = Crypt.crypt(user.getPassword(), salt);

堆栈跟踪在第 181 行 org.apache.commons.codec.digest.Sha2Crypt.sha2Crypt 结束。

PC 是 MateBook D Intel Core i7-855OU,Windows 10 Home v 1909 build 18363.1379

来自 crypto(String key, String salt)

的文档

The exact algorithm depends on the format of the salt string:

  • SHA-512 salts start with $ and are up to 16 chars long.
    ...
    The rest of the salt string is drawn from the set [a-zA-Z0-9./] and is cut at the maximum length of if a "$" sign is encountered.
    ...
    Throws:
    IllegalArgumentException - if the salt does not match the allowed pattern

由于 Base64 编码的字符串可能包含正则表达式中不允许的“=”、“+”[a-zA-Z0-9./],当生成的某些无效字符出现时,您会随机看到错误 salt .

解决方案:

  1. 只需使用 crypto(String key) 即可,因为它已经提供了随机盐。
  2. 或者按照允许的模式生成盐。

参考:
rfc4648 - Table 1: The Base 64 Alphabet