DEV Community

Cover image for HardGuard25: A 25-character alphabet for human-readable unique IDs
snapsynapse
snapsynapse

Posted on • Originally published at sam-rogers.com

HardGuard25: A 25-character alphabet for human-readable unique IDs

Standard ID alphabets include characters that look identical at normal reading sizes. O and 0. I and 1 and l. S and 5. B and 8. For dyslexic readers, d and b, q and p. Every one of these is a support ticket, a failed lookup, or a phone call where someone spells the same code three times.

Crockford Base32 has been the go-to fix since 2002, but it only removes 4 characters. HardGuard25 removes 11: the digit lookalikes, the dyslexia mirror pairs, and operator lookalikes like T (+) and X (*) that break spreadsheets and URLs.

The alphabet:

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
Enter fullscreen mode Exit fullscreen mode

The rule: when a letter and a digit compete for the same visual slot, the digit always wins.

Quickstart

JavaScript

npm install @snapsynapse/hardguard25
Enter fullscreen mode Exit fullscreen mode
import { generate, validate, normalize, checkDigit } from '@snapsynapse/hardguard25';

generate(8);                          // "AC3H7PUW"
generate(8, { checkDigit: true });    // "AC3H7PUW" + check char
validate("AC3H-7PUW");               // true
normalize("ac3h-7puw");              // "AC3H7PUW"
Enter fullscreen mode Exit fullscreen mode

Python

pip install hardguard25
Enter fullscreen mode Exit fullscreen mode
from hardguard25 import generate, validate, normalize, check_digit

generate(8)                           # "AC3H7PUW"
generate(8, check_digit=True)         # "AC3H7PUW" + check char
validate("AC3H-7PUW")                # True
normalize("ac3h-7puw")               # "AC3H7PUW"
Enter fullscreen mode Exit fullscreen mode

Go

import "github.com/snapsynapse/hardguard25/go"

id, _ := hardguard25.Generate(8)
ok := hardguard25.Validate("AC3H-7PUW")
s := hardguard25.Normalize("ac3h-7puw")
Enter fullscreen mode Exit fullscreen mode

No library needed? The alphabet is the standard. Use it directly: 0123456789ACDFGHJKMNPRUWY

Where it fits

Order numbers, tracking codes, license keys, patient IDs, booking references, device IDs, promo codes, QR payloads, one-time passcodes. If it gets printed on a label, read over the phone, entered by hand, or scanned by OCR, it should be HardGuard25.

How long should IDs be?

Length Unique IDs Good for
4 390,625 Small inventory, tickets
6 244 million Medium businesses
8 152 billion Large systems
16 3.55 x 10^22 Cross-system identifiers

Each character provides 4.64 bits of entropy.

When not to use it

Cryptographic keys (use proper key derivation), blockchain consensus (use domain-specific formats), systems requiring UUID guarantees (use UUIDv7 or ULID), or machine-only contexts where no human ever sees the ID.

Links

Spec is CC BY 4.0. Code is MIT.


What character set are you using for human-facing IDs? Curious how many people have hit the O/0 problem in production.

Top comments (0)