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