使用 Jasypt 使用 PBKDF2WithHmacSHA1 密钥进行基于密码的 AES 加密

Using Jasypt for password based AES encryption with PBKDF2WithHmacSHA1 key

我工作的地方正在实现加密机制,安全小哥的诉求如下:

  1. 使用 PBKDF2WithHmacSHA512、秘密密码、256 位盐和最少 20000 次迭代创建一个 256 位密钥。
  2. 应使用 SecureRandom.getInstance("SHA1PRNG");
  3. 生成盐
  4. 使用派生密钥使用 AES256 加密。

我正在尝试使用 Jasypt 的 StandardPBEStringEncryptor class

encryptor.setPassword(PASSWORD);
encryptor.setAlgorithm("AES/CBC/PKCS5Padding");
encryptor.setKeyObtentionIterations(20000);
encryptor.setSaltGenerator(new RandomSaltGenerator());
encryptor.encrypt("something");

执行此操作时出现以下异常:

java.security.NoSuchAlgorithmException: AES/CBC/PKCS5Padding SecretKeyFactory not available

我是否错误地使用了 Jasypt?我在这里错过了什么?

谢谢

我最终联系了 Jasypt 的首席程序员 Daniel Fernández,他的回答是:

I’m afraid Jasypt does not offer a way to specify different algorithms for the SecretKeyFactory and the instantiation of the Cipher itself. Sorry.

我使用了这段 java 代码(没有 Jasypt):

public String encrypt(final String message) {
  final byte[] salt = generateSalt();
  final Key key = createKey(salt);

  final Cipher encryptingCipher = createCipher(Cipher.ENCRYPT_MODE, key, salt);
  final byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
  final byte[] encryptedBytes = doFinal(encryptingCipher, messageBytes);
  final byte[] data = ArrayUtils.addAll(salt, encryptedBytes);
  return BaseEncoding.base64().encode(data);
}

private byte[] generateSalt() {
  final SecureRandom secureRandom = new SecureRandom();
  final byte[] salt = new byte[SALT_LENGTH];
  secureRandom.nextBytes(salt);
  return salt;
}

private Key createKey(final byte[] salt) {
  final PBEKeySpec spec = new PBEKeySpec(PASSWORD,
                                       salt,
                                       ITERATIONS,
                                       KEY_LENGTH);
  final SecretKey secretKey;
  try {
    secretKey = keyFactory.generateSecret(spec);
  } catch (final InvalidKeySpecException e) {
    throw new RuntimeException("Error creating SecretKey", e);
  }
  final SecretKeySpec result = new SecretKeySpec(secretKey.getEncoded(), ALGORITHM);
  spec.clearPassword();
  return result;
}