All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pl.edu.icm.unity.stdext.credential.pass.StrengthChecker Maven / Gradle / Ivy

Go to download

Standard plugins which are distributed with the system: attribute syntaxes, identity types, credentials

There is a newer version: 4.0.2
Show newest version
/*
 * Copyright (c) 2018 Bixbit - Krzysztof Benedyczak All rights reserved.
 * See LICENCE.txt file for licensing information.
 */
package pl.edu.icm.unity.stdext.credential.pass;

import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

import org.springframework.context.support.MessageSourceResourceBundle;

import com.nulabinc.zxcvbn.Feedback;
import com.nulabinc.zxcvbn.Strength;
import com.nulabinc.zxcvbn.Zxcvbn;

import edu.vt.middleware.password.CharacterRule;
import edu.vt.middleware.password.Password;
import edu.vt.middleware.password.PasswordData;
import edu.vt.middleware.password.Rule;
import pl.edu.icm.unity.base.message.MessageSource;

/**
 * Checks strength of the password using zxcvbn derivative library and provide other simple 
 * quality measurements of passwords. The returned result is normalized to 0-1 range, 
 * 1 (max score) corresponds to currently very hard not normalized value of 14 or minimum acceptable 
 * value whichever is greater.
 * 
 * @author K. Benedyczak
 */
public class StrengthChecker
{
	 //10^14 guesses is considered super safe
	private static final int DEFAULT_PERFECT_SCORE = 14;
	
	public static StrengthInfo measure(String password, int minAcceptable, MessageSource msg)
	{
		return measure(password, minAcceptable, msg.getLocale(), msg);
	}
	
	static StrengthInfo measure(String password, int minAcceptable, 
			Locale locale, MessageSource msg)
	{
		Zxcvbn zxcvbn = new Zxcvbn();
		Strength strength = zxcvbn.measure(password);
		
		ResourceBundle msgAdapter = new MessageSourceResourceBundle(msg, locale);
		Feedback feedback = strength.getFeedback();
		Feedback localizedFeedback = feedback.withResourceBundle(msgAdapter);

		return new StrengthInfo(normalizeScore(strength, minAcceptable),
				(int)strength.getGuessesLog10(),
				localizedFeedback.getWarning(locale),
				localizedFeedback.getSuggestions(locale));
	}
	
	public static int getCharacterClasses(String password)
	{
		List charClassesRules = PasswordVerificator.getCharacteristicsRules();
		PasswordData passwordData = new PasswordData(new Password(password));
		int ret = 0;
		for (CharacterRule rule: charClassesRules)
			if (rule.validate(passwordData).isValid())
				ret++;
		return ret;
	}

	public static boolean hasNoTrivialSequences(String password)
	{
		List charClassesRules = PasswordVerificator.getSequencesRules();
		PasswordData passwordData = new PasswordData(new Password(password));
		for (Rule rule: charClassesRules)
			if (!rule.validate(passwordData).isValid())
				return false;
		return true;
	}
	
	private static double normalizeScore(Strength strength, int minAllowed)
	{
		int perfectScore = DEFAULT_PERFECT_SCORE > minAllowed ? 
				DEFAULT_PERFECT_SCORE : minAllowed;
		double guessesLog10 = strength.getGuessesLog10();
		double scoreBounded = guessesLog10 > perfectScore ? 
				perfectScore : guessesLog10;
		
		return scoreBounded / perfectScore;
	}
	
	
	public static class StrengthInfo
	{
		public final double scoreNormalized;
		public final int score;
		public final String warning;
		public final List suggestions;

		public StrengthInfo(double scoreNormalized, int score, String warning, List suggestions)
		{
			this.scoreNormalized = scoreNormalized;
			this.score = score;
			this.warning = warning;
			this.suggestions = Collections.unmodifiableList(suggestions);
		}

		@Override
		public String toString()
		{
			return "StrengthInfo [score=" + scoreNormalized + ", warning=" + warning
					+ ", suggestions=" + suggestions + "]";
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy