How BEP 53 Supports Hex and Base32 Magnet Hashes

BitTorrent Enhancement Proposal 53 (BEP 53) standardizes and expands the magnet URI specification across BitTorrent clients, particularly regarding parameter formatting and exact topic (xt) handling. A key aspect of magnet links is identifying torrents via the 160-bit SHA-1 info-hash, which can appear as either a 40-character hexadecimal string or a 32-character Base32 encoded string. This article explains how BEP 53 accommodates both formats, how client parsers differentiate between them, and how normalization occurs internally.

The Underlying 160-Bit Info-Hash

BitTorrent v1 identifies swarms using a 20-byte (160-bit) SHA-1 cryptographic hash of the .torrent file’s info dictionary. When sharing this hash inside a magnet URI, the binary data must be encoded into a URL-safe text format within the xt (exact topic) parameter using the urn:btih: prefix:

xt=urn:btih:<encoded-hash>

Because 160 bits can be represented in multiple standard text-encoding schemes, clients must be able to read and convert either scheme back to the exact same 20-byte binary sequence.

Encoding Schemes Supported

  1. Hexadecimal (Base16):
    • Length: 40 characters.
    • Bit density: Each character represents 4 bits (\(160 / 4 = 40\)).
    • Alphabet: Case-insensitive alphanumeric characters 0-9 and a-f (or A-F).
    • Example: urn:btih:4a5c839f...
  2. Base32 (RFC 4648):
    • Length: 32 characters.
    • Bit density: Each character represents 5 bits (\(160 / 5 = 32\)).
    • Alphabet: Case-insensitive characters A-Z and 2-7 (unpadded).
    • Example: urn:btih:JJNIGN47...

How Parsers Detect the Encoding

BitTorrent clients and URI parsers distinguish between the two encodings using deterministic length checks and character validation:

If a string does not meet either length or contains characters outside the expected sets, the magnet URI is rejected as malformed.

Hash Normalization in BEP 53

While BEP 53 allows both encodings to exist in user-facing magnet links for backward compatibility with older implementations, compliant clients normalize the input into raw 20-byte binary structures upon parsing. Once decoded into memory: