Example #1
0
function minimum_entropy_match_sequence($password, $matches)
{
    # e.g. 26 for lowercase
    $bruteforce_cardinality = calc_bruteforce_cardinality($password);
    # minimum entropy up to k.
    $up_to_k = array();
    # for the optimal sequence of matches up to k, holds the
    # final match (match.j == k). null means the sequence ends
    # w/ a brute-force character.
    $backpointers = array();
    $password_len = strlen($password);
    for ($k = 0; $k < $password_len; $k++) {
        # starting scenario to try and beat:
        # adding a brute-force character to the minimum entropy sequence at k-1.
        $up_to_k[$k] = _get_index($up_to_k, $k - 1) + logarithm($bruteforce_cardinality);
        $backpointers[$k] = NULL;
        foreach ($matches as $match) {
            if ($match['j'] !== $k) {
                continue;
            }
            $i = $match['i'];
            $j = $match['j'];
            # see if best entropy up to i-1 + entropy of this match
            # is less than the current minimum at j.
            $candidate_entropy = _get_index($up_to_k, $i - 1) + calc_entropy($match);
            if ($candidate_entropy < $up_to_k[$j]) {
                $up_to_k[$j] = $candidate_entropy;
                $backpointers[$j] = $match;
            }
        }
    }
    # walk backwards and decode the best sequence
    $match_sequence = array();
    $k = strlen($password) - 1;
    while ($k >= 0) {
        $match = $backpointers[$k];
        if ($match) {
            $match_sequence[] = $match;
            $k = $match['i'] - 1;
        } else {
            $k -= 1;
        }
    }
    $match_sequence = array_reverse($match_sequence);
    # fill in the blanks between pattern matches with bruteforce "matches"
    # that way the match sequence fully covers the password:
    # match1.j == match2.i - 1 for every adjacent match1, match2.
    $make_bruteforce_match = function ($i, $j) use($password, $bruteforce_cardinality) {
        return array('pattern' => 'bruteforce', 'i' => $i, 'j' => $j, 'token' => _slice($password, $i, $j + 1), 'entropy' => logarithm(pow($bruteforce_cardinality, $j - $i + 1)), 'cardinality' => $bruteforce_cardinality);
    };
    $k = 0;
    $match_sequence_copy = array();
    foreach ($match_sequence as $match) {
        $i = $match['i'];
        $j = $match['j'];
        if ($i - $k > 0) {
            $match_sequence_copy[] = $make_bruteforce_match($k, $i - 1);
        }
        $k = $j + 1;
        $match_sequence_copy[] = $match;
    }
    if ($k < strlen($password)) {
        $match_sequence_copy[] = $make_bruteforce_match($k, strlen($password) - 1);
    }
    $match_sequence = $match_sequence_copy;
    # or 0 corner case is for an empty password ''
    if (isset($up_to_k[strlen($password) - 1])) {
        $min_entropy = $up_to_k[strlen($password) - 1];
    } else {
        $min_entropy = 0;
    }
    $crack_time = entropy_to_crack_time($min_entropy);
    # final result object
    $result = array('password' => $password, 'entropy' => round_to_x_digits($min_entropy, 3), 'match_sequence' => $match_sequence, 'crack_time_seconds' => round_to_x_digits($crack_time, 3), 'crack_time_display' => display_time($crack_time), 'score' => crack_time_to_score($crack_time));
    return $result;
}
Example #2
0
function date_sep_match($password)
{
    global $date_rx_year_suffix, $date_rx_year_prefix;
    $matches = array();
    foreach (findall($password, $date_rx_year_suffix) as $match) {
        $match['day'] = (int) $match[1];
        $match['month'] = (int) $match[3];
        $match['year'] = (int) $match[4];
        $match['sep'] = $match[2];
        $matches[] = $match;
    }
    foreach (findall($password, $date_rx_year_prefix) as $match) {
        $match['day'] = (int) $match[4];
        $match['month'] = (int) $match[3];
        $match['year'] = (int) $match[1];
        $match['sep'] = $match[2];
        $matches[] = $match;
    }
    $results = array();
    foreach ($matches as $match) {
        list($valid, $date) = check_date($match['day'], $match['month'], $match['year']);
        if (!$valid) {
            continue;
        }
        list($day, $month, $year) = $date;
        $i = $match['i'];
        $j = $match['j'];
        $results[] = array('pattern' => 'date', 'i' => $i, 'j' => $j, 'token' => _slice($password, $i, $j + 1), 'separator' => $match['sep'], 'day' => $day, 'month' => $month, 'year' => $year);
    }
    return $results;
}