pbkdf2 java_PBKDF2加密的实现

packagecom.founder.mrp.util;/** Password Hashing With PBKDF2 (http://crackstation.net/hashing-security.htm).

* Copyright (c) 2013, Taylor Hornby

* All rights reserved.

*

* Redistribution and use in source and binary forms, with or without

* modification, are permitted provided that the following conditions are met:

*

* 1. Redistributions of source code must retain the above copyright notice,

* this list of conditions and the following disclaimer.

*

* 2. Redistributions in binary form must reproduce the above copyright notice,

* this list of conditions and the following disclaimer in the documentation

* and/or other materials provided with the distribution.

*

* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE

* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

* POSSIBILITY OF SUCH DAMAGE.*/

importjava.math.BigInteger;importjava.security.NoSuchAlgorithmException;importjava.security.SecureRandom;importjava.security.spec.InvalidKeySpecException;importjavax.crypto.SecretKeyFactory;importjavax.crypto.spec.PBEKeySpec;/** PBKDF2 salted password hashing.

* Author: havoc AT defuse.ca

* www:http://crackstation.net/hashing-security.htm

*/

public classPasswordHash

{public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";//The following constants may be changed without breaking existing hashes.

public static final int SALT_BYTE_SIZE = 24;public static final int HASH_BYTE_SIZE = 24;public static final int PBKDF2_ITERATIONS = 1000;public static final int ITERATION_INDEX = 0;public static final int SALT_INDEX = 1;public static final int PBKDF2_INDEX = 2;/*** Returns a salted PBKDF2 hash of the password.

*

*@parampassword the password to hash

*@returna salted PBKDF2 hash of the password*/

public staticString createHash(String password)throwsNoSuchAlgorithmException, InvalidKeySpecException

{returncreateHash(password.toCharArray());

}/*** Returns a salted PBKDF2 hash of the password.

*

*@parampassword the password to hash

*@returna salted PBKDF2 hash of the password*/

public static String createHash(char[] password)throwsNoSuchAlgorithmException, InvalidKeySpecException

{//Generate a random salt

SecureRandom random = newSecureRandom();byte[] salt = new byte[SALT_BYTE_SIZE];

random.nextBytes(salt);//Hash the password

byte[] hash =pbkdf2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);//format iterations:salt:hash

return PBKDF2_ITERATIONS + ":" + toHex(salt) + ":" +toHex(hash);

}/*** Validates a password using a hash.

*

*@parampassword the password to check

*@paramcorrectHash the hash of the valid password

*@returntrue if the password is correct, false if not*/

public static booleanvalidatePassword(String password, String correctHash)throwsNoSuchAlgorithmException, InvalidKeySpecException

{returnvalidatePassword(password.toCharArray(), correctHash);

}/*** Validates a password using a hash.

*

*@parampassword the password to check

*@paramcorrectHash the hash of the valid password

*@returntrue if the password is correct, false if not*/

public static boolean validatePassword(char[] password, String correctHash)throwsNoSuchAlgorithmException, InvalidKeySpecException

{//Decode the hash into its parameters

String[] params = correctHash.split(":");int iterations =Integer.parseInt(params[ITERATION_INDEX]);byte[] salt =fromHex(params[SALT_INDEX]);byte[] hash =fromHex(params[PBKDF2_INDEX]);//Compute the hash of the provided password, using the same salt,//iteration count, and hash length

byte[] testHash =pbkdf2(password, salt, iterations, hash.length);//Compare the hashes in constant time. The password is correct if//both hashes match.

returnslowEquals(hash, testHash);

}/*** Compares two byte arrays in length-constant time. This comparison method

* is used so that password hashes cannot be extracted from an on-line

* system using a timing attack and then attacked off-line.

*

*@parama the first byte array

*@paramb the second byte array

*@returntrue if both byte arrays are the same, false if not*/

private static boolean slowEquals(byte[] a, byte[] b)

{int diff = a.length ^b.length;for(int i = 0; i < a.length && i < b.length; i++)

diff|= a[i] ^b[i];return diff == 0;

}/*** Computes the PBKDF2 hash of a password.

*

*@parampassword the password to hash.

*@paramsalt the salt

*@paramiterations the iteration count (slowness factor)

*@parambytes the length of the hash to compute in bytes

*@returnthe PBDKF2 hash of the password*/

private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, intbytes)throwsNoSuchAlgorithmException, InvalidKeySpecException

{

PBEKeySpec spec= new PBEKeySpec(password, salt, iterations, bytes * 8);

SecretKeyFactory skf=SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);returnskf.generateSecret(spec).getEncoded();

}/*** Converts a string of hexadecimal characters into a byte array.

*

*@paramhex the hex string

*@returnthe hex string decoded into a byte array*/

private static byte[] fromHex(String hex)

{byte[] binary = new byte[hex.length() / 2];for(int i = 0; i < binary.length; i++)

{

binary[i]= (byte)Integer.parseInt(hex.substring(2*i, 2*i+2), 16);

}returnbinary;

}/*** Converts a byte array into a hexadecimal string.

*

*@paramarray the byte array to convert

*@returna length*2 character string encoding the byte array*/

private static String toHex(byte[] array)

{

BigInteger bi= new BigInteger(1, array);

String hex= bi.toString(16);int paddingLength = (array.length * 2) -hex.length();if(paddingLength > 0)return String.format("%0" + paddingLength + "d", 0) +hex;else

returnhex;

}/*** Tests the basic functionality of the PasswordHash class

*

*@paramargs ignored*/

public static voidmain(String[] args)

{try{//Print out 10 hashes

for(int i = 0; i < 10; i++)

System.out.println(PasswordHash.createHash("123"));//Test password validation

boolean failure = false;

System.out.println("Running tests...");for(int i = 0; i < 100; i++)

{

String password= ""+i;

String hash=createHash(password);

String secondHash=createHash(password);if(hash.equals(secondHash)) {

System.out.println("FAILURE: TWO HASHES ARE EQUAL!");

failure= true;

}

String wrongPassword= ""+(i+1);if(validatePassword(wrongPassword, hash)) {

System.out.println("FAILURE: WRONG PASSWORD ACCEPTED!");

failure= true;

}if(!validatePassword(password, hash)) {

System.out.println("FAILURE: GOOD PASSWORD NOT ACCEPTED!");

failure= true;

}

}if(failure)

System.out.println("TESTS FAILED!");elseSystem.out.println("TESTS PASSED!");

}catch(Exception ex)

{

System.out.println("ERROR: " +ex);

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值