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