Password.java

package org.flasby.crypto;

import com.nulabinc.zxcvbn.Zxcvbn;

import org.mindrot.jbcrypt.BCrypt;

public class Password {

    public static class InvalidPasswordException extends Exception {
        private static final long serialVersionUID = 1L;
        public InvalidPasswordException(String message) {
            super(message);
        }
    }
    
    public static final int DEFAULT_LOG2_ROUNDS = 12;
    
    public static final int MIN_PASSWORD_LENGTH = 8;
    public static final int MAX_PASSWORD_LENGTH = 64;

    enum Strength {
        POOR(0),
        LOW(1),
        MEDIUM(2),
        GOOD(3),
        HIGH(4);
        private final int value;
        private static Strength[] VALUES = {POOR,LOW,MEDIUM,GOOD,HIGH};
        private Strength(int v ) {
            value = v;
        }
        public int getValue() { return value; }
    }
    public String hashPassword( String password ) throws InvalidPasswordException {
        checkPasswordLength(password);
        return BCrypt.hashpw(password,  BCrypt.gensalt(DEFAULT_LOG2_ROUNDS));
    }

    public Strength checkPasswordStrength( String password ) {
        com.nulabinc.zxcvbn.Strength s = new Zxcvbn().measure(password);
        try {
            return Strength.VALUES[ s.getScore() ]; 
        } finally {
            s.wipe();
        }
    }

    private String checkPasswordLength( final String password ) throws InvalidPasswordException {
        if ( password.length() <= MIN_PASSWORD_LENGTH ) throw new InvalidPasswordException("Password is too short");
        if ( password.length() > MAX_PASSWORD_LENGTH ) throw new InvalidPasswordException("Password is too long");
        return password;
    }
}