PBKDF2(Password-BasedKeyDerivationFunction)PBKDF2简单而言就是将saltedhash进行多次重复计算,这个次数是可选择的。如果计算一次所需要的时间是1微秒,那么计算1百万次就需要1秒钟。假如攻击一个密码所需的rainbowtable1千万条,建立所对应的rainbowtable所需要的时间就是115天。这个代价足以让大部分的攻击者忘而生畏。

Java代码:

public static void main(String[] args) throws NoSuchAlgorithmException,
InvalidKeySpecException {
String originalPassword = "password";
String generatedSecuredPasswordHash = generateStorngPasswordHash(originalPassword);
System.out.println(generatedSecuredPasswordHash);
boolean matched = validatePassword("password",
generatedSecuredPasswordHash);
System.out.println(matched);
matched = validatePassword("password1", generatedSecuredPasswordHash);
System.out.println(matched);
}

/**
* 说明 :判断加密数据与原始数据是否一致
*/
private static boolean validatePassword(String originalPassword,
String storedPassword) throws NoSuchAlgorithmException,
InvalidKeySpecException {
String[] parts = storedPassword.split(":");
int iterations = Integer.parseInt(parts[0]);
byte[] salt = toByte(parts[1]);
byte[] hash = toByte(parts[2]);
PBEKeySpec spec = new PBEKeySpec(originalPassword.toCharArray(), salt,
iterations, hash.length * 8);
SecretKeyFactory skf = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
byte[] testHash = skf.generateSecret(spec).getEncoded();
int diff = hash.length ^ testHash.length;
for (int i = 0; i < hash.length && i < testHash.length; i++) {
diff |= hash[i] ^ testHash[i];
}
return diff == 0;
}

/**
* 说明 :16进制字符串转byte数组
*/
public static byte[] toByte(String hexString) {
hexString = hexString.replaceAll(" ", "");
int len = hexString.length() / 2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
16).byteValue();
return result;
}

/**
*
* 说明 :PBKDF2WithHmacSHA1加盐加密
*
*/
private static String generateStorngPasswordHash(String password)
throws NoSuchAlgorithmException, InvalidKeySpecException {
int iterations = 1000;
char[] chars = password.toCharArray();
byte[] salt = getSalt().getBytes();
PBEKeySpec spec = new PBEKeySpec(chars, salt, iterations, 12 * 8);
SecretKeyFactory skf = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = skf.generateSecret(spec).getEncoded();
return iterations + ":" + bytes2Hex(salt) + ":" + bytes2Hex(hash);
}

/**
* 说明 :生成随机盐
*/
private static String getSalt() throws NoSuchAlgorithmException {
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
byte[] salt = new byte[16];
sr.nextBytes(salt);
return salt.toString();
}

/**
* 说明 :byte数组转换为16进制字符串
*/
public static String bytes2Hex(byte[] bts) {
String des = "";
String tmp = null;
for (int i = 0; i < bts.length; i++) {
tmp = (Integer.toHexString(bts[i] & 0xFF));
if (tmp.length() == 1) {
des += "0";
}
des += tmp;
}
return des;
}

更多相关文章

  1. Android 在资源文件(res/strings.xml)定义一维数组,间接定义二维数
  2. android 检测字符串是否为合法域名
  3. Android 字符串资源
  4. 网路搜集:java整型数与网络字节序的 byte[] 数组转换关系
  5. JavaScript unshift()函数移入数据到数组第一位
  6. java数组和c中数组的区别
  7. 算法 - 给出一个字符串str,输出包含两个字符串str的最短字符串,如
  8. java中 16进制字符串 与普通字符串 与 byte数组 之间的转化
  9. Java 数组练习题(1)

随机推荐

  1. Android(安卓)TextView 支持的HTML标签
  2. Android Security
  3. Android APK 扩展文件
  4. Android ViewPager使用详解
  5. Android 5.0(L) 的MediaSession架构分析(
  6. android通知栏提示
  7. Android 获取Sim卡联系人
  8. Android改变MAC地址
  9. Stuff about Android
  10. Android 自动更新代码