Encoding, hashing and tokens
Encoding bugs are quiet. Data goes in, a string comes out, and nothing complains until another system reads that string differently. Base64 and base64url use different characters for two of their sixty-four symbols, and padding is optional in one and expected in the other; a decoder that accepts both hides the mismatch until a strict one does not. Percent-encoding has several conventions for which characters stay as they are and whether a space becomes %20 or +.
Most of the rest comes down to bytes versus text. A hash is computed over bytes, so the same word hashed as UTF-8 and as UTF-16 gives different digests, and a string that looks identical may contain a different normalisation form or an invisible character. Every answer in this group states how many bytes were processed and how the input was turned into bytes, and input can be given as text, hex or base64 when the bytes matter.
Secrets need a warning of their own. An HMAC needs a key, and a key placed in a URL passes through proxies and logs on its way to any server, this one included. The HMAC endpoints are useful for test vectors and for learning, not for production keys. The same applies to JWTs: this group decodes them, and decoding is not verification.
Hashes cover the common families, from MD5 and SHA-1, which are named as broken for security use, to SHA-2, SHA-3, BLAKE2 and BLAKE3.
Pages on known traps
- Decode a JWT: Decode a JSON Web Token's header and payload in one request. Decoding shows what a token claims; it cannot show whether the claim is true or the token genuine.
Every endpoint in this group
/encode/base64?[text=]&[hex=]&[b64=]
Encode bytes as RFC 4648 base64, standard alphabet, with padding
text (optional): input as UTF-8 text (in a URL write '+' as %2B, space as %20); hex (optional): input bytes as hex, instead of text; b64 (optional): input bytes as base64, instead of text ('+' is kept literally)
curl "https://agent-helper.org/encode/base64?text=hello%20world"
/encode/base64url?[text=]&[hex=]&[b64=]&[padding=]
Encode bytes as RFC 4648 base64url (-_ alphabet)
text (optional): input as UTF-8 text (in a URL write '+' as %2B, space as %20); hex (optional): input bytes as hex, instead of text; b64 (optional): input bytes as base64, instead of text ('+' is kept literally); padding (optional): include '=' padding
curl "https://agent-helper.org/encode/base64url?text=hello%20world"
/encode/base32?[text=]&[hex=]&[b64=]&[padding=]
Encode bytes as RFC 4648 base32
text (optional): input as UTF-8 text (in a URL write '+' as %2B, space as %20); hex (optional): input bytes as hex, instead of text; b64 (optional): input bytes as base64, instead of text ('+' is kept literally); padding (optional): include '=' padding
curl "https://agent-helper.org/encode/base32?text=hello%20world"
/encode/base58?[text=]&[hex=]&[b64=]
Encode bytes as base58, Bitcoin alphabet, no checksum
text (optional): input as UTF-8 text (in a URL write '+' as %2B, space as %20); hex (optional): input bytes as hex, instead of text; b64 (optional): input bytes as base64, instead of text ('+' is kept literally)
curl "https://agent-helper.org/encode/base58?text=hello%20world"
/encode/hex?[text=]&[hex=]&[b64=]
Encode bytes as lowercase hexadecimal
text (optional): input as UTF-8 text (in a URL write '+' as %2B, space as %20); hex (optional): input bytes as hex, instead of text; b64 (optional): input bytes as base64, instead of text ('+' is kept literally)
curl "https://agent-helper.org/encode/hex?text=hello%20world"
/decode/base64?value=
Decode base64 (standard or URL-safe, padding optional) to text (or hex if not UTF-8)
value: base64 string
curl "https://agent-helper.org/decode/base64?value=aGVsbG8gd29ybGQ="
/decode/base64url?value=
Decode base64url to text (or hex if not UTF-8)
value: base64url string
curl "https://agent-helper.org/decode/base64url?value=aGVsbG8gd29ybGQ"
/decode/base32?value=
Decode base32 to text (or hex if not UTF-8)
value: base32 string
curl "https://agent-helper.org/decode/base32?value=NBSWY3DPEB3W64TMMQ======"
/decode/base58?value=
Decode base58 (Bitcoin alphabet) to text (or hex if not UTF-8)
value: base58 string
curl "https://agent-helper.org/decode/base58?value=StV1DL6CwTryKyV"
/decode/hex?value=
Decode hex to text (or hex if not UTF-8)
value: hex string
curl "https://agent-helper.org/decode/hex?value=68656c6c6f20776f726c64"
/encode/url?text=&[mode=]
Percent-encode text (RFC 3986), stating which characters stay unencoded
text: text to encode; mode (optional): component (encode everything but A-Z a-z 0-9 -._~), path (also keep /), form (space becomes +)
curl "https://agent-helper.org/encode/url?text=a%20b%26c%2Fd%3F%C3%A9"
/decode/url?value=&[plus=]
Decode percent-encoding
value: percent-encoded text; to pass it here, encode it once more (%25 for %); plus (optional): treat + as space (form encoding)
curl "https://agent-helper.org/decode/url?value=caf%25C3%25A9%2520au%2520lait"
/encode/punycode?domain=
Internationalised domain name to ASCII (IDNA 2008 / punycode)
domain: Unicode domain name
curl "https://agent-helper.org/encode/punycode?domain=b%C3%BCcher.example"
/decode/punycode?domain=
ASCII (xn--) domain name to Unicode
domain: ASCII domain with xn-- labels
curl "https://agent-helper.org/decode/punycode?domain=xn--bcher-kva.example"
/encode/hash/{alg}?[text=]&[hex=]&[b64=]&[output=]
Hash digest: md5, sha1, sha256, sha512, sha3, blake2, blake3, crc32...
alg: one of md5, sha1, sha224, sha256, sha384, sha512, sha3-256, sha3-512, blake2b, blake2s, blake3, crc32, adler32; text (optional): input as UTF-8 text (in a URL write '+' as %2B, space as %20); hex (optional): input bytes as hex, instead of text; b64 (optional): input bytes as base64, instead of text ('+' is kept literally); output (optional): hex (default) or base64
curl "https://agent-helper.org/encode/hash/sha256?text=hello"
/encode/hmac/{alg}?key=&[text=]&[hex=]&[b64=]&[output=]
HMAC of a message with a key
alg: one of sha1, sha256, sha384, sha512, sha3-256, md5; text (optional): input as UTF-8 text (in a URL write '+' as %2B, space as %20); hex (optional): input bytes as hex, instead of text; b64 (optional): input bytes as base64, instead of text ('+' is kept literally); key: key as UTF-8 text; output (optional): hex (default) or base64
curl "https://agent-helper.org/encode/hmac/sha256?text=message&key=secret"
/encode/hmac/{alg}/verify?key=&signature=&[text=]&[hex=]&[b64=]
Check an HMAC signature (constant-time comparison)
alg: one of sha1, sha256, sha384, sha512, sha3-256, md5; text (optional): input as UTF-8 text (in a URL write '+' as %2B, space as %20); hex (optional): input bytes as hex, instead of text; b64 (optional): input bytes as base64, instead of text ('+' is kept literally); key: key as UTF-8 text; signature: expected HMAC, hex or base64
curl "https://agent-helper.org/encode/hmac/sha256/verify?text=message&key=secret&signature=8b5f48702995c1598c573db1e21866a9b825d4a794d169d7060a03605796360b"
/decode/jwt?token=
Decode a JWT header and payload (signature NOT verified)
token: JSON Web Token
curl "https://agent-helper.org/decode/jwt?token=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyfQ.sig"
Decode a JWT: Decode a JSON Web Token's header and payload in one request. Decoding shows what a token claims; it cannot show whether the claim is true or the token genuine.