{"id":49895293,"url":"https://github.com/hoxxep/passwordentropy.com","last_synced_at":"2026-05-15T23:25:38.743Z","repository":{"id":347791783,"uuid":"1127724880","full_name":"hoxxep/passwordentropy.com","owner":"hoxxep","description":"Estimate password entropy and cracking times. Inspired by xkcd #936.","archived":false,"fork":false,"pushed_at":"2026-04-18T15:56:55.000Z","size":1923,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-18T17:37:28.090Z","etag":null,"topics":["entropy","hashing","password"],"latest_commit_sha":null,"homepage":"http://passwordentropy.com","language":"Astro","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hoxxep.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-04T13:27:31.000Z","updated_at":"2026-04-18T15:56:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hoxxep/passwordentropy.com","commit_stats":null,"previous_names":["hoxxep/passwordentropy.com"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hoxxep/passwordentropy.com","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoxxep%2Fpasswordentropy.com","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoxxep%2Fpasswordentropy.com/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoxxep%2Fpasswordentropy.com/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoxxep%2Fpasswordentropy.com/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hoxxep","download_url":"https://codeload.github.com/hoxxep/passwordentropy.com/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoxxep%2Fpasswordentropy.com/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33083314,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T20:25:35.270Z","status":"ssl_error","status_checked_at":"2026-05-15T20:25:34.732Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["entropy","hashing","password"],"created_at":"2026-05-15T23:25:38.074Z","updated_at":"2026-05-15T23:25:38.735Z","avatar_url":"https://github.com/hoxxep.png","language":"Astro","funding_links":[],"categories":[],"sub_categories":[],"readme":"# passwordentropy.com\n\nA password strength calculator that does things properly.\n\nMost password strength meters are terrible. They check for a capital letter, a number, and call it a day. This one uses real cryptographic research, actual GPU benchmarks, and breach data to tell you how long your password would *actually* take to crack.\n\nSponsored by [Upon: Digital Inheritance Vaults](https://uponvault.com/?ref=gh-pe).\n\n## Why \"P@ssw0rd!\" Gets a Failing Grade\n\nTraditional password meters reward complexity theater: swap an `a` for `@`, add a `1` at the end, and suddenly you're \"strong.\" But attackers aren't stupid. They know about [l33tspeak](https://en.wikipedia.org/wiki/Leet). They have dictionaries of common substitutions. \"P@ssw0rd!\" isn't 9 random characters drawn from 95 possibilities, it's a predictable mutation of the #4 most common password on the internet. In fact, it's been breached 120k times and is likely one of the first passwords an attacker will try!\n\n### How We Score Passwords\n\nWe combine three signals to estimate how quickly an attacker could crack your password:\n\n1. **Pattern analysis:** [zxcvbn](#zxcvbn-pattern-matching-not-character-counting) decomposes your password into dictionary words, keyboard patterns, and substitutions, then estimates how many guesses it would take.\n2. **Breach data:** we check [Have I Been Pwned](#have-i-been-pwned-when-your-password-is-already-public) to see if your password has leaked, then apply a [Zipf's law penalty](#the-zipfs-law-penalty-modeling-attacker-behavior) based on how often it appears.\n3. **Real hardware benchmarks:** we use [actual RTX 5090 hashcat speeds](#hash-rate-benchmarks-rtx-5090-numbers) to show crack times across different hash algorithms and attacker resources.\n\nThe final entropy is the *minimum* of the pattern-based estimate and the breach-based estimate. A password in an attackers list from previous breaches is effectively worthless, no matter how random it looks.\n\n### What Is Password Entropy?\n\nEntropy measures *uncertainty*, expressed as the number of guesses an attacker would need to find your password. We measure it in bits, where each bit doubles the search space:\n\n| Bits | Possible Combinations | Equivalent To            |\n|------|-----------------------|--------------------------|\n| 10   | 1,024                 | 4-digit PIN with letters |\n| 20   | ~1 million            | Weak password            |\n| 40   | ~1 trillion           | Moderate password        |\n| 60   | ~1 quintillion        | Strong password          |\n| 80   | ~1 septillion         | Very strong password     |\n\nMathematically, entropy is the base-2 logarithm of guesses needed, assuming an attacker tries passwords in optimal order. If you pick randomly from a character set of size `N` for `L` characters, `entropy = L × log₂(N)`. A 10-character lowercase password has `10 × 4.7 ≈ 47 bits`.\n\nHumans don't pick randomly, though. We use words, patterns, and substitutions that drastically reduce the *effective* entropy. [xkcd #936](https://xkcd.com/936/) illustrates this perfectly:\n\n[![xkcd 936: Password Strength](https://imgs.xkcd.com/comics/password_strength.png)](https://xkcd.com/936/)\n\nThe comic shows \"Tr0ub4dor\u00263\" at ~28 bits versus \"correct horse battery staple\" at ~44 bits. The complex-looking password is actually weaker. **The number of guesses matters, not how \"random\" it looks to a human.**\n\n### zxcvbn: Pattern Matching, Not Character Counting\n\nWe use [zxcvbn-ts](https://github.com/zxcvbn-ts/zxcvbn), a TypeScript port of Dropbox's [zxcvbn](https://github.com/dropbox/zxcvbn) library. Instead of the naive approach (`entropy = log₂(charset_size) × length`), zxcvbn models how attackers actually crack passwords:\n\n1. **Dictionary attacks** – Checks against common passwords, English words, names, and surnames\n2. **Keyboard patterns** – Recognizes \"qwerty\", \"zxcvbn\", and \"123456\"\n3. **Repeated characters** – \"aaaaaaa\" isn't 7 characters of entropy\n4. **Sequences** – \"abcdef\" and \"13579\" are predictable\n5. **L33t substitutions** – \"@\" for \"a\", \"0\" for \"o\", \"$\" for \"s\"\n6. **Dates** – Birthdays and anniversaries are common password components\n\nzxcvbn estimates the number of guesses an attacker would need by finding the *lowest-cost decomposition* of your password into known patterns, which we can then convert into bits via `entropy = log₂(guesses)`.\n\nzxcvbn accurately estimates entropy for human-created passwords but tends to underestimate truly random passwords. For example, \"Hn@q8kKYN*\" has ~60 bits of true entropy based on its character set, yet zxcvbn estimates only ~33 bits.\n\n### Have I Been Pwned: When Your Password Is Already Public\n\nEven a randomly-generated password becomes worthless if it's in a breach database. Attackers don't brute-force from scratch, they start with lists of *known* passwords, sorted by frequency. Your clever passphrase might be unique in your head, but if it leaked from Adobe in 2013, it's in every attacker's wordlist.\n\nWe check passwords against [Have I Been Pwned](https://haveibeenpwned.com)'s database of 850+ million compromised passwords without ever sending your password over the internet.\n\nHIBP stores SHA-1 hashes of every leaked password in their database, which we query using a protocol called [k-anonymity](https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/):\n\n1. We SHA-1 hash your password locally (e.g. `password123` becomes `CBFDAC6008F9CAB4083784CBD1874F76618D2A97`)\n2. We send only the first 5 characters of the hash to HIBP (`CBFDA`)\n3. HIBP returns ~500 hash suffixes that match that prefix\n4. We check locally if our full hash suffix is in the list\n\nThe server never sees your password or even its full hash. The 5-character prefix matches ~500 other hashes, providing plausible deniability. We also use the `Add-Padding: true` header to prevent response length analysis.\n\n#### Modeling Attacker Behavior with Zipf's Law\n\nIf your password appears in 10,000 breaches, how much does that actually hurt you?\n\nAttackers don't try passwords randomly. They try them in order of *popularity*, and password frequency distributions follow [Zipf's law](https://en.wikipedia.org/wiki/Zipf%27s_law), the same power law that governs word frequency in natural language. The most common password is tried first, the second most common second, and so on. A password that appears twice as often gets tried much earlier, not just a little earlier.\n\nResearch on password distributions ([\"A Large-Scale Study of Web Password Habits\"](https://www.microsoft.com/en-us/research/publication/a-large-scale-study-of-web-password-habits/) and [subsequent analysis](https://arxiv.org/pdf/1104.3722)) suggests that password frequency follows:\n\n```\nfrequency(rank) = C / rank^s\n```\n\nWe use the exponent `s ≈ 0.78` for passwords as per the research papers. Inverting this formula lets us estimate rank from frequency:\n\n```\nrank = (C / frequency)^(1/s)\nentropy = log₂(rank)\n```\n\nWe use pessimistic parameters: C = 1,000,000, anchored to \"password\" appearing roughly 1 million times in breaches. This aligns with leaked datasets like RockYou and Collection #1, where the most common passwords appear millions of times.\n\n| Breach Count | Estimated Rank | Entropy (bits) |\n|--------------|----------------|----------------|\n| 42,000,000   | ~1             | ~0             |\n| 1,000,000    | ~1             | ~0             |\n| 100,000      | ~19            | ~4.2           |\n| 10,000       | ~363           | ~8.5           |\n| 1,000        | ~6,918         | ~12.8          |\n| 100          | ~132,000       | ~17            |\n| 10           | ~2,500,000     | ~21.3          |\n| 1            | ~48,000,000    | ~25.5          |\n\nWe also apply a hard cap of 25 bits for any breached password. Even if a password only appears once in a breach, the attacker's wordlist is only ~1 billion entries (`log₂(1 billion)` is ~30 bits of entropy) and we want to be conservative.\n\n### Hash Rate Benchmarks: RTX 5090 Numbers\n\nThe crack time table uses real-world benchmarks from [hashcat](https://hashcat.net/) running on an NVIDIA RTX 5090 (the current fastest consumer GPU for password cracking). Sources:\n\n- [RTX 5090 hashcat benchmarks](https://gist.github.com/Chick3nman/09bac0775e6393468c2925c1e1363d5c) by Chick3nman\n- [RTX 4090 benchmarks](https://gist.github.com/Chick3nman/32e662a5bb63bc4f51b847bb422222fd) for comparison\n- [Argon2id benchmarks](https://hashcat.net/forum/thread-11277.html) from hashcat 7.0.0\n\n#### Fast Hashes (Don't Use These for Passwords)\n\n| Algorithm | RTX 5090 Speed | Notes                           |\n|-----------|----------------|---------------------------------|\n| MD5       | 220.6 GH/s     | 220 billion attempts per second |\n| SHA-1     | 70.2 GH/s      | Still catastrophically fast     |\n| SHA-512   | 10 GH/s        | Faster than you'd expect        |\n\nThese are *message digests*, not password hashes. They're designed to be fast, which is exactly wrong for password storage. If you see a site storing passwords as MD5... run. Even with salts, fast hashes remain unsafe because attackers can still test billions of guesses per second per account.\n\n#### Key Stretching Functions (Use These)\n\nKSFs are specifically designed to be slow, memory-hard, or both. We benchmark with production-realistic parameters:\n\n| Algorithm | Parameters                              | RTX 5090 Speed |\n|-----------|-----------------------------------------|----------------|\n| PBKDF2    | 310,000 iterations (Django 4.x default) | ~36 kH/s       |\n| bcrypt    | cost 10 (1,024 rounds)                  | ~9.5 kH/s      |\n| scrypt    | N=16384, r=1, p=1                       | ~7.8 kH/s      |\n| Argon2id  | m=64MiB, t=3, p=1 (RFC 9106)            | ~2.2 kH/s      |\n\nArgon2id is the current recommendation from the [Password Hashing Competition](https://www.password-hashing.net/). It's memory-hard, requiring 64MB of RAM per hash attempt, which makes GPU parallelization expensive. The parameters we use match the \"first recommendation\" from [RFC 9106](https://www.rfc-editor.org/rfc/rfc9106.html).\n\n#### GPU Scaling\n\nThe table shows crack times across different attacker resources:\n\n- **1 GPU**: Individual attacker or researcher\n- **10-100 GPUs**: Small organization or dedicated attacker\n- **1,000-10,000 GPUs**: Large corporation or criminal enterprise\n- **1,000,000 GPUs (Nation State)**: Theoretical upper bound rather than any known deployed system in 2025\n\n### The Math\n\nFor a given password, the time to crack is:\n\n```\naverage_time = (2^entropy) / (2 × hash_rate × gpu_count)\n```\n\nWe divide by 2 because on average, you'll find the password halfway through the search space.\n\nA 12-character random password using lowercase letters and digits has about 62 bits of entropy. Here's how crack times differ based on how the site stores your password:\n\n| Storage Method | 1 GPU     | 10k GPUs   | Nation State |\n|----------------|-----------|------------|--------------|\n| MD5            | 105 years | 4 days     | Instant      |\n| Argon2id       | 66M years | 6.6k years | 66 years     |\n\nThe same password, stored properly, goes from being crackable by a well-funded attacker to almost impossible to crack.\n\n## The Takeaways\n\n1. **Use a password manager**: randomly generate every password except your master password.\n2. **Entropy beats complexity theater**: 4 random dictionary words (\"correct horse battery staple\") outperform complex-looking mutations (\"Tr0ub4dor\u00263\") because attackers know about l33tspeak.\n3. **Check your passwords against breaches**: if it's leaked, it's worthless, no matter how random it looks.\n4. **Use unique passwords everywhere**: credential stuffing means one breach compromises all accounts sharing that password.\n5. **Demand proper password storage**: Use a strongly configured key stretching function like Argon2id (ideally with PAKE such as OPAQUE and per-user salts). If a service stores your password with MD5 or SHA, they are failing you.\n6. **80+ bits of entropy remains out of reach**, even for nation-states with theoretical million-GPU clusters. But don't forget [rule #538](https://xkcd.com/538/): \u003cbr /\u003e\n   [![xkcd 538: Security](https://imgs.xkcd.com/comics/security.png)](https://xkcd.com/538/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoxxep%2Fpasswordentropy.com","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoxxep%2Fpasswordentropy.com","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoxxep%2Fpasswordentropy.com/lists"}