Skip to main content

password-key

PyPI Python CI CodeQL OpenSSF Scorecard OpenSSF Best Practices License: MIT

Cryptographically secure passwords that are safe to paste anywhere.

Most password generators hand you k9$P@x/2' and let you discover — an hour later, three layers deep in a stack trace — that @ split your database URL, $ was expanded by your shell, and ' broke your SQL. password-key is built around one idea:

URL-safe output is the default. Letters, digits, and - _ . ~ — the only punctuation RFC 3986 guarantees is safe in a URL — and characters that also carry no special meaning in a SQL literal or a shell. At 32 characters that is still ~193 bits of entropy, far beyond any brute-force attack. The restriction buys safety and costs nothing.

The password is copied to your clipboard, never printed (terminal scrollback is a file on disk), drawn from the OS cryptographic RNG via Python's secrets module, and the whole package has zero runtime dependencies — the smallest possible supply-chain surface for a tool that generates credentials.

Install

pipx install password-key    # recommended for CLI use
# or
pip install password-key

Usage

$ password-key

  Length    : 32 characters
  Charset   : URL-safe (letters, digits, - _ . ~) — safe anywhere
  Strength  : ~193 bits of entropy (excellent)
  Clipboard : COPIED

  Paste it into your password manager now, then copy
  something harmless to clear the clipboard.

The essentials:

password-key                  # 32 chars, URL-safe → clipboard
password-key -l 48            # longer
password-key --words 6        # diceware passphrase (see below)
password-key --clear 30       # auto-clear the clipboard after 30 s
password-key --no-ambiguous   # drop 0 O 1 l I | (for reading aloud)
password-key --full           # full punctuation (see warning below)
password-key --show           # display it too (still copied)
password-key --print          # bare password on stdout, for scripts
password-key -i               # interactive menu
pwk                           # short alias for all of the above

Passphrases

$ password-key --words 6

  Words     : 6
  Charset   : 6 words, EFF Large Wordlist (URL-safe)
  Strength  : ~77 bits of entropy (strong)
  Clipboard : COPIED

Diceware passphrases from the EFF Large Wordlist (7,776 words, ~12.9 bits each) — for the secrets a human has to type or remember. The default - separator keeps even passphrases URL-safe. Six words is the EFF's recommendation; use --words 7 (~90 bits) for anything facing offline attack.

Auto-clear

$ password-key --clear 30
  ...
  Clearing clipboard in  30s  (Ctrl+C to keep it)

After the countdown, the clipboard is wiped only if it still holds the password — if you copied something else in the meantime, it is left alone.

Scripting

--print writes the bare secret to stdout and everything else to stderr, so it composes:

DB_PASSWORD=$(password-key --print)
password-key --print --count 5        # five candidates, one per line

Python API

from password_key import generate, generate_passphrase, entropy_bits, FULL

generate()                        # 32-char URL-safe password
generate(48)                      # longer
generate(20, charset=FULL)        # full punctuation
generate(exclude_ambiguous=True)  # no 0 O 1 l I |
generate_passphrase(6)            # 'correct-horse-battery-staple-...'
entropy_bits(66, 32)              # 193.42...

Everything is drawn from secrets — never random.

When you do need punctuation

Some systems mandate a symbol class. --full adds ! # $ % & ( ) * + , - . : ; < = > ? @ [ ] ^ { | } _ ~ and guarantees at least one upper, lower, digit, and symbol:

$ password-key --full

  Charset   : full punctuation — NOT safe in a DSN without percent-encoding
  WARNING   : percent-encode this before putting it in a connection string

An unencoded @ or % inside postgresql://user:PASSWORD@host/db splits the string and surfaces much later as a confusing "could not translate host name". If you must embed a --full password in a URL, percent-encode it first:

from urllib.parse import quote
quote(password, safe="")

Even --full deliberately excludes quotes, backslash, backtick, and space — they add ~0.1 bits per character and are the characters that turn a working password into an escaping bug.

Security design

Decision Why
secrets (OS CSPRNG), never random random is seeded, deterministic pseudo-randomness — unfit for credentials.
Unbiased selection secrets.choice uses rejection sampling internally; no character is ever more likely than another. Checked by a chi-squared test over ~64k draws — test_generator.py, and the same test against the PowerShell script.
Clipboard, not terminal Terminal scrollback is written to disk. The secret is displayed only on explicit request or when no clipboard exists.
Zero dependencies Nothing to typosquat, nothing to compromise. Clipboard access uses the Win32 API directly (ctypes) and pbcopy / wl-copy / xclip elsewhere.
Guarded auto-clear --clear wipes the clipboard only while it still holds the generated password.
No state, no telemetry, no network Passwords are never logged, cached, or written anywhere.

Found a vulnerability? See SECURITY.md.

Verifying this, rather than trusting it

A password generator asks for more trust than most packages, and a README is the wrong basis for granting it. Everything above is meant to be checkable by a stranger.

Check that the wheel you installed came from this source. Releases are published with trusted publishing — there is no long-lived API token that could be stolen and used to push a package this repository never built — and each artifact carries a PEP 740 attestation binding it to the commit it was built from:

VERSION=$(python -c "import password_key; print(password_key.__version__)")
pipx run pypi-attestations verify pypi \
  --repository https://github.com/nathanramoscfa/password-key \
  "pypi:password_key-${VERSION}-py3-none-any.whl"

That checks the version you actually have, not the one this README was written against. A pass prints OK: password_key-<version>-py3-none-any.whl; point it at any other repository and it fails, which is the point. (On Windows, pypi-attestations needs Developer Mode enabled — its trust-root cache creates a symlink, and without that privilege it stops with WinError 1314 before checking anything.)

Installing nothing, the same evidence is on the PyPI page under Verified details: publisher nathanramoscfa/password-key, workflow publish.yml, the commit SHA, and a Sigstore transparency-log entry that is public and append-only.

Then read it. No signature can tell you the code is good, only that it is the code that was published. This package is deliberately small enough to audit in one sitting: the entire security-relevant surface is generator.py (167 lines) and passphrase.py (80 lines), with zero runtime dependencies to follow. There is no cryptography of our own to review — every random draw is secrets.choice.

What checks it besides the author, on every push:

Check What it covers
Tests 378 tests on Linux, macOS, and Windows × Python 3.9–3.13, at 87% branch coverage with a floor enforced in CI.
Fuzzing An Atheris harness drives generate and generate_passphrase with adversarial input on every push, asserting they either honor the contract exactly or raise ValueError — and that entropy is never over-stated, the direction that would call a weak secret strong.
Pester suite The PowerShell script is a second credential generator, so it gets its own bias and charset tests — including a parity check that its alphabet still matches the Python one.
mypy --strict Run for linux, darwin, and win32, so the Windows-only clipboard path is type-checked on every commit rather than only when someone runs it.
CodeQL GitHub's security-extended query suite; results are in the repository's Security tab.
Locked CI tooling Every action is pinned by commit SHA and every pip install runs with --require-hashes, transitive dependencies included, so a substituted wheel cannot enter a build. Dependabot refreshes the pins, because a stale pin is still a stale dependency.
OpenSSF Scorecard A third party scoring this repo's supply-chain posture — pinned actions, token scopes, release provenance — so the claim is not ours to make.

What this does not have. It is a young project with one maintainer and no independent security audit. The checks above are automated ones; none of them is a human expert reading the code adversarially. Judge it on the source, which is the point of keeping it this small.

Windows double-click launcher

Prefer not to open a terminal? New Password.bat launches the interactive menu with a double-click. A standalone PowerShell implementation (no Python required) lives in contrib/new-password.ps1.

Contributing

Issues and PRs welcome — see CONTRIBUTING.md.

License

Built by ArcForge Labs.

MIT. The bundled EFF Large Wordlist is © the Electronic Frontier Foundation, CC BY 3.0 — see THIRD-PARTY-NOTICES.md.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

password_key-1.1.2.tar.gz (81.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

password_key-1.1.2-py3-none-any.whl (63.4 kB view details)

Uploaded Python 3

File details

Details for the file password_key-1.1.2.tar.gz.

File metadata

  • Download URL: password_key-1.1.2.tar.gz
  • Upload date:
  • Size: 81.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for password_key-1.1.2.tar.gz
Algorithm Hash digest
SHA256 7484c3d34244f344413a5ebafad9b09f21b1c817b540e3c611bcaa00c5999ce4
MD5 79361ae1d229561543fb1b0c90d81b90
BLAKE2b-256 8dd7dbf07dd7a8fd1e9803e86abf9631f69765778c88aa506d871772201a94cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for password_key-1.1.2.tar.gz:

Publisher: publish.yml on nathanramoscfa/password-key

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file password_key-1.1.2-py3-none-any.whl.

File metadata

  • Download URL: password_key-1.1.2-py3-none-any.whl
  • Upload date:
  • Size: 63.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for password_key-1.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1448cffcead2e788d8876155d6dd9510af329106b3a5efd323939f45f4ea6d96
MD5 54f630846a30c1561696b98309ffaf57
BLAKE2b-256 52544f220dd73fab3b379ae08b4aa53e37da459732d64dc5a03707ee137ce826

See more details on using hashes here.

Provenance

The following attestation bundles were made for password_key-1.1.2-py3-none-any.whl:

Publisher: publish.yml on nathanramoscfa/password-key

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.1.2 This release

2 files

1.1.1

2 files

1.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page