Base32 Encoding From Scratch In Go

Often times we need to generate a unique token or ID for some aspect of our Go application. A simple way to achieve this is through the crypto and encoding packages to create base32 encoded strings.

What Is Base32 Encoding?

But what use is base32? From this stackoverflow answer:

Like any other “ASCII-only” encoding, base32’s primary purpose is to make sure that the data it encodes will survive transportation through systems or protocols which have special restrictions on the range of characters they will accept and emerge unmodified. For example, b32-encoded data can be passed to a system that accepts single-byte character input, or UTF-8 encoded string input, or appended to a URL, or added to HTML content, without being mangled or resulting in an invalid form. Base64 (which is much more common) is used for the exact same reasons. The main advantage of b32 over b64 is that it is much more human-readable. That’s not much of an advantage because the data will typically be processed by computers, hence the relative rarity of b32 versus b64 (which is more efficient space-wise). Update: there’s the same question asked about Base64 here: What is base 64 encoding used for?

Source: What Is Base32 Encoding?

What Is Base64 Encoding?

Alternatively, we could use base64 encoding as well.

When you have some binary data that you want to ship across a network, you generally don’t do it by just streaming the bits and bytes over the wire in a raw format. Why? because some media are made for streaming text. You never know – some protocols may interpret your binary data as control characters (like a modem), or your binary data could be screwed up because the underlying protocol might think that you’ve entered a special character combination (like how FTP translates line endings). So to get around this, people encode the binary data into characters. Base64 is one of these types of encodings. Why 64? Because you can generally rely on the same 64 characters being present in many character sets, and you can be reasonably confident that your data’s going to end up on the other side of the wire uncorrupted.

Source: What Is Base64 Encoding Used For?

package main

import (
    "crypto/rand"
    "crypto/sha256"
    "crypto/sha512"
    "encoding/base32"
    "encoding/base64"
    "fmt"
)

func main() {

    // Base 32 Encoding

    // Seed some random bytes

    randomBytes := make([]byte, 16)

    _, err := rand.Read(randomBytes)

    if err != nil {
        panic(err)
    }

    plaintext := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(randomBytes)

    hash := sha256.Sum256([]byte(plaintext))

    fmt.Println(plaintext, hash)

    // Base 64 Encoding

    // Seed new random bytes

    newRandomBytes := make([]byte, 32)

    _, err = rand.Read(newRandomBytes)

    if err != nil {
        panic(err)
    }

    b64Plaintext := base64.StdEncoding.WithPadding(base64.NoPadding).EncodeToString(newRandomBytes)

    b64Hash := sha512.Sum512([]byte(b64Plaintext))

    fmt.Println(b64Plaintext, b64Hash)
}
}