hardguard25
Python reference implementation of HardGuard25 — an open standard for human-safe identifiers.
0 1 2 3 4 5 6 7 8 9 A C D F G H J K M N P R U W Y
HardGuard25 is a 25-character alphabet designed to exclude common visual confusables, including patterns relevant to dyslexia-sensitive workflows. It removes 11 letters associated with predictable confusion (I L O B S Z E T V X Q). When a letter and a digit compete for the same visual slot, the digit always wins. Comparative OCR and transcription error rates have not yet been established empirically.
Install
pip install hardguard25
Requires Python 3.9+.
Quickstart
from hardguard25 import generate, validate, normalize, check_digit, verify_check_digit
generate(8) # e.g. "AC3H7PUW"
generate(8, check_digit=True) # e.g. "AC3H7PUWN" (length+1)
validate("ac3h-7puw") # True (case and separators tolerated)
normalize("ac3h-7puw") # "AC3H7PUW"
check_digit("AC3H7PUW") # "N"
verify_check_digit("AC3H7PUWN") # True
Normalization removes the Unicode White_Space set pinned by the specification plus -, _, and ., and rejects empty or separator-only input. Validation returns False for invalid input, and check-digit calculation rejects an empty payload.
API
| Function | Purpose |
|---|---|
generate(length, *, check_digit=False) |
Cryptographically secure random ID using rejection sampling for uniform distribution |
validate(s) |
True if s normalizes to a valid HardGuard25 ID; never raises |
normalize(s) |
Remove pinned Unicode White_Space and - _ ., uppercase, and reject other characters |
check_digit(code) |
Mod-25 weighted check digit for manual-entry error detection |
verify_check_digit(code) |
Strip last char, recompute, compare |
ALPHABET |
"0123456789ACDFGHJKMNPRUWY" |
Type hints and py.typed marker included.
Sizing
Each character carries log2(25) = 4.64 bits of entropy.
| Length | Bits | Possible Strings | Typical Use |
|---|---|---|---|
| 4 | 18.6 | 390,625 | Small inventory, tickets |
| 5 | 23.2 | 9,765,625 | Small business |
| 6 | 27.9 | 244,140,625 | Medium businesses |
| 7 | 32.5 | 6.1 billion | Large catalogs |
| 8 | 37.2 | 152.6 billion | Large systems |
| 12 | 55.7 | 5.96 × 10¹⁶ | Internal tokens |
| 16 | 74.3 | 2.33 × 10²² | Cross-system IDs |
| 20 | 92.9 | 9.09 × 10²⁷ | Public tokens |
| 22 | 102.2 | 5.68 × 10³⁰ | Internet-scale |
These values are possible payload strings, not safe random issuance counts. Random issuance must account for birthday collisions. An appended check digit is derived from the payload and does not add random entropy.
Recommended defaults:
- 16 for internal systems up to millions of IDs
- 20 for public tokens or cross-org use
- 22 for long-lived, internet-scale identifiers
See the spec for collision-bound tables.
Implementation guidance
For project integration guidance, see:
- Human implementation guide: https://github.com/snapsynapse/hardguard25/blob/main/docs/IMPLEMENTATION.md
- Assistant guide: https://hardguard25.com/.well-known/assistant-guide.txt
- Assistant guide SHA-256: https://hardguard25.com/.well-known/assistant-guide.txt.sha256
When NOT to Use HardGuard25
- Cryptographic keys (use proper key derivation)
- Blockchain consensus (use domain-specific formats)
- Systems requiring global UUID guarantees (use UUIDv7 or ULID)
- Machine-only contexts where no human ever sees the ID
Reference
- Spec: https://github.com/snapsynapse/hardguard25/blob/main/SPEC.md
- Homepage: https://hardguard25.com/
- Source: https://github.com/snapsynapse/hardguard25
- Other languages: JavaScript, Go (same repo)
License
MIT
Metadata
Release files for hardguard25 1.3.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hardguard25-1.3.8.tar.gz | 6.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hardguard25-1.3.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 13.1 kB
Release files / hardguard25-1.3.8.tar.gz
| Download URL | hardguard25-1.3.8.tar.gz |
|---|---|
| Size | 6.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9ea511598dac76da9b0086d6f212d53bf106d1135c486167d6314a0c3ef198f1
|
|
BLAKE2b-256 checksum How to use checksums |
9276c95c5e22d07a5e1359664f50e26accd94bba294dc09de753d6b8c8fbbf24
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency logRelease files / hardguard25-1.3.8-py3-none-any.whl
| Download URL | hardguard25-1.3.8-py3-none-any.whl |
|---|---|
| Size | 6.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
056cb6e98bc69f12c5544f7206d31caa6e02acc0cd25b231cba4c69aac2f735b
|
|
BLAKE2b-256 checksum How to use checksums |
12bd0afec2d4b6720914a3b23fc2007d4b6e94eb59abfc181fe34a5b3e72496e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency log