2 releases (1 stable)

Uses new Rust 2024

new 1.0.0 Apr 14, 2025

#171 in Authentication

Download history 173/week @ 2025-04-09

173 downloads per month

MIT license

50KB
843 lines

Password Strength (Rust)

Build Status Crates.io License: MIT

A Rust library for estimating password strength based on multiple configurable factors, including length, character set diversity, randomness, and common weak patterns.

Overview

This library provides a flexible way to analyze passwords and assign them a strength score between 0.0 (very weak) and 1.0 (very strong). It combines several analysis techniques:

  1. Length Analysis: Scores passwords based on their length, rewarding longer passwords.
  2. Character Set Analysis: Evaluates the diversity of character types used (e.g., lowercase, uppercase, digits, symbols, Unicode, emojis) and their distribution.
  3. Trigraph Analysis: Measures the statistical randomness of character triplets using Shannon entropy.
  4. Pattern Analysis: Detects and penalizes common weak patterns like keyboard sequences (e.g., "qwerty"), character sequences (e.g., "abc", "123"), repeated characters or sequences (e.g., "aaa", "testtest"), and common substitutions (e.g., "@" for "a", "3" for "e").

The library provides individual analyzers for each factor and a main function (estimate_strength) that combines these factors using a weighted average approach.

Features

  • Multi-Factor Analysis: Considers length, charset, randomness (trigraphs), and common patterns.
  • Unicode Support: Correctly handles Unicode characters and graphemes in analysis (e.g., emojis, non-ASCII letters).
  • Configurable Pattern Detection: The PatternAnalyzer can be configured (e.g., custom keyboard layouts, sequences, substitution rules, penalty weights) using a builder pattern (though the main function uses defaults).
  • Weighted Scoring: Provides a combined score (0.0–1.0) based on a configurable weighted average of the individual analysis results.
  • Modular Design: Use the combined estimate_strength function or leverage individual Analyzer implementations for more granular control.

Installation

Add this library to your Cargo.toml dependencies:

[dependencies]
password-strength = "1"

Usage

Basic Strength Estimation

The easiest way to use the library is via the estimate_strength function.

use password_strength::estimate_strength;

fn main() {
    let password_to_check = "aB1!üöß字例😊_Long";
    let strength = estimate_strength(password_to_check);

    println!("Password: {}", password_to_check);
    println!("Estimated Strength: {:.3}", strength); // Score between 0.0 and 1.0

    if strength < 0.3 {
        println!("Result: Very Weak");
    } else if strength < 0.6 {
        println!("Result: Weak");
    } else if strength < 0.8 {
        println!("Result: Moderate");
    } else {
        println!("Result: Strong");
    }
}

Interpreting the Score

  • 0.0: Indicates a very weak password (e.g., too short, fails multiple checks significantly).
  • 1.0: Indicates a very strong password according to the analyzer's criteria (e.g., long, diverse character set, random, no common patterns detected).

Values in between represent varying degrees of strength. The thresholds for "Weak", "Moderate", "Strong" depend on your specific security requirements.

Using Individual Analyzers (Advanced)

You can also use the individual analyzers if you need more detailed information or want to implement custom scoring logic.

use password_strength::analyzer::{Analyzer, length::LengthAnalyzer, charset::CharsetAnalyzer, trigraph::TrigraphAnalyzer, pattern::PatternAnalyzer};

fn main() {
    let password = "P@sswOrd!123";

    let length_analyzer = LengthAnalyzer::default();
    let charset_analyzer = CharsetAnalyzer::default();
    let trigraph_analyzer = TrigraphAnalyzer::default();
    let pattern_analyzer = PatternAnalyzer::default(); // Can use ::builder() for config

    let score_length = length_analyzer.analyze(password);
    let score_charset = charset_analyzer.analyze(password);
    let score_trigraph = trigraph_analyzer.analyze(password);
    let score_pattern = pattern_analyzer.analyze(password); // 1.0 = no patterns, 0.0 = max penalty

    println!("Password: {}", password);
    println!(" - Length Score: {:.3}", score_length);
    println!(" - Charset Score: {:.3}", score_charset);
    println!(" - Trigraph Score: {:.3}", score_trigraph);
    println!(" - Pattern Score (1.0 - Penalty): {:.3}", score_pattern);

    // Implement your own custom combination logic here if needed
    // let custom_final_score = ...;
}

Analyzers Explained

  • LengthAnalyzer: Scores 0.0 for passwords < 8 chars, 1.0 for >= 16 chars, with linear scaling in between.
  • CharsetAnalyzer: Scores based on the number of character categories used (ASCII lower/upper/digit/symbol, non-ASCII letter/digit/symbol, emoji) and how evenly characters are distributed among the used categories. Max score 1.0.
  • TrigraphAnalyzer: Calculates the Shannon entropy of 3-character sequences (graphemes) and normalizes it to a 0.0–1.0 score. Higher scores indicate less predictability.
  • PatternAnalyzer: Starts with a score of 1.0 and subtracts penalties for detected weaknesses (keyboard patterns, sequences, repeats, substitutions). Returns the final score (1.0 - total penalty), clamped between 0.0 and 1.0.

Weighting in estimate_strength

The default estimate_strength function combines the individual scores using a weighted average. As of the last update, the weights are:

  • Length Score: 25%
  • Charset Score: 25%
  • Trigraph Score: 10%
  • Pattern Score: 40%

Formula: final_score = (0.25 * S_len) + (0.25 * S_char) + (0.10 * S_trig) + (0.40 * S_pat)

You can modify the estimate_strength function in the source code or create your own combining function if you require different weighting or logic.

Contributing

Contributions are welcome!

Please feel free to submit pull requests or open issues for bugs, feature requests, or improvements.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Dependencies

~355KB