Regex Bitcoin address
A Bitcoin address isn't just one format: legacy P2PKH/P2SH addresses ("1...", "3...") use the Base58 alphabet, but the native SegWit Bech32 format ("bc1...", BIP 173) uses a completely different 32-character alphabet, deliberately excluding "1", "b", "i" and "o" to avoid visual confusion. A real npm library nonetheless applies the Base58 alphabet to a Bech32 address - since the two alphabets barely overlap, a good chunk of legitimate Bech32 addresses fail. Two other attempts simply ignore Bech32 altogether. Here's a pattern handling both systems correctly, compared against these three attempts.
/^(?:[13][a-km-zA-HJ-NP-Z1-9]{25,34}|bc1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,87})$/passes 20/20 cases
Comparison of existing patterns
| Source | pattern | Score on the corpus | ReDoS |
|---|---|---|---|
| kevva/bitcoin-regex (package npm réel) — ignore complètement Bech32, toute adresse SegWit native moderne (« bc1… »), pourtant majoritaire aujourd'hui, est rejetée | (?:^(?:[13][a-km-zA-HJ-NP-Z1-9]{25,34})$) | 18 / 20 | safe |
| Article technique mokagio (2014) — même limitation, aucune branche pour Bech32 ; l'auteur reconnaît lui-même que la spec Bitcoin déconseille cette approche sans vérification de checksum | ^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$ | 18 / 20 | safe |
| iHateRegex — applique l'alphabet Base58 (qui exclut 0/O/I/l) à la branche bc1, alors que Bech32 utilise un alphabet totalement différent (exclut 1/b/i/o) ; plage de longueur trop courte pour du P2WSH | ^(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$ | 17 / 20 | safe |
Implementation
const re = new RegExp("^(?:[13][a-km-zA-HJ-NP-Z1-9]{25,34}|bc1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,87})$", "");
re.test(input);Limits
- Valide seulement la FORME et l'alphabet : ne calcule ni le checksum Base58Check (SHA-256 double, 4 premiers octets) des adresses legacy, ni le checksum polynomial Bech32 — une adresse syntaxiquement valide selon ce motif peut avoir un checksum faux et ne correspondre à aucune adresse réellement dérivable d'une clé publique.
- Ne distingue pas les adresses P2PKH (préfixe « 1 ») des adresses P2SH (préfixe « 3 ») dans son résultat, alors qu'elles correspondent à des mécanismes de verrouillage différents (clé publique simple vs script arbitraire, souvent multi-signature).
- N'accepte que le réseau principal (mainnet) : le réseau de test (testnet) utilise ses propres préfixes (« m »/« n » pour P2PKH, « 2 » pour P2SH, « tb1 » pour Bech32), non couverts ici.
- La casse Bech32 doit être uniformément minuscule ou uniformément majuscule, jamais mélangée (le checksum polynomial en dépend) : ce motif n'accepte que la forme tout-minuscule, la plus répandue en pratique dans les portefeuilles et explorateurs de blocs.