# passmeter

**Offline ML-powered password strength evaluation for Python developers.**

`passmeter` uses a trained Random Forest classifier to score passwords as Weak, Medium, or Strong — with confidence scores and actionable feedback. Everything runs locally: no API calls, no servers, no internet required.

---

## Installation

```bash
pip install passmeter
```

---

## Quick Start

```python
from passmeter import evaluate_password

result = evaluate_password("Monkey2024!")
print(result)
```

**Output:**

```json
{
  "score": 1,
  "label": "Medium",
  "confidence": 0.87,
  "features": {
    "length": 11,
    "entropy": 3.1,
    "num_upper": 1,
    "num_digits": 4,
    "num_special": 1
  },
  "feedback": [
    "Longer passwords are significantly harder to crack",
    "Avoid predictable patterns like years or repeated digits"
  ]
}
```

---

## API Reference

### `evaluate_password(password: str) → dict`

Evaluates a password and returns a structured result.

| Key          | Type    | Description                                              |
|--------------|---------|----------------------------------------------------------|
| `score`      | `int`   | Numeric strength: `0` = Weak, `1` = Medium, `2` = Strong |
| `label`      | `str`   | Human-readable label matching the score                  |
| `confidence` | `float` | Model probability for the predicted class (0.0 – 1.0)    |
| `features`   | `dict`  | Key statistics extracted from the password               |
| `feedback`   | `list`  | Actionable suggestions; empty list means no issues found |

**Raises:**
- `TypeError` – if input is not a string
- `ValueError` – if input is an empty string

---

### `extract_features(password: str) → dict`

Returns all 10 raw statistical features used by the model.

```python
from passmeter import extract_features

extract_features("Monkey2024!")
# {
#   'length': 11, 'num_upper': 1, 'num_lower': 6,
#   'num_digits': 4, 'num_special': 1, 'entropy': 3.1,
#   'unique_chars': 10, 'has_upper': 1, 'has_digit': 1, 'has_special': 1
# }
```

---

## More Examples

```python
from passmeter import evaluate_password

# Weak password
r = evaluate_password("password")
print(r["label"])       # Weak
print(r["feedback"])    # ['Add at least one uppercase letter', ...]

# Strong password
r = evaluate_password("xK9#mP2$vL8@nQ4!")
print(r["label"])       # Strong
print(r["confidence"])  # 0.97
print(r["feedback"])    # []
```

---

## How It Works

### Feature Extraction

`passmeter` computes 10 statistical features from each password:

| Feature        | Description                                  |
|----------------|----------------------------------------------|
| `length`       | Total number of characters                   |
| `num_upper`    | Count of uppercase letters                   |
| `num_lower`    | Count of lowercase letters                   |
| `num_digits`   | Count of digit characters                    |
| `num_special`  | Count of non-alphanumeric characters         |
| `entropy`      | Shannon entropy (bits per character)         |
| `unique_chars` | Number of distinct characters used           |
| `has_upper`    | Boolean: contains at least one uppercase     |
| `has_digit`    | Boolean: contains at least one digit         |
| `has_special`  | Boolean: contains at least one special char  |

### ML Model

A **Random Forest classifier** was trained on a labeled password dataset. It learns non-linear relationships between these features and password strength — going beyond simple rule matching.

`predict_proba()` is used to surface a confidence score alongside the predicted class, giving callers a sense of how certain the model is.

---

## ML vs Rule-Based: Why Not zxcvbn?

[zxcvbn](https://github.com/dwolfhub/zxcvbn-python) is a well-known rule-based estimator that checks passwords against wordlists, keyboard patterns, and dates. It is excellent for its use case, but it has some differences from `passmeter`:

| Feature                      | passmeter (ML)              | zxcvbn (rule-based)        |
|------------------------------|-----------------------------|----------------------------|
| Approach                     | Random Forest classifier    | Pattern + dictionary rules |
| Scores derived from          | Learned statistical patterns | Hardcoded heuristics       |
| Confidence score             | Yes (model probability)     | No                         |
| Customisable training data   | Yes (retrain on your data)  | No                         |
| Wordlist dependency          | None                        | Bundled ~30k word list     |
| Generalises to novel patterns| Yes (via feature stats)     | Limited to known patterns  |
| Fully offline                | Yes                         | Yes                        |

Both tools have value. `passmeter` is better suited when you want ML-derived confidence scores, a trainable model, or a smaller dependency footprint.

---

## Offline Advantage

`passmeter` ships the trained model file (`passmeter_model.pkl`) **inside the package itself**. Once installed via `pip`, it works in:

- Air-gapped servers and secure environments
- CI/CD pipelines with no outbound network access
- Embedded systems and edge deployments
- Any environment where calling an external API is undesirable

No credentials, no rate limits, no latency from a remote service.

---

## License

MIT — see [LICENSE](LICENSE).
