Go BLAKE3 Hash Code Example (Online Runner)

Go BLAKE3 hashing examples with digest length control, keyed hashing, and context strings.

Online calculator: use the site BLAKE3 text tool.

Note: This snippet requires locally installed dependencies and will not run in the online runner. Run it locally with: go mod init blake3-demo && go get github.com/zeebo/blake3 && go run blake3_basic.go

Calculation method

BLAKE3 supports variable digest lengths, keyed hashing, and context-based derivation. Only one of key or context can be set.

Implementation notes

  • Package: github.com/zeebo/blake3.
  • Implementation: BLAKE3 is an XOF, so digestLen controls output size in bytes.
  • Notes: keyed mode is a MAC; context mode is for domain separation.

Text hashing example

go
package main

import (
	"encoding/hex"
	"fmt"
	"io"

	"github.com/zeebo/blake3"
)

func blake3Text(text string, digestLen int) string {
	hasher := blake3.New()
	hasher.Write([]byte(text))
	out := make([]byte, digestLen)
	io.ReadFull(hasher.Digest(), out)
	return hex.EncodeToString(out)
}

func main() {
	fmt.Println(blake3Text("hello world", 32))
}

File hashing example

go
package main

import (
	"encoding/hex"
	"fmt"
	"io"
	"os"

	"github.com/zeebo/blake3"
)

func blake3File(path string, digestLen int) (string, error) {
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer file.Close()

	hasher := blake3.New()
	if _, err := io.Copy(hasher, file); err != nil {
		return "", err
	}
	out := make([]byte, digestLen)
	if _, err := io.ReadFull(hasher.Digest(), out); err != nil {
		return "", err
	}
	return hex.EncodeToString(out), nil
}

func main() {
	file, err := os.CreateTemp("", "blake3-example-*.bin")
	if err != nil {
		panic(err)
	}
	defer os.Remove(file.Name())
	file.WriteString("example payload\n")
	file.Close()

	value, err := blake3File(file.Name(), 32)
	if err != nil {
		panic(err)
	}
	fmt.Println(value)
}

Complete script (implementation + tests)

go
package main

import (
	"encoding/hex"
	"errors"
	"fmt"
	"io"

	"github.com/zeebo/blake3"
)

const (
	defaultDigestLen = 32
	maxDigestLen     = 64
)

func blake3Text(text string, digestLen int, key string, context string) (string, error) {
	if key != "" && context != "" {
		return "", errors.New("use either key or context, not both")
	}
	if digestLen == 0 {
		digestLen = defaultDigestLen
	}
	if digestLen < 1 || digestLen > maxDigestLen {
		return "", errors.New("digest length must be between 1 and 64 bytes")
	}

	var hasher *blake3.Hasher
	switch {
	case key != "":
		if len(key) != 32 {
			return "", errors.New("BLAKE3 key must be 32 bytes")
		}
		keyBytes := []byte(key)
		var err error
		hasher, err = blake3.NewKeyed(keyBytes)
		if err != nil {
			return "", err
		}
	case context != "":
		hasher = blake3.NewDeriveKey(context)
	default:
		hasher = blake3.New()
	}

	hasher.Write([]byte(text))
	out := make([]byte, digestLen)
	if _, err := io.ReadFull(hasher.Digest(), out); err != nil {
		return "", err
	}
	return hex.EncodeToString(out), nil
}

func main() {
	value, err := blake3Text("hello", 0, "", "")
	if err != nil {
		panic(err)
	}
	fmt.Println("blake3=", value)

	valueKeyed, err := blake3Text("hello", 16, "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk", "")
	if err != nil {
		panic(err)
	}
	fmt.Println("blake3 keyed=", valueKeyed)

	valueCtx, err := blake3Text("hello", 32, "", "my-app-v1")
	if err != nil {
		panic(err)
	}
	fmt.Println("blake3 context=", valueCtx)
}