No description
  • Rust 52.2%
  • TypeScript 32.5%
  • Nix 12%
  • HTML 1.7%
  • Ruby 1.3%
  • Other 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
jesse brooklyn hannah 8a7164fa01
Some checks failed
/ clippy (pull_request) Failing after 28s
/ test-wasm (pull_request) Has been skipped
/ build (macos-latest) (pull_request) Has been skipped
/ build (ubuntu-24.04-arm) (pull_request) Has been skipped
/ build (ubuntu-latest) (pull_request) Has been skipped
/ build (windows-11-arm) (pull_request) Has been skipped
/ build (windows-latest) (pull_request) Has been skipped
/ clippy (push) Failing after 46s
/ test-wasm (push) Has been skipped
/ build (macos-latest) (push) Has been skipped
/ build (ubuntu-24.04-arm) (push) Has been skipped
/ build (ubuntu-latest) (push) Has been skipped
/ build (windows-11-arm) (push) Has been skipped
/ build (windows-latest) (push) Has been skipped
update devenv
2026-10-16 14:42:38 -07:00
.cargo Add wasm binding and skip CLI for wasm target 2025-03-18 10:49:04 -07:00
.github Bump actions/checkout from 5 to 7 (#410) 2026-10-16 14:31:12 -07:00
Formula update formula to v1.4.0 2026-03-13 21:00:58 -07:00
nix add nix flake 2025-06-06 18:34:14 -07:00
src 🧹 [code health] avoid unnecessary string allocation in generate (#380) 2026-04-09 16:54:50 +00:00
web update pnpm dependencies 2026-08-26 13:17:59 -07:00
.envrc add devenv 2025-09-03 09:53:21 -07:00
.gitattributes force lf line endings 2025-06-09 11:19:02 -07:00
.gitignore add devenv 2025-09-03 09:53:21 -07:00
AGENTS.md Add Copilot coding agent instructions (#366) 2026-03-13 22:15:33 -07:00
biome.json fix biome config schema version 2026-02-02 22:58:49 -08:00
Cargo.lock update cargo dependencies 2026-08-26 13:16:05 -07:00
Cargo.toml Bump rand from 0.10.0 to 0.10.1 (#395) 2026-05-18 10:30:16 -07:00
devenv.lock update devenv 2026-10-16 14:42:38 -07:00
devenv.nix add wasm rust target to devenv 2025-10-02 10:24:42 -07:00
devenv.yaml use stable rust channel in devenv 2025-09-20 22:24:18 -07:00
flake.lock update flake.lock 2025-09-03 08:59:34 -07:00
flake.nix update flake.lock 2025-09-03 08:59:34 -07:00
LICENSE update copyright year 2025-09-03 11:16:07 -07:00
README.md v1.4.0 2026-03-13 20:55:50 -07:00
rust-toolchain.toml add copilot setup steps 2025-10-02 10:53:51 -07:00

pkpw

Crates.io npm .github/workflows/ci.yml

What if correct horse battery staple, but Pokémon.

Installation

brew install jbhannah/pkpw/pkpw

CLI/Rust Library

cargo install pkpw

npm Library

npm add pkpw

Usage

CLI

$ pkpw -h
pkpw 1.4.0
Jesse Brooklyn Hannah <[email protected]>
What if correct horse battery staple, but Pokémon.

USAGE:
    pkpw [OPTIONS]

OPTIONS:
    -c, --copy                     Copy the generated value to the clipboard instead of displaying
                                   it
    -h, --help                     Print help information
    -l, --length <LENGTH>          Minimum length of the generated password
    -n, --count <COUNT>            Number of Pokémon names to use in the generated password
                                   [default: 4]
    -s, --separator <SEPARATOR>    Separator between Pokémon names in the generated password; either
                                   a single character, "digit" for random digits, or "special" for
                                   random special characters [default: " "]
    -V, --version                  Print version information

Rust

use pkpw::generate;
use rand::rng;

let mut rng = rng();
let password = generate(None, 4, " ", None, &mut rng);

Javascript/Typescript

import { pkpw } from "pkpw";

const password = pkpw();

The Javascript/Typescript package is compiled from Rust into WASM. If embedded in a web page, for example, all password generation runs in the browser; only analytics of page visit count, password generation count, and the options (minimum length, Pokémon name count, and separator character set) are sent over the network. Make sure you trust any online password generator that uses this package before using the passwords you generate from it!

But is it secure?

Disclaimer: These are just estimates, I have a physics degree but I'm not a combinatorics or cryptography expert.

Password entropy is calculated using the pool size R and password length L used to generate a password:

E = log_2(R^L)

where a brute-force attack will need an average of 2^{E-1} guesses to crack a password with E bits of entropy.

By default, pkpw chooses 4 Pokémon names from the pool of 1028 known Pokémon, resulting in an entropy of

E = log_2(1028^4) \approx 40.022

bits. A dictionary attack that knows to use the 1028 known Pokémon names as the pool of values would take 5.584 \times 10^{11} guesses on average to correctly guess a password, or about 17 years, 8 months, and 12 days at 1000 guesses per second.

At an average length of about 7.67 characters per Pokémon name, passwords generated using the default settings have an average length of about 34 characters (4 Pokémon names, plus one space separating each name for a total of 3 spaces). A brute-force attack that uses a pool of 95 standard US keyboard characters (alphanumeric, special characters, and space) would be working against

E = log_2(95^{34}) \approx 222.375

bits of entropy, taking an average of 1.748 \times 10^{67} guesses, or 5.540 \times 10^{56} years, to correctly guess a password.

All Pokémon names are ™ and © The Pokémon Company, Inc. Everything else in this project is © Jesse Brooklyn Hannah and released under the terms of the MIT License.