Package org.owasp.passfault

Source Code of org.owasp.passfault.PasswordAnalysis_Unoptimized

/* ©Copyright 2011 Cameron Morris
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*     http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.owasp.passfault;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.owasp.passfault.AnalysisListener;
import org.owasp.passfault.PasswordPattern;
import org.owasp.passfault.PasswordResults;
import org.owasp.passfault.PathCost;
import org.owasp.passfault.RandomPattern;
import org.owasp.passfault.finders.RepeatingPatternFinder;

/**
* This class holds the results of the analysis of a password.  An instance
* of this class begins with a password to analyze.  Then it is handed to
* multiple <code>PatternFinder<code>s.
*
* This class contains the logic for post-analysis of the finders found
* (althought this logic might be better if separated from this class)  This
* logic includes finding the weakest combination of finders and locating
* repeated finders.
*
* @author cam
*/
public class PasswordAnalysis_Unoptimized implements PasswordResults {

  private String password;
  private Map<Integer, List<PasswordPattern>> foundPatterns = new HashMap<Integer, List<PasswordPattern>>();
  private int patternCount = 0;
  private List<AnalysisListener> analysisListeners = new LinkedList<AnalysisListener>();
  private RepeatingPatternFinder repeatingPatternFinder = new RepeatingPatternFinder();
  private PathCost finalResults = null;
  private RandomPattern randomPatternFinder = new RandomPattern();
  private static final Logger log = java.util.logging.Logger.getLogger(PasswordAnalysis_Unoptimized.class.getName());
  //todo remove counter, this is just for debugging to measure the optmization effectiveness
  private int counter = 0;

  public PasswordAnalysis_Unoptimized(String password) {
    this.password = password;
  }

  public CharSequence getCharSequence() {
    return password;
  }

  public int getLength() {
    return password.length();
  }

  /**
   * Adds a listener that will be notified when a pattern is found and when
   * a password analysis is complete
   * @param listener callback object to be notified when a pattern is found and
   * when analysis is complete.
   */
  @Override
  public void addListener(AnalysisListener listener) {
    this.analysisListeners.add(listener);
  }

  /**
   * This method is called by pattern finders to store a newly discovered pattern
   * in a password.
   * @param patt pattern found in the password.
   */
  @Override
  synchronized public void foundPattern(PasswordPattern patt) {
//    PasswordPattern randomPattern = randomPatternFinder.getRandomPattern(password, patt.startIndex, patt.length);
//    if (patt.cost > randomPattern.cost){
//      //random is less expensive so throw away the pattern
//      log.log(Level.INFO, "Pattern discarded because random is smaller: {0}", patt.name);
//      patt = randomPattern;
//    }
    List<PasswordPattern> patterns = getIndexSet(patt.getStartIndex());
    boolean worsePatternAlreadyFound = false;
    for (PasswordPattern passwordPattern : patterns) {
      if (patt.getLength() == passwordPattern.getLength()
          && patt.getCost() > passwordPattern.getCost()) {
        worsePatternAlreadyFound = true;
        log.log(Level.INFO, "discarding found pattern since a worse pattern already exists: {0}", patt.getName());
      }
    }
    if (!worsePatternAlreadyFound) {
      patterns.add(patt);
      patternCount++;
      for (AnalysisListener observer : analysisListeners) {
        observer.foundPattern(patt);
      }
    }
  }

  /**
   * This is a lazy loading getter for a list of finders that begin on the
   * index of the password.
   * @param startIndex index of the a character in a the password where the list
   * of finders begin.
   *
   * @return a List of finders found for the starting index of where a pattern
   * starts.
   */
  private List<PasswordPattern> getIndexSet(int startIndex) {
    if (!foundPatterns.containsKey(startIndex)) {
      foundPatterns.put(startIndex, new LinkedList<PasswordPattern>());
    }
    return foundPatterns.get(startIndex);
  }

  /**
   * @return total number of finders identified.
   */
  @Override
  public int getPossiblePatternCount() {
    return patternCount;
  }

  /**
   * Calculates the highest probable combination of finders.  In other words,
   * the weakest combination of found finders.
   * @return List of finders that make up the weakest combination of found passwords
   */
  @Override
  public PathCost calculateHighestProbablePatterns() {
    if (finalResults == null) {
      log.log(Level.INFO, "Calculating the highest probable combination of {0} finders\n", getPossiblePatternCount());
      PathCost cost = smallestCost(0);
      cost = postAnalysis(cost);
      log.log(Level.FINE, "smallestCost took {0} iterations", counter);

      for (AnalysisListener observer : analysisListeners) {
        observer.foundHighestProbablePatterns(cost);
      }
      finalResults = cost;
    }
    return finalResults;
  }

  /**
   * This is a recursive call to compute the smallest Cost (or weakest combination)
   * of finders starting at the index specified by startChar
   * @param startChar
   * @return List of finders including cost
   */
  private PathCost smallestCost(int startChar) {
    double smallestCost = Double.MAX_VALUE;
    PathCost smallestCostPath = new PathCost(this);
    for (int i = startChar; i < password.length(); i++) {
      List<PasswordPattern> ithPatterns = foundPatterns.get(i);
      if (ithPatterns != null) {
        PathCost pathCost = ithSmallestCost(ithPatterns);
        counter++;

        //random characters between startChar and the next found pattern
        PasswordPattern randomPattern = getRandomPattern(startChar, i);

        if (randomPattern != null) {
          pathCost.addPattern(randomPattern);
        }
        if (pathCost.getRelativeCost() < smallestCost) {
          smallestCost = pathCost.getRelativeCost();
          smallestCostPath = pathCost;
        }
      }
    }
    if (smallestCostPath.getPath().size() == 0) {
      PasswordPattern randomPattern = getRandomPattern(startChar, password.length());
      if (randomPattern != null) {
        smallestCostPath.addPattern(randomPattern);
      }
    }
    return smallestCostPath;
  }

  /**
   * Helper method for smallestCost,
   * @param ithPatterns list of finders starting with a specific index
   * @return result of the smallest result of calling smallestCost on all
   * finders in the list
   */
  private PathCost ithSmallestCost(List<PasswordPattern> ithPatterns) {
    double smallestCost = Double.MAX_VALUE;
    PathCost smallestCostPath = null;
    for (PasswordPattern pattern : ithPatterns) {
      PathCost costPath = smallestCost(pattern.getStartIndex() + pattern.getLength());
      costPath.addPattern(pattern);
      double cost = costPath.getRelativeCost();
      if (cost < smallestCost) {
        smallestCost = cost;
        smallestCostPath = costPath;
      }
    }
    return smallestCostPath;
  }

  private PathCost postAnalysis(PathCost cost) {
    return repeatingPatternFinder.process(cost, this);
  }

  private PasswordPattern getRandomPattern(int startChar, int endChar) {
    if (endChar <= startChar) {
      return null;
    }

    return randomPatternFinder.getRandomPattern(this.password, startChar, endChar - startChar);
  }
}
TOP

Related Classes of org.owasp.passfault.PasswordAnalysis_Unoptimized

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.