目录
PBKDF2
输入参数
输出参数
Java实现
测试结果
使用随机的salt
使用固定的salt
PBKDF2
PBKDF2 (Password-Based Key Derivation Function 2),基于口令的密钥派生函数,可以防止字典攻击和彩虹表攻击。使用用户持有的、不需要保存的秘密,比如口令,来推导对称密钥(消息的发送方和接收方持有相同的秘密,使用同样的算法来推导对称密钥)。
key = generateKey(String algorithm, char[] password, byte[] salt, int iterationCount, int keyLength)
输入参数
algorithm: 算法名,比如: PBKDF2WithHmacSHA256
password: 口令,字节数组/字符串
salt:盐,安全生成的随机字节,推荐长度为128位
iterationCount:迭代次数
keyLength:派生密钥长度
注意:生成密钥所使用的类为javax.crypto.SecretKeyFactory(私密密钥工厂类)。可以通过指定以下的算法来请求SecretKeyFactory实例.
输出参数
根据请求长度派生的密钥,如32字节(256位)的密钥。
Java实现
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
public class PBKDF2Test {
//字节数组转换成十六进制字符串
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static byte[] generateKey(String algorithm, char[] password, byte[] salt, int iterationCount, int keyLength)
throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec keySpec = new PBEKeySpec(password, salt, iterationCount, keyLength);
SecretKeyFactory factory = SecretKeyFactory.getInstance(algorithm);
byte[] key = factory.generateSecret(keySpec).getEncoded();
return key;
}
public static void main(String[] args) {
String algorithm = "PBKDF2WithHmacSHA256";
SecureRandom sRandom = new SecureRandom();
byte[] salt = new byte[16];
sRandom.nextBytes(salt);
String pwdText = "password1";
int iterationCount = 50000;
int keyLength = 256;
try {
byte[] hash = PBKDF2Test.generateKey(algorithm,password.toCharArray(), salt, iterationCount, keyLength);
System.out.println("hash字节数组长度: " +hash.length);
System.out.println("Hex字符串输出: "+ bytesToHex(hash));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
}
}
其中,algorithm使用的是PBKDF2WithHmacSHA256
String algorithm = "PBKDF2WithHmacSHA256";
salt是使用强随机数生成器生成的长度为16的字节数组
SecureRandom sRandom = new SecureRandom();
byte[] salt = new byte[16];
sRandom.nextBytes(salt);
如果想基于指定的16进制字符串来生成salt,需要使用 hexToByte(String hex) 函数来做转换:
public static byte[] hexToByte(String hex){
int m = 0, n = 0;
int byteLen = hex.length() / 2;
byte[] ret = new byte[byteLen];
for (int i = 0; i < byteLen; i++) {
m = i * 2 + 1;
n = m + 1;
int intVal = Integer.decode("0x" + hex.substring(i * 2, m) + hex.substring(m, n));
ret[i] = Byte.valueOf((byte)intVal);
}
return ret;
}
byte[] salt = hexToByte("aaef2d3f4d77ac66e9c5a6c3d8f921d1");
iterationCount,设置迭代次数为50000:
int iterationCount = 50000;
keyLength,设置派生密钥长度为32字节/256位:
int keyLength = 256;
调用generateKey函数,返回得到字节数组,并将其转换成hex16进制字符串:
bytesToHex(hash)
测试结果
使用随机的salt
salt值是使用强随机数生成器生成的,每次计算派生的密钥是不一样的。
第一次
第二次
使用固定的salt
salt值是基于hex字符串生成的,每次计算派生的密钥是一样的。
第一次和第二次文章来源:https://www.toymoban.com/news/detail-611430.html
文章来源地址https://www.toymoban.com/news/detail-611430.html
到了这里,关于PBKDF2算法Java实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!