]> WPIA git - gigi.git/blob - src/org/cacert/gigi/util/PasswordHash.java
add: implement password migration to scrypt on login.
[gigi.git] / src / org / cacert / gigi / util / PasswordHash.java
1 package org.cacert.gigi.util;
2
3 import java.security.MessageDigest;
4 import java.security.NoSuchAlgorithmException;
5
6 import com.lambdaworks.crypto.SCryptUtil;
7
8 public class PasswordHash {
9
10     /**
11      * Verifies a password hash.
12      * 
13      * @param password
14      *            The password that should result in the given hash.
15      * @param hash
16      *            The hash to verify the password against.
17      * @return <ul>
18      *         <li><code>null</code>, if the password was valid</li>
19      *         <li><code>hash</code>, if the password is valid and the hash
20      *         doesn't need to be updated</li>
21      *         <li>a new hash, if the password is valid but the hash in the
22      *         database needs to be updated.</li>
23      *         </ul>
24      */
25     public static String verifyHash(String password, String hash) {
26         if (hash.contains("$")) {
27             if (SCryptUtil.check(password, hash)) {
28                 return hash;
29             } else {
30                 return null;
31             }
32         }
33         String newhash = sha1(password);
34         boolean match = true;
35         if (newhash.length() != hash.length()) {
36             match = false;
37         }
38         for (int i = 0; i < newhash.length(); i++) {
39             match &= newhash.charAt(i) == hash.charAt(i);
40         }
41         if (match) {
42             return hash(password);
43         } else {
44             return null;
45         }
46     }
47
48     private static String sha1(String password) {
49         try {
50             MessageDigest md = MessageDigest.getInstance("SHA1");
51             byte[] digest = md.digest(password.getBytes());
52             StringBuffer res = new StringBuffer(digest.length * 2);
53             for (int i = 0; i < digest.length; i++) {
54                 res.append(Integer.toHexString((digest[i] & 0xF0) >> 4));
55                 res.append(Integer.toHexString(digest[i] & 0xF));
56             }
57             return res.toString();
58         } catch (NoSuchAlgorithmException e) {
59             throw new Error(e);
60         }
61     }
62
63     public static String hash(String password) {
64         return SCryptUtil.scrypt(password, 1 << 14, 8, 1);
65     }
66 }