base32

package
v2.7.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 24, 2025 License: MIT Imports: 2 Imported by: 0

README

Base32 Package

Go Reference

Crockford Base32 encoding and CRC-10 checksums for human-readable, error-correcting identifiers.

Features

  • Crockford Base32 Encoding

    • Human-readable alphabet (excludes ambiguous characters: I, L, O, U)
    • Case-insensitive decoding
    • Automatic error correction (I→1, L→1, O→0)
    • Fixed-length and compact encoding modes
    • URL-safe output
  • CRC-10 Checksums

    • 99.9%+ error detection rate
    • Detects single character errors (100%)
    • Detects transpositions (99.9%+)
    • Detects double errors (99.9%+)
    • Only 2 characters overhead

Installation

go get github.com/jasoet/pkg/v2

Quick Start

package main

import (
    "fmt"
    "github.com/jasoet/pkg/v2/base32"
)

func main() {
    // Encode a number
    id := base32.EncodeBase32(12345, 8)  // "0000C1P9"

    // Add checksum for error detection
    idWithChecksum := base32.AppendChecksum(id)

    // Validate checksum
    if base32.ValidateChecksum(idWithChecksum) {
        fmt.Println("Valid ID!")
    }

    // Decode back
    value, _ := base32.DecodeBase32(id)
    fmt.Println(value)  // 12345
}

Use Cases

1. URL Shorteners
// Database ID to short code
databaseID := uint64(123456789)
shortCode := base32.EncodeBase32Compact(databaseID)
// https://short.url/3QTYY1

// Decode back
decoded, _ := base32.DecodeBase32(shortCode)
2. Order/Transaction IDs
// Generate order ID with timestamp and sequence
timestamp := uint64(time.Now().Unix())
sequence := uint64(12345)

timeCode := base32.EncodeBase32(timestamp, 8)
seqCode := base32.EncodeBase32(sequence, 4)

orderID := base32.AppendChecksum("ORD-" + timeCode + "-" + seqCode)
// ORD-6HG4K2N0-00C1P9XY
3. License Keys
productID := uint64(42)
customerID := uint64(789)

product := base32.EncodeBase32(productID, 2)
customer := base32.EncodeBase32(customerID, 4)

licenseKey := base32.AppendChecksum(product + customer)
// Format: 16-00NC-XY
4. Voucher/Coupon Codes
voucherID := uint64(9999)
code := base32.EncodeBase32(voucherID, 4)
codeWithChecksum := base32.AppendChecksum(code)
// 09ZZ-XY (easy to type, error-correcting)
5. IoT Device IDs
deviceSerial := uint64(123456)
deviceID := base32.EncodeBase32Compact(deviceSerial)
// Compact, human-readable device identifier

API Reference

Base32 Encoding
EncodeBase32(value uint64, length int) string

Encodes an unsigned integer to a fixed-length Base32 string.

base32.EncodeBase32(42, 4)     // "0016"
base32.EncodeBase32(12345, 6)  // "00C1P9"
EncodeBase32Compact(value uint64) string

Encodes to the minimum number of characters needed.

base32.EncodeBase32Compact(0)      // "0"
base32.EncodeBase32Compact(12345)  // "C1P9"
DecodeBase32(encoded string) (uint64, error)

Decodes a Base32 string to an unsigned integer.

value, err := base32.DecodeBase32("C1P9")  // 12345, nil
value, err := base32.DecodeBase32("c1p9")  // 12345, nil (case-insensitive)
value, err := base32.DecodeBase32("C1PO")  // 12345, nil (O→0 correction)
NormalizeBase32(input string) string

Normalizes Base32 input by:

  • Converting to uppercase
  • Removing dashes and spaces
  • Correcting common mistakes (I→1, L→1, O→0)
base32.NormalizeBase32("abc-def")  // "ABCDEF"
base32.NormalizeBase32("1O 2I")    // "1021"
IsValidBase32Char(c rune) bool

Checks if a character is valid in Base32 encoding.

base32.IsValidBase32Char('A')  // true
base32.IsValidBase32Char('O')  // true (auto-corrected)
base32.IsValidBase32Char('U')  // false
Checksums
CalculateChecksum(data string) string

Computes a 2-character CRC-10 checksum.

checksum := base32.CalculateChecksum("ABC123")  // "XY"
AppendChecksum(data string) string

Adds checksum to the end of data.

withChecksum := base32.AppendChecksum("ABC123")  // "ABC123XY"
ValidateChecksum(input string) bool

Verifies checksum validity.

valid := base32.ValidateChecksum("ABC123XY")  // true
valid := base32.ValidateChecksum("ABC123ZZ")  // false
StripChecksum(input string) string

Removes the last 2 characters (checksum).

data := base32.StripChecksum("ABC123XY")  // "ABC123"
ExtractChecksum(input string) string

Extracts the last 2 characters (checksum).

checksum := base32.ExtractChecksum("ABC123XY")  // "XY"

Error Detection

The CRC-10 checksum provides excellent error detection:

Error Type Detection Rate
Single character error 100%
Transposition (AB→BA) 99.9%+
Double errors 99.9%+
Insertion/deletion High
Example
// Valid ID
validID := base32.AppendChecksum("ABC123")

// Corrupted ID (A → X)
corrupted := "XBC123" + base32.ExtractChecksum(validID)
base32.ValidateChecksum(corrupted)  // false - detected!

// Transposition (AB → BA)
chars := []rune(validID)
chars[0], chars[1] = chars[1], chars[0]
transposed := string(chars)
base32.ValidateChecksum(transposed)  // false - detected!

Examples

Run comprehensive examples:

go run -tags=example ./base32/examples

See examples/main.go for detailed usage patterns.

Performance

Benchmarks on modern hardware:

BenchmarkEncodeBase32-8          50000000    25.3 ns/op
BenchmarkDecodeBase32-8          30000000    45.2 ns/op
BenchmarkCalculateChecksum-8     10000000   125.0 ns/op
BenchmarkValidateChecksum-8       8000000   160.0 ns/op

Alphabet Reference

Crockford Base32 Alphabet
0 1 2 3 4 5 6 7 8 9 A B C D E F G H J K M N P Q R S T V W X Y Z

Excluded characters:

  • I - Looks like 1 (auto-corrected to 1)
  • L - Looks like 1 (auto-corrected to 1)
  • O - Looks like 0 (auto-corrected to 0)
  • U - Could be confused with V

This design minimizes human transcription errors.

Best Practices

  1. Always use checksums for user-facing IDs

    // ✓ Good
    id := base32.AppendChecksum(data)
    
    // ✗ Avoid
    id := data  // No error detection
    
  2. Normalize user input

    userInput := "ab-cd-ef"
    normalized := base32.NormalizeBase32(userInput)
    
  3. Use fixed-length encoding for databases

    // Consistent length for indexing
    id := base32.EncodeBase32(value, 10)
    
  4. Use compact encoding for URLs

    // Shorter URLs
    shortCode := base32.EncodeBase32Compact(value)
    

Migration from tix-core

If migrating from github.com/jasoet/tix-core/encoding:

Before:

import "github.com/jasoet/tix-core/encoding"

After:

import "github.com/jasoet/pkg/v2/base32"

API is 100% compatible - only the import path and package name change.

Contributing

See the main pkg/v2 repository for contribution guidelines.

License

MIT License - see LICENSE for details.


Part of github.com/jasoet/pkg/v2 - Production-ready Go utility packages.

Documentation

Overview

Package base32 provides Crockford Base32 encoding and CRC-10 checksums for human-readable, error-correcting identifiers.

The Base32 implementation uses Crockford's alphabet (excludes I, L, O, U) and provides case-insensitive decoding with automatic error correction.

The CRC-10 checksum provides 99.9%+ error detection for single character errors, transpositions, and double errors.

Example:

// Encode a value
id := base32.EncodeBase32(12345, 8)  // "0000C1P9"

// Add checksum
idWithChecksum := base32.AppendChecksum(id)

// Validate
if base32.ValidateChecksum(idWithChecksum) {
    // Valid ID
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AppendChecksum

func AppendChecksum(data string) string

AppendChecksum adds a 2-character checksum to the end of the data.

This is the recommended way to create checksummed strings.

Example:

id := base32.EncodeBase32(12345, 6)            // "00C1P9"
idWithChecksum := base32.AppendChecksum(id)   // "00C1P9XY"

Parameters:

  • data: The Base32 string to checksum

Returns:

  • The input string with a 2-character checksum appended

func CalculateChecksum

func CalculateChecksum(data string) string

CalculateChecksum computes a 2-character Base32 checksum using CRC-10.

The checksum provides 99.9%+ error detection for:

  • Single character errors
  • Character transpositions
  • Double errors
  • Most insertion/deletion errors

The CRC-10 algorithm processes each Base32 character (5 bits) and produces a 10-bit checksum, which is then encoded as 2 Base32 characters.

Example:

checksum := base32.CalculateChecksum("ABC123")  // "XY"
withChecksum := base32.AppendChecksum("ABC123") // "ABC123XY"

Parameters:

  • data: The Base32 string to checksum

Returns:

  • A 2-character Base32 checksum

func DecodeBase32

func DecodeBase32(encoded string) (uint64, error)

DecodeBase32 decodes a Base32 string to an unsigned integer.

Returns an error if the string contains invalid characters. Supports case-insensitive input and common error corrections (I→1, L→1, O→0).

Example:

val, err := base32.DecodeBase32("C1P9")  // 12345, nil
val, err := base32.DecodeBase32("c1p9")  // 12345, nil (case-insensitive)
val, err := base32.DecodeBase32("C1PO")  // 12345, nil (O→0 correction)

Parameters:

  • encoded: The Base32-encoded string to decode

Returns:

  • The decoded unsigned integer value
  • An error if the input contains invalid characters

func EncodeBase32

func EncodeBase32(value uint64, length int) string

EncodeBase32 encodes an unsigned integer to a Base32 string of specified length.

The encoded value is left-padded with '0's to reach the specified length. Uses Crockford's Base32 alphabet (0-9, A-Z excluding I, L, O, U).

Example:

base32.EncodeBase32(42, 4)     // "0016"
base32.EncodeBase32(999, 3)    // "0ZZ"
base32.EncodeBase32(32, 2)     // "10"

Parameters:

  • value: The unsigned integer to encode
  • length: The minimum length of the output string

Returns:

  • A Base32-encoded string of at least 'length' characters

func EncodeBase32Compact

func EncodeBase32Compact(value uint64) string

EncodeBase32Compact encodes a value to the minimum number of Base32 characters needed.

Unlike EncodeBase32, this function does not pad the output to a fixed length.

Example:

base32.EncodeBase32Compact(0)      // "0"
base32.EncodeBase32Compact(31)     // "Z"
base32.EncodeBase32Compact(32)     // "10"
base32.EncodeBase32Compact(12345)  // "C1P9"

func ExtractChecksum

func ExtractChecksum(input string) string

ExtractChecksum extracts the last 2 characters (checksum) from a string.

Returns an empty string if the input has fewer than 2 characters.

Example:

checksum := base32.ExtractChecksum("ABC123XY")  // "XY"
checksum := base32.ExtractChecksum("A")         // ""

Parameters:

  • input: The string with checksum appended

Returns:

  • The last 2 characters of the input

func IsValidBase32Char

func IsValidBase32Char(c rune) bool

IsValidBase32Char returns true if the character is valid in Base32 encoding.

Valid characters include: 0-9, A-Z (excluding I, L, O, U), and their lowercase equivalents. Also accepts I, L, O as they are auto-corrected to 1, 1, 0.

Example:

base32.IsValidBase32Char('A')  // true
base32.IsValidBase32Char('a')  // true
base32.IsValidBase32Char('O')  // true (auto-corrected to 0)
base32.IsValidBase32Char('U')  // false

func NormalizeBase32

func NormalizeBase32(input string) string

NormalizeBase32 normalizes a Base32 string by:

  • Converting to uppercase
  • Removing dashes and spaces
  • Correcting common mistakes (I→1, L→1, O→0)

This function is useful for processing user input to ensure consistency.

Example:

base32.NormalizeBase32("abc-def")   // "ABCDEF"
base32.NormalizeBase32("1O 2I")     // "1021"
base32.NormalizeBase32("hell0")     // "HELL0"

func StripChecksum

func StripChecksum(input string) string

StripChecksum removes the last 2 characters (checksum) from a string.

Returns an empty string if the input has 2 or fewer characters.

Example:

data := base32.StripChecksum("ABC123XY")  // "ABC123"
data := base32.StripChecksum("AB")        // ""

Parameters:

  • input: The string with checksum appended

Returns:

  • The input string without the last 2 characters

func ValidateChecksum

func ValidateChecksum(input string) bool

ValidateChecksum verifies that the checksum in a string is correct.

Expected format: [data][2 chars checksum]

This function is useful for validating user input or detecting data corruption.

Example:

valid := base32.ValidateChecksum("ABC123XY")  // true if XY is correct checksum
valid := base32.ValidateChecksum("ABC123ZZ")  // false if ZZ is wrong

Parameters:

  • input: The string with checksum appended (minimum 3 characters)

Returns:

  • true if the checksum is valid, false otherwise

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL