blake256

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 22, 2024 License: ISC Imports: 4 Imported by: 52

README

blake256

Build Status ISC License Doc

Overview

Package blake256 implements the BLAKE-256 and BLAKE-224 cryptographic hash functions (SHA-3 candidate) in pure Go along with highly optimized SSE2, SSE4.1, and AVX acceleration.

It provides an API that enables zero allocations and the ability to save and restore the intermediate state (also often called the midstate). The design philosophy has a strong on emphasis correctness, readability, and efficiency while also aiming to provide an ergonomic API.

In addition to the zero allocation API, it also implements the standard library interfaces hash.Hash, encoding.BinaryMarshaler, and encoding.BinaryUnmarshaler for callers that are not as concerned about avoiding allocations. No dependencies beyond the standard library are required.

A full suite of tests with 100% branch coverage and benchmarks are provided to help ensure proper functionality and analyze performance characteristics.

The core assembly code to take advantage of the amd64 SIMD vector extensions is generated with Go via avo.

Show me the benchmarks already!

Example Usage?

Hashing Data

The simplest way to hash data that is already serialized into bytes is via the global Sum224 (BLAKE-224) or Sum256 (BLAKE-256) functions. This is demonstrated for BLAKE-256 via the "Basic Usage" example linked in the Examples section.

However, since hashing typically involves writing various pieces of information that aren't already serialized, this package provides NewHasher224 (BLAKE-224) and NewHasher256 (BLAKE-256) (and their respective variants NewHasher224Salt and NewHasher256Salt that accept salt).

These methods return rolling hasher instances that support writing an arbitrary amount of data along with several convenience methods for writing various data types in either big endian or little endian. For example, WriteString adds a string encoded as its UTF-8 byte sequence to the rolling hash and WriteUint64BE adds an unsigned 64-bit integer encoded as an 8-byte big-endian byte sequence to the rolling hash.

The hash is then obtained via the Sum224 (BLAKE-224) or Sum256 (BLAKE-256) method on the respective hasher instance.

See the "Rolling Hasher Usage" example linked in the Examples section to see rolling hashing in action.

Saving and Resuming Intermediate States

Many applications involve hashing data that always starts with the same sequence of bytes (aka a shared prefix). Whenever that prefix is larger than the block size (BlockSize), or it is otherwise costly to generate and serialize, it is typically more efficient to save the intermediate state (midstate) after writing the shared prefix so that all future hashes can resume from that midstate and thereby avoid redoing work.

To that end, the aforementioned rolling hasher instances support being copied to save and restore the current midstate within the same process. This is demonstrated via the "Same Process Save and Restore" example linked in the Examples section.

Alternatively, when a simple copy of the instance is not possible, such as when the midstate is needed among multiple processes, perhaps on entirely different hardware, it can be serialized via SaveState and restored via UnmarshalBinary. Note that there is necessarily additional overhead involved with serializing and deserializing the intermediate state, so callers should be sure to compare that overhead with rehashing the shared data to see which approach yields better results for their particular application.

Hashing With Salt

This implementation also provides NewHasher224Salt (BLAKE-224) and NewHasher256Salt (BLAKE-256) which accept a 16-byte salt input as described by the specification. Hashing with distinct salts effectively provides an efficient method to hash with different functions while using the same underlying algorithm. The salted variants behave exactly the same as the normal unsalted variants described throughout the documentation.

Benchmarks

The following benchmarks are from a Ryzen 7 5800X3D processor on Linux and are the result of feeding benchstat 10 iterations of each. Benchmarks for both BLAKE-224 and BLAKE-256 are provided. They are essentialy identical (within the margin of error) as expected since the only notable difference as it pertains to performance is that the final output is 4 bytes shorter.

BLAKE-256 Hashing Benchmarks

The following results demonstrate the performance of hashing various amounts of data for both small and larger inputs with the Sum256 method.

Operation Pure Go SSE2 SSE4.1 AVX
Sum256 (32b) 168MB/s ± 1% 188MB/s ± 1% 232MB/s ± 0% 234MB/s ± 1%
Sum256 (64b) 187MB/s ± 0% 208MB/s ± 0% 270MB/s ± 1% 271MB/s ± 1%
Sum256 (1KiB) 378MB/s ± 1% 421MB/s ± 1% 536MB/s ± 1% 539MB/s ± 1%
Sum256 (8KiB) 405MB/s ± 1% 448MB/s ± 0% 573MB/s ± 0% 573MB/s ± 0%
Sum256 (16KiB) 402MB/s ± 1% 449MB/s ± 0% 575MB/s ± 0% 575MB/s ± 0%
Operation Pure Go SSE2 SSE4.1 AVX Allocs / Op
Sum256 (32b) 190ns ± 1% 170ns ± 1% 138ns ± 0% 137ns ± 1% 0
Sum256 (64b) 342ns ± 0% 308ns ± 0% 237ns ± 1% 236ns ± 1% 0
Sum256 (1KiB) 2.71µs ± 1% 2.43µs ± 1% 1.91µs ± 1% 1.90µs ± 1% 0
Sum256 (8KiB) 20.2µs ± 1% 18.3µs ± 0% 14.3µs ± 0% 14.3µs ± 0% 0
Sum256 (16KiB) 40.8µs ± 1% 36.5µs ± 0% 28.5µs ± 0% 28.5µs ± 0% 0
BLAKE-224 Hashing Benchmarks

The following results demonstrate the performance of hashing various amounts of data for both small and larger inputs with the Sum224 method.

Operation Pure Go SSE2 SSE4.1 AVX
Sum224 (32b) 171MB/s ± 1% 188MB/s ± 1% 232MB/s ± 1% 234MB/s ± 1%
Sum224 (64b) 187MB/s ± 2% 209MB/s ± 1% 269MB/s ± 1% 271MB/s ± 1%
Sum224 (1KiB) 378MB/s ± 1% 423MB/s ± 1% 539MB/s ± 1% 536MB/s ± 1%
Sum224 (8KiB) 404MB/s ± 1% 447MB/s ± 1% 577MB/s ± 1% 577MB/s ± 0%
Sum224 (16KiB) 401MB/s ± 1% 453MB/s ± 0% 577MB/s ± 0% 577MB/s ± 0%
Operation Pure Go SSE2 SSE4.1 AVX Allocs / Op
Sum224 (32b) 187ns ± 1% 170ns ± 1% 138ns ± 1% 137ns ± 1% 0
Sum224 (64b) 342ns ± 2% 306ns ± 1% 238ns ± 1% 236ns ± 1% 0
Sum224 (1KiB) 2.71µs ± 1% 2.42µs ± 1% 1.90µs ± 1% 1.91µs ± 1% 0
Sum224 (8KiB) 20.3µs ± 1% 18.3µs ± 1% 14.2µs ± 1% 14.2µs ± 0% 0
Sum224 (16KiB) 40.9µs ± 1% 36.2µs ± 0% 28.4µs ± 0% 28.4µs ± 0% 0
State Serialization Benchmarks

The following results demonstrate the performance of serializing the intermediate state for both BLAKE-224 and BLAKE-256 using the zero-alloc SaveState method versus the standard library encoding.MarshalBinary interface.

Metric MarshalBinary SaveState Delta
Time / Op 40.6ns ± 1% 16.0ns ± 0% -60.60% (p=0.000 n=10+10)
Allocs / Op 1 0 -100.00% (p=0.000 n=10+10)

Disabling Assembler Optimizations

The purego build tag may be used to disable all assembly code.

Additionally, when built normally without the purego build tag, the assembly optimizations for each of the supported vector extensions can individually be disabled at runtime by setting the following environment variables to 1.

  • BLAKE256_DISABLE_AVX=1: Disable Advanced Vector Extensions (AVX) optimizations
  • BLAKE256_DISABLE_SSE41=1: Disable Streaming SIMD Extensions 4.1 (SSE4.1) optimizations
  • BLAKE256_DISABLE_SSE2=1: Disable Streaming SIMD Extensions 2 (SSE2) optimizations

The package will automatically use the fastest available extensions that are not disabled.

Examples

  • Basic Usage
    Demonstrates the simplest method of hashing an existing serialized data buffer with BLAKE-256.
  • Rolling Hasher Usage
    Demonstrates creating a rolling BLAKE-256 hasher, writing various data types to it, computing the hash, writing more data, and finally computing the cumulative hash.
  • Same Process Save and Restore
    Demonstrates creating a rolling BLAKE-256 hasher, writing some data to it, making a copy of the intermediate state, restoring the intermediate state in multiple goroutines, writing more data to each of those restored copies, and computing the final hashes.

Installation and Updating

This package is part of the github.com/decred/dcrd/crypto/blake256 module. Use the standard go tooling for working with modules to incorporate it.

License

Package blake256 is licensed under the copyfree ISC License.

Documentation

Overview

Package blake256 implements BLAKE-256 and BLAKE-224 with SSE2, SSE4.1, and AVX acceleration and zero allocations.

Example (BasicUsageExistingBuffer)

This example demonstrates the simplest method of hashing an existing serialized data buffer with BLAKE-256.

package main

import (
	"fmt"

	"github.com/decred/dcrd/crypto/blake256"
)

func main() {
	// The data to hash in this scenario would ordinarily come from somewhere
	// else, but it is hard coded here for the purposes of the example.
	data := []byte{0x01, 0x02, 0x03, 0x04}
	hash := blake256.Sum256(data)
	fmt.Printf("hash: %x\n", hash)

}
Output:

hash: c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7
Example (RollingHasherUsage)

This example demonstrates creating a rolling BLAKE-256 hasher, writing various data types to it, computing the hash, writing more data, and finally computing the cumulative hash.

package main

import (
	"fmt"

	"github.com/decred/dcrd/crypto/blake256"
)

func main() {
	// Create a new zero-allocation hasher for BLAKE-256 and write data with
	// various types to it.
	hasher := blake256.NewHasher256()
	hasher.WriteString("Some string to include in the hash")
	hasher.WriteBytes([]byte{0x01, 0x02, 0x03, 0x04})
	hasher.WriteByte(0x05)
	hasher.WriteUint16BE(6789)       // Big endian
	hasher.WriteUint32LE(268435455)  // Little endian
	hasher.WriteUint64BE(4294967297) // Big endian

	// Compute the hash of the data written to this point.  Note that the hasher
	// state is not modified, so it is possible to continue writing more data
	// afterwards as demonstrated next.
	hash := hasher.Sum256()
	fmt.Printf("hash1: %x\n", hash)

	// Write some more data and compute the cumulative hash.
	hasher.WriteString("more data to include in the hash")
	fmt.Printf("hash2: %x\n", hasher.Sum256())

}
Output:

hash1: 3bd1db9a41e8a7942a14d30eb196f1420a3991a1094bdbf678d3b4ded30dda6f
hash2: 36771288c89b3cda5659e270338127b76361e1a07bfe26bb2baae14d46e56c64
Example (SameProcessSaveRestore)

This example demonstrates creating a rolling BLAKE-256 hasher, writing some data to it, making a copy of the intermediate state, restoring the intermediate state in multiple goroutines, writing more data to each of those restored copies, and computing the final hashes.

package main

import (
	"bytes"
	"fmt"
	"sort"

	"github.com/decred/dcrd/crypto/blake256"
)

func main() {
	// Create 1024 bytes of mock shared prefix data.  This is meant to simulate
	// what would ordinarily be actual data at the beginning that does not
	// change between multiple hash invocations.
	sharedPrefixData := bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x04}, 256)

	// Create a new zero-allocation hasher for BLAKE-256 and write the mock
	// shared prefix data to it.
	hasher := blake256.NewHasher256()
	hasher.WriteBytes(sharedPrefixData)

	// Make a copy of the current intermediate hasher state.
	savedHasher := *hasher

	// Launch some goroutines that each restore the saved intermediate state,
	// write different suffix data, compute the final hash, and deliver the
	// resulting hashes on a channel.
	//
	// Note that the key point this is attempting to demonstrate is that all of
	// the shared prefix data does not need to be rewritten.
	const numResults = 4
	results := make(chan [blake256.Size]byte, numResults)
	for i := 0; i < numResults; i++ {
		go func(moreData uint16) {
			restoredHasher := savedHasher
			restoredHasher.WriteUint16BE(moreData)
			results <- restoredHasher.Sum256()
		}(uint16(i))
	}

	// Collect the resulting hashes from the goroutines.
	hashes := make([][blake256.Size]byte, numResults)
	for i := 0; i < numResults; i++ {
		hashes[i] = <-results
	}

	// Sort the results for stable test output.  This typically wouldn't be
	// needed in a real application.
	sort.Slice(hashes, func(i, j int) bool {
		return bytes.Compare(hashes[i][:], hashes[j][:]) < 0
	})
	for i, hash := range hashes {
		fmt.Printf("hash%d: %x\n", i+1, hash)
	}

}
Output:

hash1: 290278508c9ba1b7717338bbde28fa91e36aa2c39c7eb63bd96ba6abd5ebff21
hash2: 2c44931aacea282297d9c153bc0cd9f48d13796d16f634cad672504518e36af2
hash3: 77c9e453e13c923b540bda1a61dddab55de4c7b624cd499f2990e9de0345bacc
hash4: 8c61d57f5be4ce7b12c577c4d8e51127766b331a1ff54220e5ca1c7ea9c0360a

Index

Examples

Constants

View Source
const (
	// ErrMalformedState indicates a serialized intermediate state is malformed
	// in some way such as not having at least the expected number of bytes.
	ErrMalformedState = ErrorKind("ErrMalformedState")

	// ErrMismatchedState indicates a serialized intermediate state is not for
	// the hash type that is attempting to restore it.  For example, it will be
	// returned when attempting to restore a BLAKE-256 intermediate state with
	// a BLAKE-224 hasher.
	ErrMismatchedState = ErrorKind("ErrMismatchedState")
)

These constants are used to identify a specific ErrorKind.

View Source
const (
	// BlockSize is the block size of the hash algorithm in bytes.
	BlockSize = 64

	// Size is the size of a BLAKE-256 hash in bytes.
	Size = 32

	// Size224 is the size of a BLAKE-224 hash in bytes.
	Size224 = 28

	// SavedStateSize is the number of bytes of a serialized intermediate state.
	SavedStateSize = 128
)

Variables

This section is empty.

Functions

func New

func New() hash.Hash

New returns a new hash.Hash computing the BLAKE-256 checksum.

Callers should prefer NewHasher256 instead since it returns a concrete type that has more functionality and allows avoiding additional allocations. It can also be used as a hash.Hash if desired.

func New224

func New224() hash.Hash

New224 returns a new hash.Hash computing the BLAKE-224 checksum.

Callers should prefer NewHasher224 instead since it returns a concrete type that has more functionality and allows avoiding additional allocations. It can also be used as a hash.Hash if desired.

func New224Salt

func New224Salt(salt []byte) hash.Hash

New224Salt returns a new hash.Hash computing the BLAKE-224 checksum initialized with the given 16-byte salt.

It will panic if the provided salt is not 16 bytes.

Callers should prefer NewHasher224Salt instead since it returns a concrete type that has more functionality and allows avoiding additional allocations. It can also be used as a hash.Hash if desired.

func NewSalt

func NewSalt(salt []byte) hash.Hash

NewSalt returns a new hash.Hash computing the BLAKE-256 checksum initialized with the given 16-byte salt.

It will panic if the provided salt is not 16 bytes.

Callers should prefer NewHasher256Salt instead since it returns a concrete type that has more functionality and allows avoiding additional allocations. It can also be used as a hash.Hash if desired.

func Sum224

func Sum224(data []byte) [Size224]byte

Sum224 returns the BLAKE-224 checksum of the data.

func Sum256

func Sum256(data []byte) [Size]byte

Sum256 returns the BLAKE-256 checksum of the data.

Types

type Error added in v1.1.0

type Error struct {
	Err         error
	Description string
}

Error identifies an error related to restoring an intermediate hashing state.

It has full support for errors.Is and errors.As, so the caller can ascertain the specific reason for the error by checking the underlying error.

func (Error) Error added in v1.1.0

func (e Error) Error() string

Error satisfies the error interface and prints human-readable errors.

func (Error) Unwrap added in v1.1.0

func (e Error) Unwrap() error

Unwrap returns the underlying wrapped error.

type ErrorKind added in v1.1.0

type ErrorKind string

ErrorKind identifies a kind of error.

func (ErrorKind) Error added in v1.1.0

func (e ErrorKind) Error() string

Error satisfies the error interface and prints human-readable errors.

type Hasher224 added in v1.1.0

type Hasher224 struct {
	// contains filtered or unexported fields
}

Hasher224 provides a zero-allocation implementation to compute a rolling BLAKE-224 checksum.

It can safely be copied at any point to save its intermediate state for use in additional processing later, without having to write the previously written data again.

In addition to the aforementioned in-process state saving capability, it also supports serializing the intermediate state to enable sharing across process boundaries.

It is effectively a mix of a hash.Hash, encoding.BinaryMarshaler, and encoding.BinaryUnmarshaler with a modified API that enables zero allocations and also provides additional convenience funcs for writing integers encoded with both big and little endian as well as writing individual bytes.

However, it also implements hash.Hash, encoding.BinaryMarshaler, and encoding.BinaryUnmarshaler for callers that aren't as concerned about reducing allocations and would prefer to use it with the aforementioned standard library interfaces.

NOTE: The zero value is NOT safe to use. It must be initialized via NewHasher224 or NewHasher224Salt.

func NewHasher224 added in v1.1.0

func NewHasher224() *Hasher224

NewHasher224 returns a zero-allocation hasher for computing a rolling BLAKE-224 checksum.

func NewHasher224Salt added in v1.1.0

func NewHasher224Salt(salt []byte) *Hasher224

NewHasher224Salt returns a zero-allocation hasher for computing a rolling BLAKE-224 checksum initialized with the given 16-byte salt slice.

It will panic if the provided salt is not 16 bytes.

func (*Hasher224) BlockSize added in v1.1.0

func (h *Hasher224) BlockSize() int

BlockSize returns the underlying block size of the BLAKE-224 hashing algorithm.

This is part of the hash.Hash interface.

func (*Hasher224) MarshalBinary added in v1.1.0

func (h *Hasher224) MarshalBinary() ([]byte, error)

MarshalBinary returns the intermediate state of the rolling hash serialized into a binary form that may be used to resume from the current state later without having to write the previously written data again. It does not change the underlying hash state.

As described by the Hasher224 documentation, the hasher instance can simply be copied to achieve the same result much more efficiently when the caller is able to keep a copy. Therefore, that approach should be preferred when possible.

However, the ability to serialize the state is also provided to enable sharing it across process boundaries.

NOTE: This method only returns an error in order to satisfy the encoding.BinaryMarshaler interface. However, it will never error, meaning the error will always be nil, so it is safe to ignore.

Callers that wish to avoid allocations should prefer Hasher224.SaveState instead.

func (*Hasher224) Reset added in v1.1.0

func (h *Hasher224) Reset()

Reset resets the state of the rolling hash.

This is part of the hash.Hash interface.

func (*Hasher224) SaveState added in v1.1.0

func (h *Hasher224) SaveState(target []byte) []byte

SaveState appends the current intermediate state of the rolling hash, as generated by Hasher224.MarshalBinary, to the provided slice and returns the resulting slice. It does not change the underlying hash state.

The resulting serialized data may be used to resume from the current intermediate state later without having to write the previously written data again by providing it to Hasher224.UnmarshalBinary.

As described by the Hasher224 documentation, the hasher instance can simply be copied to achieve the same result much more efficiently when the caller is able to keep a copy. Therefore, that approach should be preferred when possible.

However, the ability to serialize the state is also provided to enable sharing it across process boundaries.

Note that allocations can typically be avoided by providing a slice that has enough capacity to house the resulting state as defined by the SavedStateSize constant. For example:

state := make([]byte, blake256.SavedStateSize)
h := blake256.NewHasher224()
h.WriteUint64LE(1)
state = h.SaveState(state[:0])

func (*Hasher224) Size added in v1.1.0

func (h *Hasher224) Size() int

Size returns the size of a BLAKE-224 hash in bytes.

This is part of the hash.Hash interface.

func (Hasher224) Sum added in v1.1.0

func (h Hasher224) Sum(b []byte) []byte

Sum finalizes the rolling hash, appends the resulting checksum to the provided slice and returns the resulting slice. It does not change the underlying hash state.

Note that allocations can often be avoided by providing a slice that has enough capacity to house the resulting checksum. For example:

digest := make([]byte, blake256.Size224)
h := blake256.NewHasher224()
h.WriteUint64LE(1)
digest = h.Sum(digest[:0])

This is part of the hash.Hash interface.

func (Hasher224) Sum224 added in v1.1.0

func (h Hasher224) Sum224() [Size224]byte

Sum224 finalizes the rolling hash and returns the resulting checksum. It does not change the underlying hash state.

func (*Hasher224) UnmarshalBinary added in v1.1.0

func (h *Hasher224) UnmarshalBinary(state []byte) error

UnmarshalBinary restores the rolling hash to the provided serialized intermediate state. See Hasher224.MarshalBinary for more details.

ErrMalformedState will be returned when the provided serialized state is not at least the required SavedStateSize number of bytes.

ErrMismatchedState will be returned if the provided state is not for a BLAKE-224 hash. For example, it will be returned when attempting to restore a BLAKE-256 intermediate state.

This implements the encoding.BinaryUnmarshaler interface.

func (*Hasher224) Write added in v1.1.0

func (h *Hasher224) Write(b []byte) (int, error)

Write adds the given bytes to the rolling hash.

NOTE: This method only returns an error in order to satisfy the io.Writer and hash.Hash interfaces. However, it will never error, meaning the error will always be nil, so it is safe to ignore.

Callers may optionally choose to call [WriteBytes] which does not return an error to make the fact writing can never fail.

func (*Hasher224) WriteByte added in v1.1.0

func (h *Hasher224) WriteByte(b byte)

WriteByte adds the given byte to the rolling hash.

func (*Hasher224) WriteBytes added in v1.1.0

func (h *Hasher224) WriteBytes(b []byte)

WriteBytes adds the given bytes to the rolling hash.

This method is identical to [Write] except it does not return an error in order to make it clear that writing can never fail.

func (*Hasher224) WriteString added in v1.1.0

func (h *Hasher224) WriteString(s string)

WriteString adds the given string to the rolling hash.

func (*Hasher224) WriteUint16BE added in v1.1.0

func (h *Hasher224) WriteUint16BE(val uint16)

WriteUint16BE encodes the given unsigned 16-bit integer as a 2-byte big-endian byte sequence and adds it to the rolling hash.

func (*Hasher224) WriteUint16LE added in v1.1.0

func (h *Hasher224) WriteUint16LE(val uint16)

WriteUint16LE encodes the given unsigned 16-bit integer as a 2-byte little-endian byte sequence and adds it to the rolling hash.

func (*Hasher224) WriteUint32BE added in v1.1.0

func (h *Hasher224) WriteUint32BE(val uint32)

WriteUint32BE encodes the given unsigned 32-bit integer as a 4-byte big-endian byte sequence and adds it to the rolling hash.

func (*Hasher224) WriteUint32LE added in v1.1.0

func (h *Hasher224) WriteUint32LE(val uint32)

WriteUint32LE encodes the given unsigned 32-bit integer as a 4-byte little-endian byte sequence and adds it to the rolling hash.

func (*Hasher224) WriteUint64BE added in v1.1.0

func (h *Hasher224) WriteUint64BE(val uint64)

WriteUint64BE encodes the given unsigned 64-bit integer as an 8-byte big-endian byte sequence and adds it to the rolling hash.

func (*Hasher224) WriteUint64LE added in v1.1.0

func (h *Hasher224) WriteUint64LE(val uint64)

WriteUint64LE encodes the given unsigned 64-bit integer as an 8-byte little-endian byte sequence and adds it to the rolling hash.

type Hasher256 added in v1.1.0

type Hasher256 struct {
	// contains filtered or unexported fields
}

Hasher256 provides a zero-allocation implementation to compute a rolling BLAKE-256 checksum.

It can safely be copied at any point to save its intermediate state for use in additional processing later, without having to write the previously written data again.

In addition to the aforementioned in-process state saving capability, it also supports serializing the intermediate state to enable sharing across process boundaries.

It is effectively a mix of a hash.Hash, encoding.BinaryMarshaler, and encoding.BinaryUnmarshaler with a modified API that enables zero allocations and also provides additional convenience funcs for writing integers encoded with both big and little endian as well as writing individual bytes.

However, it also implements hash.Hash, encoding.BinaryMarshaler, and encoding.BinaryUnmarshaler for callers that aren't as concerned about reducing allocations and would prefer to use it with the aforementioned standard library interfaces.

NOTE: The zero value is NOT safe to use. It must be initialized via NewHasher256.

func NewHasher256 added in v1.1.0

func NewHasher256() *Hasher256

NewHasher256 returns a zero-allocation hasher for computing a rolling BLAKE-256 checksum.

func NewHasher256Salt added in v1.1.0

func NewHasher256Salt(salt []byte) *Hasher256

NewHasher256Salt returns a zero-allocation hasher for computing a rolling BLAKE-256 checksum initialized with the given 16-byte salt slice.

It will panic if the provided salt is not 16 bytes.

func (*Hasher256) BlockSize added in v1.1.0

func (h *Hasher256) BlockSize() int

BlockSize returns the underlying block size of the BLAKE-256 hashing algorithm.

This is part of the hash.Hash interface.

func (*Hasher256) MarshalBinary added in v1.1.0

func (h *Hasher256) MarshalBinary() ([]byte, error)

MarshalBinary returns the intermediate state of the rolling hash serialized into a binary form that may be used to resume from the current state later without having to write the previously written data again. It does not change the underlying hash state.

As described by the Hasher256 documentation, the hasher instance can simply be copied to achieve the same result much more efficiently when the caller is able to keep a copy. Therefore, that approach should be preferred when possible.

However, the ability to serialize the state is also provided to enable sharing it across process boundaries.

NOTE: This method only returns an error in order to satisfy the encoding.BinaryMarshaler interface. However, it will never error, meaning the error will always be nil, so it is safe to ignore.

Callers that wish to avoid allocations should prefer Hasher256.SaveState instead.

func (*Hasher256) Reset added in v1.1.0

func (h *Hasher256) Reset()

Reset resets the state of the rolling hash.

This is part of the hash.Hash interface.

func (*Hasher256) SaveState added in v1.1.0

func (h *Hasher256) SaveState(target []byte) []byte

SaveState appends the current intermediate state of the rolling hash, as generated by Hasher256.MarshalBinary, to the provided slice and returns the resulting slice. It does not change the underlying hash state.

The resulting serialized data may be used to resume from the current intermediate state later without having to write the previously written data again by providing it to Hasher256.UnmarshalBinary.

As described by the Hasher256 documentation, the hasher instance can simply be copied to achieve the same result much more efficiently when the caller is able to keep a copy. Therefore, that approach should be preferred when possible.

However, the ability to serialize the state is also provided to enable sharing it across process boundaries.

Note that allocations can typically be avoided by providing a slice that has enough capacity to house the resulting state as defined by the SavedStateSize constant. For example:

state := make([]byte, blake256.SavedStateSize)
h := blake256.NewHasher256()
h.WriteUint64LE(1)
state = h.SaveState(state[:0])

func (*Hasher256) Size added in v1.1.0

func (h *Hasher256) Size() int

Size returns the size of a BLAKE-256 hash in bytes.

This is part of the hash.Hash interface.

func (Hasher256) Sum added in v1.1.0

func (h Hasher256) Sum(b []byte) []byte

Sum finalizes the rolling hash, appends the resulting checksum to the provided slice and returns the resulting slice. It does not change the underlying hash state.

Note that allocations can often be avoided by providing a slice that has enough capacity to house the resulting checksum. For example:

digest := make([]byte, blake256.Size)
h := blake256.NewHasher256()
h.WriteUint64LE(1)
digest = h.Sum(digest[:0])

This is part of the hash.Hash interface.

func (Hasher256) Sum256 added in v1.1.0

func (h Hasher256) Sum256() [Size]byte

Sum256 finalizes the rolling hash and returns the resulting checksum. It does not change the underlying hash state.

func (*Hasher256) UnmarshalBinary added in v1.1.0

func (h *Hasher256) UnmarshalBinary(state []byte) error

UnmarshalBinary restores the rolling hash to the provided serialized intermediate state. See Hasher256.MarshalBinary for more details.

ErrMalformedState will be returned when the provided serialized state is not at least the required SavedStateSize number of bytes.

ErrMismatchedState will be returned if the provided state is not for a BLAKE-256 hash. For example, it will be returned when attempting to restore a BLAKE-224 intermediate state.

This implements the encoding.BinaryUnmarshaler interface.

func (*Hasher256) Write added in v1.1.0

func (h *Hasher256) Write(b []byte) (int, error)

Write adds the given bytes to the rolling hash.

NOTE: This method only returns an error in order to satisfy the io.Writer and hash.Hash interfaces. However, it will never error, meaning the error will always be nil, so it is safe to ignore.

Callers may optionally choose to call [WriteBytes] which does not return an error to make the fact writing can never fail.

func (*Hasher256) WriteByte added in v1.1.0

func (h *Hasher256) WriteByte(b byte)

WriteByte adds the given byte to the rolling hash.

func (*Hasher256) WriteBytes added in v1.1.0

func (h *Hasher256) WriteBytes(b []byte)

WriteBytes adds the given bytes to the rolling hash.

This method is identical to [Write] except it does not return an error in order to make it clear that writing can never fail.

func (*Hasher256) WriteString added in v1.1.0

func (h *Hasher256) WriteString(s string)

WriteString adds the given string to the rolling hash.

func (*Hasher256) WriteUint16BE added in v1.1.0

func (h *Hasher256) WriteUint16BE(val uint16)

WriteUint16BE encodes the given unsigned 16-bit integer as a 2-byte big-endian byte sequence and adds it to the rolling hash.

func (*Hasher256) WriteUint16LE added in v1.1.0

func (h *Hasher256) WriteUint16LE(val uint16)

WriteUint16LE encodes the given unsigned 16-bit integer as a 2-byte little-endian byte sequence and adds it to the rolling hash.

func (*Hasher256) WriteUint32BE added in v1.1.0

func (h *Hasher256) WriteUint32BE(val uint32)

WriteUint32BE encodes the given unsigned 32-bit integer as a 4-byte big-endian byte sequence and adds it to the rolling hash.

func (*Hasher256) WriteUint32LE added in v1.1.0

func (h *Hasher256) WriteUint32LE(val uint32)

WriteUint32LE encodes the given unsigned 32-bit integer as a 4-byte little-endian byte sequence and adds it to the rolling hash.

func (*Hasher256) WriteUint64BE added in v1.1.0

func (h *Hasher256) WriteUint64BE(val uint64)

WriteUint64BE encodes the given unsigned 64-bit integer as an 8-byte big-endian byte sequence and adds it to the rolling hash.

func (*Hasher256) WriteUint64LE added in v1.1.0

func (h *Hasher256) WriteUint64LE(val uint64)

WriteUint64LE encodes the given unsigned 64-bit integer as an 8-byte little-endian byte sequence and adds it to the rolling hash.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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