1 // Written in 2012 by Dmitry Chestnykh.
3 // To the extent possible under law, the author have dedicated all copyright
4 // and related and neighboring rights to this software to the public domain
5 // worldwide. This software is distributed without any warranty.
6 // http://creativecommons.org/publicdomain/zero/1.0/
8 // Package blake2b implements BLAKE2b cryptographic hash function.
18 BlockSize = 128 // block size of algorithm
19 Size = 64 // maximum digest size
20 SaltSize = 16 // maximum salt size
21 PersonSize = 16 // maximum personalization string size
22 KeySize = 64 // maximum size of key
26 h [8]uint64 // current chain value
27 t [2]uint64 // message bytes counter
28 f [2]uint64 // finalization flags
29 x [BlockSize]byte // buffer for data not yet compressed
30 nx int // number of bytes in buffer
32 ih [8]uint64 // initial chain value (after config)
33 paddedKey [BlockSize]byte // copy of key, padded with zeros
34 isKeyed bool // indicates whether hash was keyed
35 size uint8 // digest size in bytes
36 isLastNode bool // indicates processing of the last node in tree hashing
39 // Initialization values.
41 0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
42 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
43 0x510e527fade682d1, 0x9b05688c2b3e6c1f,
44 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
47 // Config is used to configure hash function parameters and keying.
48 // All parameters are optional.
50 Size uint8 // digest size (if zero, default size of 64 bytes is used)
51 Key []byte // key for prefix-MAC
52 Salt []byte // salt (if < 16 bytes, padded with zeros)
53 Person []byte // personalization (if < 16 bytes, padded with zeros)
54 Tree *Tree // parameters for tree hashing
57 // Tree represents parameters for tree hashing.
59 Fanout uint8 // fanout
60 MaxDepth uint8 // maximal depth
61 LeafSize uint32 // leaf maximal byte length (0 for unlimited)
62 NodeOffset uint64 // node offset (0 for first, leftmost or leaf)
63 NodeDepth uint8 // node depth (0 for leaves)
64 InnerHashSize uint8 // inner hash byte length
65 IsLastNode bool // indicates processing of the last node of layer
69 defaultConfig = &Config{Size: Size}
70 config256 = &Config{Size: 32}
73 func verifyConfig(c *Config) error {
75 return errors.New("digest size is too large")
77 if len(c.Key) > KeySize {
78 return errors.New("key is too large")
80 if len(c.Salt) > SaltSize {
81 // Smaller salt is okay: it will be padded with zeros.
82 return errors.New("salt is too large")
84 if len(c.Person) > PersonSize {
85 // Smaller personalization is okay: it will be padded with zeros.
86 return errors.New("personalization is too large")
89 if c.Tree.Fanout == 1 {
90 return errors.New("fanout of 1 is not allowed in tree mode")
92 if c.Tree.MaxDepth < 2 {
93 return errors.New("incorrect tree depth")
95 if c.Tree.InnerHashSize < 1 || c.Tree.InnerHashSize > Size {
96 return errors.New("incorrect tree inner hash size")
102 // New returns a new hash.Hash configured with the given Config.
103 // Config can be nil, in which case the default one is used, calculating 64-byte digest.
104 // Returns non-nil error if Config contains invalid parameters.
105 func New(c *Config) (hash.Hash, error) {
110 // Set default size if it's zero.
113 if err := verifyConfig(c); err != nil {
122 // initialize initializes digest with the given
123 // config, which must be non-nil and verified.
124 func (d *digest) initialize(c *Config) {
125 // Create parameter block.
126 var p [BlockSize]byte
128 p[1] = uint8(len(c.Key))
133 copy(p[48:], c.Person)
137 p[3] = c.Tree.MaxDepth
138 binary.LittleEndian.PutUint32(p[4:], c.Tree.LeafSize)
139 binary.LittleEndian.PutUint64(p[8:], c.Tree.NodeOffset)
140 p[16] = c.Tree.NodeDepth
141 p[17] = c.Tree.InnerHashSize
149 for i := 0; i < 8; i++ {
150 d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(p[i*8:])
152 if c.Tree != nil && c.Tree.IsLastNode {
158 copy(d.paddedKey[:], c.Key)
159 d.Write(d.paddedKey[:])
162 // Save a copy of initialized state.
163 copy(d.ih[:], d.h[:])
166 // New512 returns a new hash.Hash computing the BLAKE2b 64-byte checksum.
167 func New512() hash.Hash {
169 d.initialize(defaultConfig)
173 // New256 returns a new hash.Hash computing the BLAKE2b 32-byte checksum.
174 func New256() hash.Hash {
176 d.initialize(config256)
180 // NewMAC returns a new hash.Hash computing BLAKE2b prefix-
181 // Message Authentication Code of the given size in bytes
182 // (up to 64) with the given key (up to 64 bytes in length).
183 func NewMAC(outBytes uint8, key []byte) hash.Hash {
184 d, err := New(&Config{Size: outBytes, Key: key})
191 // Reset resets the state of digest to the initial state
192 // after configuration and keying.
193 func (d *digest) Reset() {
194 copy(d.h[:], d.ih[:])
201 d.Write(d.paddedKey[:])
205 // Size returns the digest size in bytes.
206 func (d *digest) Size() int { return int(d.size) }
208 // BlockSize returns the algorithm block size in bytes.
209 func (d *digest) BlockSize() int { return BlockSize }
211 func (d *digest) Write(p []byte) (nn int, err error) {
213 left := BlockSize - d.nx
216 copy(d.x[d.nx:], p[:left])
221 // Process full blocks except for the last one.
222 if len(p) > BlockSize {
223 n := len(p) &^ (BlockSize - 1)
231 d.nx += copy(d.x[d.nx:], p)
235 // Sum returns the calculated checksum.
236 func (d *digest) Sum(in []byte) []byte {
237 // Make a copy of d so that caller can keep writing and summing.
239 hash := d0.checkSum()
240 return append(in, hash[:d0.size]...)
243 func (d *digest) checkSum() [Size]byte {
244 // Do not create unnecessary copies of the key.
246 for i := 0; i < len(d.paddedKey); i++ {
251 dec := BlockSize - uint64(d.nx)
257 // Pad buffer with zeros.
258 for i := d.nx; i < len(d.x); i++ {
261 // Set last block flag.
262 d.f[0] = 0xffffffffffffffff
264 d.f[1] = 0xffffffffffffffff
266 // Compress last block.
271 for _, s := range d.h[:(d.size-1)/8+1] {
272 out[j+0] = byte(s >> 0)
273 out[j+1] = byte(s >> 8)
274 out[j+2] = byte(s >> 16)
275 out[j+3] = byte(s >> 24)
276 out[j+4] = byte(s >> 32)
277 out[j+5] = byte(s >> 40)
278 out[j+6] = byte(s >> 48)
279 out[j+7] = byte(s >> 56)
285 // Sum512 returns a 64-byte BLAKE2b hash of data.
286 func Sum512(data []byte) [64]byte {
288 d.initialize(defaultConfig)
293 // Sum256 returns a 32-byte BLAKE2b hash of data.
294 func Sum256(data []byte) (out [32]byte) {
296 d.initialize(config256)
299 copy(out[:], sum[:32])