类名称:PBKDF2 修改备注: 1.当增加一个用户的时候,调用generateSalt()生成盐,然后调用getEncryptedPassword(),同时存储盐和密文。 再次强调,不要存储明文密码,不要存储明文密码,因为没必要!不要担心将盐和密文存储在同一张表中,上面已经说过了,这个无关紧要。 2.当认证用户的时候,从数据库中取出盐和密文,将他们和明文密码同时传给authenticate(),根据返回结果判断是否认证成功。 3.当用户修改密码的时候,仍然可以使用原来的盐,只需要调用getEncryptedPassword()方法重新生成密文就可以了。 @a
| 24 | * @author SeanDragon |
| 25 | */ |
| 26 | public final class ToolPbkdf2 { |
| 27 | private ToolPbkdf2() { |
| 28 | throw new UnsupportedOperationException("我是工具类,别初始化我。。。"); |
| 29 | } |
| 30 | |
| 31 | public static boolean authenticate(String attemptedPassword, byte[] encryptedPassword, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { |
| 32 | // Encrypt the clear-text password using the same salt that was used to |
| 33 | // encrypt the original password |
| 34 | byte[] encryptedAttemptedPassword = getEncryptedPassword(attemptedPassword, salt); |
| 35 | |
| 36 | // Authentication succeeds if encrypted password that the user entered |
| 37 | // is equal to the stored hash |
| 38 | return Arrays.equals(encryptedPassword, encryptedAttemptedPassword); |
| 39 | } |
| 40 | |
| 41 | public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { |
| 42 | |
| 43 | // PBKDF2 with SHA-1 as the hashing algorithm. Note that the NIST |
| 44 | // specifically names SHA-1 as an acceptable hashing algorithm for |
| 45 | // PBKDF2 |
| 46 | |
| 47 | String algorithm = "PBKDF2WithHmacSHA1"; |
| 48 | |
| 49 | // SHA-1 generates 160 bit hashes, so that's what makes sense here |
| 50 | |
| 51 | int derivedKeyLength = 160; |
| 52 | |
| 53 | // Pick an iteration count that works for you. The NIST recommends at |
| 54 | |
| 55 | // least 1,000 iterations: |
| 56 | |
| 57 | // http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf |
| 58 | |
| 59 | // iOS 4.x reportedly uses 10,000: |
| 60 | |
| 61 | // http://blog.crackpassword.com/2010/09/smartphone-forensics-cracking-blackberry-backup-passwords/ |
| 62 | |
| 63 | int iterations = 20000; |
| 64 | |
| 65 | KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, derivedKeyLength); |
| 66 | |
| 67 | SecretKeyFactory f = SecretKeyFactory.getInstance(algorithm); |
| 68 | |
| 69 | return f.generateSecret(spec).getEncoded(); |
| 70 | } |
| 71 | |
| 72 | public static byte[] generateSalt() throws NoSuchAlgorithmException { |
| 73 | // VERY important to use SecureRandom instead of just Random |
| 74 | SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); |
| 75 | // Generate a 8 byte (64 bit) salt as recommended by RSA PKCS5 |
| 76 | byte[] salt = new byte[8]; |
| 77 | random.nextBytes(salt); |
| 78 | return salt; |
| 79 | } |
| 80 | |
| 81 | } |
nothing calls this directly
no outgoing calls
no test coverage detected