Crypto addresses are currently accepted on shape alone — a single-character mutation of a valid address is still detected as a wallet address.
Evidence
src/CryptoAddress.ts:60-79 validates Bitcoin addresses only by character set and length
src/CryptoAddress.ts:107-167 accepts checksum-invalid Base58Check and Bech32/Bech32m strings
src/CryptoAddress.ts:170-184 accepts every mixed-case Ethereum address without EIP-55
- Negative tests only cover length (
tests/CryptoAddress.test.ts:68-89)
Proposal
After the existing cheap shape prefilter:
- Legacy BTC (P2PKH/P2SH): Base58Check decode, require 25-byte payload, version byte
0x00/0x05, verify 4-byte double-SHA-256 checksum
- Bech32/Bech32m: verify polymod (Bech32 for v0, Bech32m for v1-16), validate witness program length/padding, accept all-upper or all-lower, reject mixed case
- ETH: accept all-lower/all-upper freely; require EIP-55 checksum for mixed-case
Tests to add
- One-character mutations of known-valid BTC/Base58Check and Bech32 addresses → reject
- Valid uppercase Bech32 → accept
- Valid mixed-case EIP-55 → accept; same address with one case bit flipped → reject
Performance note
Keep regexes as prefilters so the hashing cost only applies to shape candidates. Inputs are short and bounded. Deno has crypto.subtle for SHA-256; Keccak-256 for EIP-55 needs a small vendored implementation or a dependency decision.
Crypto addresses are currently accepted on shape alone — a single-character mutation of a valid address is still detected as a wallet address.
Evidence
src/CryptoAddress.ts:60-79validates Bitcoin addresses only by character set and lengthsrc/CryptoAddress.ts:107-167accepts checksum-invalid Base58Check and Bech32/Bech32m stringssrc/CryptoAddress.ts:170-184accepts every mixed-case Ethereum address without EIP-55tests/CryptoAddress.test.ts:68-89)Proposal
After the existing cheap shape prefilter:
0x00/0x05, verify 4-byte double-SHA-256 checksumTests to add
Performance note
Keep regexes as prefilters so the hashing cost only applies to shape candidates. Inputs are short and bounded. Deno has
crypto.subtlefor SHA-256; Keccak-256 for EIP-55 needs a small vendored implementation or a dependency decision.