SSD added
[staff/due1/sed-hs15-srs-purple.git] / src / main / java / ch / bfh / ti / srs / extern / Password.java
1 package ch.bfh.ti.srs.extern;
2
3 import javax.crypto.SecretKey;
4 import javax.crypto.SecretKeyFactory;
5 import javax.crypto.spec.PBEKeySpec;
6 import java.security.SecureRandom;
7 import org.apache.commons.codec.binary.Base64;
8
9 public class Password {
10 // The higher the number of iterations the more
11 // expensive computing the hash is for us and
12 // also for an attacker.
13 private static final int iterations = 20*1000;
14 private static final int saltLen = 32;
15 private static final int desiredKeyLen = 256;
16
17 /** Computes a salted PBKDF2 hash of given plaintext password
18 suitable for storing in a database.
19 Empty passwords are not supported. */
20 public static String getSaltedHash(String password) throws Exception {
21 byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
22 // store the salt with the password
23 return Base64.encodeBase64String(salt) + "$" + hash(password, salt);
24 }
25
26 /** Checks whether given plaintext password corresponds
27 to a stored salted hash of the password. */
28 public static boolean check(String password, String stored) throws Exception{
29 String[] saltAndPass = stored.split("\\$");
30 if (saltAndPass.length != 2) {
31 throw new IllegalStateException(
32 "The stored password have the form 'salt$hash'");
33 }
34 String hashOfInput = hash(password, Base64.decodeBase64(saltAndPass[0]));
35 return hashOfInput.equals(saltAndPass[1]);
36 }
37
38 // using PBKDF2 from Sun, an alternative is https://github.com/wg/scrypt
39 // cf. http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
40 private static String hash(String password, byte[] salt) throws Exception {
41 if (password == null || password.length() == 0)
42 throw new IllegalArgumentException("Empty passwords are not supported.");
43 SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
44 SecretKey key = f.generateSecret(new PBEKeySpec(
45 password.toCharArray(), salt, iterations, desiredKeyLen)
46 );
47 return Base64.encodeBase64String(key.getEncoded());
48 }
49 }