diff options
author | 2022-01-16 18:52:30 +0100 | |
---|---|---|
committer | 2022-01-16 18:52:30 +0100 | |
commit | 6f5ccf435585e43a00e3cc50f4bcefac36ada818 (patch) | |
tree | ba368d27464b79b1e5d010c0662fd3e340bf108e /vendor/github.com/zeebo/blake3/api.go | |
parent | add go-runners to readme (diff) | |
download | gotosocial-6f5ccf435585e43a00e3cc50f4bcefac36ada818.tar.xz |
update dependencies
Diffstat (limited to 'vendor/github.com/zeebo/blake3/api.go')
-rw-r--r-- | vendor/github.com/zeebo/blake3/api.go | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/vendor/github.com/zeebo/blake3/api.go b/vendor/github.com/zeebo/blake3/api.go new file mode 100644 index 000000000..5de263f08 --- /dev/null +++ b/vendor/github.com/zeebo/blake3/api.go @@ -0,0 +1,166 @@ +// Package blake3 provides an SSE4.1/AVX2 accelerated BLAKE3 implementation. +package blake3 + +import ( + "errors" + + "github.com/zeebo/blake3/internal/consts" + "github.com/zeebo/blake3/internal/utils" +) + +// Hasher is a hash.Hash for BLAKE3. +type Hasher struct { + size int + h hasher +} + +// New returns a new Hasher that has a digest size of 32 bytes. +// +// If you need more or less output bytes than that, use Digest method. +func New() *Hasher { + return &Hasher{ + size: 32, + h: hasher{ + key: consts.IV, + }, + } +} + +// NewKeyed returns a new Hasher that uses the 32 byte input key and has +// a digest size of 32 bytes. +// +// If you need more or less output bytes than that, use the Digest method. +func NewKeyed(key []byte) (*Hasher, error) { + if len(key) != 32 { + return nil, errors.New("invalid key size") + } + + h := &Hasher{ + size: 32, + h: hasher{ + flags: consts.Flag_Keyed, + }, + } + utils.KeyFromBytes(key, &h.h.key) + + return h, nil +} + +// DeriveKey derives a key based on reusable key material of any +// length, in the given context. The key will be stored in out, using +// all of its current length. +// +// Context strings must be hardcoded constants, and the recommended +// format is "[application] [commit timestamp] [purpose]", e.g., +// "example.com 2019-12-25 16:18:03 session tokens v1". +func DeriveKey(context string, material []byte, out []byte) { + h := NewDeriveKey(context) + _, _ = h.Write(material) + _, _ = h.Digest().Read(out) +} + +// NewDeriveKey returns a Hasher that is initialized with the context +// string. See DeriveKey for details. It has a digest size of 32 bytes. +// +// If you need more or less output bytes than that, use the Digest method. +func NewDeriveKey(context string) *Hasher { + // hash the context string and use that instead of IV + h := &Hasher{ + size: 32, + h: hasher{ + key: consts.IV, + flags: consts.Flag_DeriveKeyContext, + }, + } + + var buf [32]byte + _, _ = h.WriteString(context) + _, _ = h.Digest().Read(buf[:]) + + h.Reset() + utils.KeyFromBytes(buf[:], &h.h.key) + h.h.flags = consts.Flag_DeriveKeyMaterial + + return h +} + +// Write implements part of the hash.Hash interface. It never returns an error. +func (h *Hasher) Write(p []byte) (int, error) { + h.h.update(p) + return len(p), nil +} + +// WriteString is like Write but specialized to strings to avoid allocations. +func (h *Hasher) WriteString(p string) (int, error) { + h.h.updateString(p) + return len(p), nil +} + +// Reset implements part of the hash.Hash interface. It causes the Hasher to +// act as if it was newly created. +func (h *Hasher) Reset() { + h.h.reset() +} + +// Clone returns a new Hasher with the same internal state. +// +// Modifying the resulting Hasher will not modify the original Hasher, and vice versa. +func (h *Hasher) Clone() *Hasher { + return &Hasher{size: h.size, h: h.h} +} + +// Size implements part of the hash.Hash interface. It returns the number of +// bytes the hash will output in Sum. +func (h *Hasher) Size() int { + return h.size +} + +// BlockSize implements part of the hash.Hash interface. It returns the most +// natural size to write to the Hasher. +func (h *Hasher) BlockSize() int { + // TODO: is there a downside to picking this large size? + return 8192 +} + +// Sum implements part of the hash.Hash interface. It appends the digest of +// the Hasher to the provided buffer and returns it. +func (h *Hasher) Sum(b []byte) []byte { + if top := len(b) + h.size; top <= cap(b) && top >= len(b) { + h.h.finalize(b[len(b):top]) + return b[:top] + } + + tmp := make([]byte, h.size) + h.h.finalize(tmp) + return append(b, tmp...) +} + +// Digest takes a snapshot of the hash state and returns an object that can +// be used to read and seek through 2^64 bytes of digest output. +func (h *Hasher) Digest() *Digest { + var d Digest + h.h.finalizeDigest(&d) + return &d +} + +// Sum256 returns the first 256 bits of the unkeyed digest of the data. +func Sum256(data []byte) (sum [32]byte) { + out := Sum512(data) + copy(sum[:], out[:32]) + return sum +} + +// Sum512 returns the first 512 bits of the unkeyed digest of the data. +func Sum512(data []byte) (sum [64]byte) { + if len(data) <= consts.ChunkLen { + var d Digest + compressAll(&d, data, 0, consts.IV) + _, _ = d.Read(sum[:]) + return sum + } else { + h := hasher{key: consts.IV} + h.update(data) + h.finalize(sum[:]) + return sum + } +} |