Base58Check Encode and Verify

Encode payloads as Base58 with a double SHA-256 checksum, preserve leading zero bytes, and reject corrupted input on decode.

PythonData Integrity

Code

snippet
import hashlib

ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"


def b58encode(raw: bytes) -> str:
    number = int.from_bytes(raw, "big")
    digits: list[str] = []
    while number:
        number, remainder = divmod(number, 58)
        digits.append(ALPHABET[remainder])
    leading_zeros = len(raw) - len(raw.lstrip(b"\0"))
    return ALPHABET[0] * leading_zeros + "".join(reversed(digits))


def b58decode(text: str) -> bytes:
    number = 0
    for char in text:
        index = ALPHABET.find(char)
        if index < 0:
            raise ValueError(f"invalid base58 character: {char!r}")
        number = number * 58 + index
    body = number.to_bytes((number.bit_length() + 7) // 8, "big") if number else b""
    leading_ones = len(text) - len(text.lstrip(ALPHABET[0]))
    return b"\0" * leading_ones + body


def checksum(payload: bytes) -> bytes:
    first = hashlib.sha256(payload).digest()
    return hashlib.sha256(first).digest()[:4]


def encode_check(payload: bytes) -> str:
    return b58encode(payload + checksum(payload))


def decode_check(text: str) -> bytes:
    raw = b58decode(text)
    if len(raw) < 5:
        raise ValueError("input too short to contain a checksum")
    payload, supplied = raw[:-4], raw[-4:]
    if checksum(payload) != supplied:
        raise ValueError("checksum mismatch")
    return payload


if __name__ == "__main__":
    token = encode_check(b"\x00hello")
    print(token, decode_check(token))
    corrupted = token[:-1] + ("1" if token[-1] != "1" else "2")
    try:
        decode_check(corrupted)
    except ValueError as error:
        print("rejected:", error)