解决方案如下:
// 指定一个自定义的 Provider
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1", new PBEProvider());
// PBEProvider
public class PBEProvider extends Provider {
public PBEProvider() {
super("PBEProvider", 1.0, "MyProvider v1.0: Custom SecretKeyFactorySpi Implementation");
put("SecretKeyFactory.PBKDF2WithHmacSHA1", PBESecretKeyFactorySpi.class.getName());
}
}
// PBESecretKeyFactorySpi
public class PBESecretKeyFactorySpi extends SecretKeyFactorySpi {
String prfAlgo = "HmacSHA1";
@
Override protected SecretKey engineGenerateSecret(KeySpec spec) throws InvalidKeySpecException {
if (spec instanceof PBEKeySpec pksp) {
return new PBKDF2KeyImpl(pksp, this.prfAlgo);
} else {
throw new InvalidKeySpecException("Unsupported KeySpec");
}
}
// ...省略其他方法
}
// 自己实现一个 PBKDF2KeyImpl
// 重写 getPasswdBytes 方法
// 将每个 byte 直接转成 char 传入,然后再强转还原 byte[]即可
private static byte[] getPasswordBytes(char[] passwd) {
byte[] result = new byte[passwd.length];
for (int i = 0; i < passwd.length; i++) {
result[i] = (byte) passwd[i];
}
return result;
}
其中遇到一个问题,JDK 的 PBKDF2KeyImpl 里面有 CleanFactory ,搜了下好像是清理用的,我没处理这个直接注释了。