1// Written in 2012 by Dmitry Chestnykh. 2// 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/ 7 8// Package blake2b implements BLAKE2b cryptographic hash function. 9package blake2b 10 11import ( 12 "encoding/binary" 13 "errors" 14 "hash" 15) 16 17const ( 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 23) 24 25type digest struct { 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 31 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 37} 38 39// Initialization values. 40var iv = [8]uint64{ 41 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 42 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 43 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 44 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, 45} 46 47// Config is used to configure hash function parameters and keying. 48// All parameters are optional. 49type Config struct { 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 55} 56 57// Tree represents parameters for tree hashing. 58type Tree struct { 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 66} 67 68var ( 69 defaultConfig = &Config{Size: Size} 70 config256 = &Config{Size: 32} 71) 72 73func verifyConfig(c *Config) error { 74 if c.Size > Size { 75 return errors.New("digest size is too large") 76 } 77 if len(c.Key) > KeySize { 78 return errors.New("key is too large") 79 } 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") 83 } 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") 87 } 88 if c.Tree != nil { 89 if c.Tree.Fanout == 1 { 90 return errors.New("fanout of 1 is not allowed in tree mode") 91 } 92 if c.Tree.MaxDepth < 2 { 93 return errors.New("incorrect tree depth") 94 } 95 if c.Tree.InnerHashSize < 1 || c.Tree.InnerHashSize > Size { 96 return errors.New("incorrect tree inner hash size") 97 } 98 } 99 return nil 100} 101 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. 105func New(c *Config) (hash.Hash, error) { 106 if c == nil { 107 c = defaultConfig 108 } else { 109 if c.Size == 0 { 110 // Set default size if it's zero. 111 c.Size = Size 112 } 113 if err := verifyConfig(c); err != nil { 114 return nil, err 115 } 116 } 117 d := new(digest) 118 d.initialize(c) 119 return d, nil 120} 121 122// initialize initializes digest with the given 123// config, which must be non-nil and verified. 124func (d *digest) initialize(c *Config) { 125 // Create parameter block. 126 var p [BlockSize]byte 127 p[0] = c.Size 128 p[1] = uint8(len(c.Key)) 129 if c.Salt != nil { 130 copy(p[32:], c.Salt) 131 } 132 if c.Person != nil { 133 copy(p[48:], c.Person) 134 } 135 if c.Tree != nil { 136 p[2] = c.Tree.Fanout 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 142 } else { 143 p[2] = 1 144 p[3] = 1 145 } 146 147 // Initialize. 148 d.size = c.Size 149 for i := 0; i < 8; i++ { 150 d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(p[i*8:]) 151 } 152 if c.Tree != nil && c.Tree.IsLastNode { 153 d.isLastNode = true 154 } 155 156 // Process key. 157 if c.Key != nil { 158 copy(d.paddedKey[:], c.Key) 159 d.Write(d.paddedKey[:]) 160 d.isKeyed = true 161 } 162 // Save a copy of initialized state. 163 copy(d.ih[:], d.h[:]) 164} 165 166// New512 returns a new hash.Hash computing the BLAKE2b 64-byte checksum. 167func New512() hash.Hash { 168 d := new(digest) 169 d.initialize(defaultConfig) 170 return d 171} 172 173// New256 returns a new hash.Hash computing the BLAKE2b 32-byte checksum. 174func New256() hash.Hash { 175 d := new(digest) 176 d.initialize(config256) 177 return d 178} 179 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). 183func NewMAC(outBytes uint8, key []byte) hash.Hash { 184 d, err := New(&Config{Size: outBytes, Key: key}) 185 if err != nil { 186 panic(err.Error()) 187 } 188 return d 189} 190 191// Reset resets the state of digest to the initial state 192// after configuration and keying. 193func (d *digest) Reset() { 194 copy(d.h[:], d.ih[:]) 195 d.t[0] = 0 196 d.t[1] = 0 197 d.f[0] = 0 198 d.f[1] = 0 199 d.nx = 0 200 if d.isKeyed { 201 d.Write(d.paddedKey[:]) 202 } 203} 204 205// Size returns the digest size in bytes. 206func (d *digest) Size() int { return int(d.size) } 207 208// BlockSize returns the algorithm block size in bytes. 209func (d *digest) BlockSize() int { return BlockSize } 210 211func (d *digest) Write(p []byte) (nn int, err error) { 212 nn = len(p) 213 left := BlockSize - d.nx 214 if len(p) > left { 215 // Process buffer. 216 copy(d.x[d.nx:], p[:left]) 217 p = p[left:] 218 compress(d, d.x[:]) 219 d.nx = 0 220 } 221 // Process full blocks except for the last one. 222 if len(p) > BlockSize { 223 n := len(p) &^ (BlockSize - 1) 224 if n == len(p) { 225 n -= BlockSize 226 } 227 compress(d, p[:n]) 228 p = p[n:] 229 } 230 // Fill buffer. 231 d.nx += copy(d.x[d.nx:], p) 232 return 233} 234 235// Sum returns the calculated checksum. 236func (d *digest) Sum(in []byte) []byte { 237 // Make a copy of d so that caller can keep writing and summing. 238 d0 := *d 239 hash := d0.checkSum() 240 return append(in, hash[:d0.size]...) 241} 242 243func (d *digest) checkSum() [Size]byte { 244 // Do not create unnecessary copies of the key. 245 if d.isKeyed { 246 for i := 0; i < len(d.paddedKey); i++ { 247 d.paddedKey[i] = 0 248 } 249 } 250 251 dec := BlockSize - uint64(d.nx) 252 if d.t[0] < dec { 253 d.t[1]-- 254 } 255 d.t[0] -= dec 256 257 // Pad buffer with zeros. 258 for i := d.nx; i < len(d.x); i++ { 259 d.x[i] = 0 260 } 261 // Set last block flag. 262 d.f[0] = 0xffffffffffffffff 263 if d.isLastNode { 264 d.f[1] = 0xffffffffffffffff 265 } 266 // Compress last block. 267 compress(d, d.x[:]) 268 269 var out [Size]byte 270 j := 0 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) 280 j += 8 281 } 282 return out 283} 284 285// Sum512 returns a 64-byte BLAKE2b hash of data. 286func Sum512(data []byte) [64]byte { 287 var d digest 288 d.initialize(defaultConfig) 289 d.Write(data) 290 return d.checkSum() 291} 292 293// Sum256 returns a 32-byte BLAKE2b hash of data. 294func Sum256(data []byte) (out [32]byte) { 295 var d digest 296 d.initialize(config256) 297 d.Write(data) 298 sum := d.checkSum() 299 copy(out[:], sum[:32]) 300 return 301} 302