tuplehash

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2024 License: BSD-3-Clause Imports: 4 Imported by: 0

README

SHA-3 TupleHash in Go

This small package implements the SHA-3 derived TupleHash function as specified by NIST SP 800-185.

NIST SP 800-185, Section 5 TupleHash:

TupleHash is a SHA-3-derived hash function with variable-length output that is designed to simply hash a tuple of input strings, any or all of which may be empty strings, in an unambiguous way. Such a tuple may consist of any number of strings, including zero, and is represented as a sequence of strings or variables in parentheses like ("a", "b", "c", ..., "z") in this document.

TupleHash is designed to provide a generic, misuse-resistant way to combine a sequence of strings for hashing such that, for example, a TupleHash computed on the tuple ("abc", "d") will produce a different hash value than a TupleHash computed on the tuple ("ab", "cd"), even though all the remaining input parameters are kept the same, and the two resulting concatenated strings, without string encoding, are identical.

Motivation

Even though the description above points out the problem that TupleHash is designed to solve, I would like to motivate this with a small example.

Take the following Go snippet, creating a hash over a multitude of fields. While it was written to highlight the very issue, I have seen variants of this code just too many times.

package main

import (
	"crypto/sha256"
	"fmt"
)

func main() {
	fields := [][]byte{[]byte("foo"), []byte("bar")}
	sep := []byte(",")

	h := sha256.New()
	for _, field := range fields {
		_, _ = h.Write(field)
		_, _ = h.Write(sep)
	}

	fmt.Printf("%x\n", h.Sum(nil))
}

Those fields are being separated by a separator. If, however, the fields are based on user input, the separator may be supplied as an input.

To be precise, both

fields := [][]byte{[]byte("foo"), []byte(""), []byte("bar")}

and

fields := [][]byte{[]byte("foo"), []byte(",bar")}

would result in the same hash.

This has a certain Bobby Tables smell.

Usage

Go Reference

This package ships a custom hash.Hash type implementing TupleHash. For general API information, please take a look at the documentation linked above.

The prior example can be rewritten like the following, resulting in different hashes as commented.

package main

import (
	"fmt"

	"codeberg.org/oxzi/go-tuplehash"
)

func main() {
	// 8a1dcaf3016d4767bcaef22356e238f96801a9fb8d79023639eed0808da5df93
	fields := [][]byte{[]byte("foo"), []byte(""), []byte("bar")}
	// a260c2ec145b0032d24a44eb2609dc0b0f7d559b4a0facf3199b7bcd1b5a6b65
	// fields := [][]byte{[]byte("foo"), []byte(",bar")}
	sep := []byte(",")

	h := tuplehash.NewTupleHash128(nil, 32)
	for _, field := range fields {
		_, _ = h.Write(field)
		_, _ = h.Write(sep)
	}

	fmt.Printf("%x\n", h.Sum(nil))
}

Disclaimer

The author is not a cryptographer. Even if the heavy lifting is already done in Go's /x/crypto, there may be serious flaws in this code. Consider it educational and take a closer look to see if it appeals to you.

Documentation

Overview

Package tuplehash implements the SHA-3 derived TupleHash from NIST SP 800-185.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewTupleHash128

func NewTupleHash128(s []byte, outputLen int) hash.Hash

NewTupleHash128 creates a new SHA-3 TupleHash128 as a hash.Hash.

s may either be nil or an optional customization bit string of any length, allowing a custom branded hash.

outputLen defines the final hash length in bytes. If uncertain, pick 32.

func NewTupleHash256

func NewTupleHash256(s []byte, outputLen int) hash.Hash

NewTupleHash256 creates a new SHA-3 TupleHash256 as a hash.Hash.

s may either be nil or an optional customization bit string of any length, allowing a custom branded hash.

outputLen defines the final hash length in bytes. If uncertain, pick 64.

func TupleHashSum128

func TupleHashSum128(s []byte, outputLen int, data [][]byte) []byte

TupleHashSum128 returns an arbitrary-length TupleHash for multiple byte arrays.

This function works on an internal cSHAKE128 instance.

s may either be nil or an optional customization bit string of any length, allowing a custom branded hash.

outputLen defines the final hash length in bytes. If uncertain, pick 32.

data is an array of byte arrays, each to be hashed as one tuple.

The returned byte array will be of outputLen bytes.

func TupleHashSum256

func TupleHashSum256(s []byte, outputLen int, data [][]byte) []byte

TupleHashSum256 returns an arbitrary-length TupleHash for multiple byte arrays.

This function works on an internal cSHAKE256 instance.

s may either be nil or an optional customization bit string of any length, allowing a custom branded hash.

outputLen defines the final hash length in bytes. If uncertain, pick 64.

data is an array of byte arrays, each to be hashed as one tuple.

The returned byte array will be of outputLen bytes.

Types

This section is empty.

Jump to

Keyboard shortcuts

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