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 ¶
- Constants
- func New() hash.Hash
- func New224() hash.Hash
- func New224Salt(salt []byte) hash.Hash
- func NewSalt(salt []byte) hash.Hash
- func Sum224(data []byte) [Size224]byte
- func Sum256(data []byte) [Size]byte
- type Error
- type ErrorKind
- type Hasher224
- func (h *Hasher224) BlockSize() int
- func (h *Hasher224) MarshalBinary() ([]byte, error)
- func (h *Hasher224) Reset()
- func (h *Hasher224) SaveState(target []byte) []byte
- func (h *Hasher224) Size() int
- func (h Hasher224) Sum(b []byte) []byte
- func (h Hasher224) Sum224() [Size224]byte
- func (h *Hasher224) UnmarshalBinary(state []byte) error
- func (h *Hasher224) Write(b []byte) (int, error)
- func (h *Hasher224) WriteByte(b byte)
- func (h *Hasher224) WriteBytes(b []byte)
- func (h *Hasher224) WriteString(s string)
- func (h *Hasher224) WriteUint16BE(val uint16)
- func (h *Hasher224) WriteUint16LE(val uint16)
- func (h *Hasher224) WriteUint32BE(val uint32)
- func (h *Hasher224) WriteUint32LE(val uint32)
- func (h *Hasher224) WriteUint64BE(val uint64)
- func (h *Hasher224) WriteUint64LE(val uint64)
- type Hasher256
- func (h *Hasher256) BlockSize() int
- func (h *Hasher256) MarshalBinary() ([]byte, error)
- func (h *Hasher256) Reset()
- func (h *Hasher256) SaveState(target []byte) []byte
- func (h *Hasher256) Size() int
- func (h Hasher256) Sum(b []byte) []byte
- func (h Hasher256) Sum256() [Size]byte
- func (h *Hasher256) UnmarshalBinary(state []byte) error
- func (h *Hasher256) Write(b []byte) (int, error)
- func (h *Hasher256) WriteByte(b byte)
- func (h *Hasher256) WriteBytes(b []byte)
- func (h *Hasher256) WriteString(s string)
- func (h *Hasher256) WriteUint16BE(val uint16)
- func (h *Hasher256) WriteUint16LE(val uint16)
- func (h *Hasher256) WriteUint32BE(val uint32)
- func (h *Hasher256) WriteUint32LE(val uint32)
- func (h *Hasher256) WriteUint64BE(val uint64)
- func (h *Hasher256) WriteUint64LE(val uint64)
Examples ¶
Constants ¶
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.
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 ¶
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 ¶
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 ¶
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 ¶
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.
Types ¶
type Error ¶ added in v1.1.0
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.
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
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
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
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
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
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
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
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
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
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) WriteBytes ¶ added in v1.1.0
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
WriteString adds the given string to the rolling hash.
func (*Hasher224) WriteUint16BE ¶ added in v1.1.0
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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) WriteBytes ¶ added in v1.1.0
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
WriteString adds the given string to the rolling hash.
func (*Hasher256) WriteUint16BE ¶ added in v1.1.0
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
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
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
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
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
WriteUint64LE encodes the given unsigned 64-bit integer as an 8-byte little-endian byte sequence and adds it to the rolling hash.