1// Copyright 2016 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 6// and the extendable output function (XOF) BLAKE2Xb. 7// 8// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf 9// and for BLAKE2Xb see https://blake2.net/blake2x.pdf 10// 11// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512). 12// If you need a secret-key MAC (message authentication code), use the New512 13// function with a non-nil key. 14// 15// BLAKE2X is a construction to compute hash values larger than 64 bytes. It 16// can produce hash values between 0 and 4 GiB. 17package blake2b 18 19import ( 20 "encoding/binary" 21 "errors" 22 "hash" 23) 24 25const ( 26 // The blocksize of BLAKE2b in bytes. 27 BlockSize = 128 28 // The hash size of BLAKE2b-512 in bytes. 29 Size = 64 30 // The hash size of BLAKE2b-384 in bytes. 31 Size384 = 48 32 // The hash size of BLAKE2b-256 in bytes. 33 Size256 = 32 34) 35 36var ( 37 useAVX2 bool 38 useAVX bool 39 useSSE4 bool 40) 41 42var ( 43 errKeySize = errors.New("blake2b: invalid key size") 44 errHashSize = errors.New("blake2b: invalid hash size") 45) 46 47var iv = [8]uint64{ 48 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 49 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, 50} 51 52// Sum512 returns the BLAKE2b-512 checksum of the data. 53func Sum512(data []byte) [Size]byte { 54 var sum [Size]byte 55 checkSum(&sum, Size, data) 56 return sum 57} 58 59// Sum384 returns the BLAKE2b-384 checksum of the data. 60func Sum384(data []byte) [Size384]byte { 61 var sum [Size]byte 62 var sum384 [Size384]byte 63 checkSum(&sum, Size384, data) 64 copy(sum384[:], sum[:Size384]) 65 return sum384 66} 67 68// Sum256 returns the BLAKE2b-256 checksum of the data. 69func Sum256(data []byte) [Size256]byte { 70 var sum [Size]byte 71 var sum256 [Size256]byte 72 checkSum(&sum, Size256, data) 73 copy(sum256[:], sum[:Size256]) 74 return sum256 75} 76 77// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil 78// key turns the hash into a MAC. The key must between zero and 64 bytes long. 79func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } 80 81// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil 82// key turns the hash into a MAC. The key must between zero and 64 bytes long. 83func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } 84 85// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil 86// key turns the hash into a MAC. The key must between zero and 64 bytes long. 87func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } 88 89// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length. 90// A non-nil key turns the hash into a MAC. The key must between zero and 64 bytes long. 91// The hash size can be a value between 1 and 64 but it is highly recommended to use 92// values equal or greater than: 93// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). 94// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). 95func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } 96 97func newDigest(hashSize int, key []byte) (*digest, error) { 98 if hashSize < 1 || hashSize > Size { 99 return nil, errHashSize 100 } 101 if len(key) > Size { 102 return nil, errKeySize 103 } 104 d := &digest{ 105 size: hashSize, 106 keyLen: len(key), 107 } 108 copy(d.key[:], key) 109 d.Reset() 110 return d, nil 111} 112 113func checkSum(sum *[Size]byte, hashSize int, data []byte) { 114 h := iv 115 h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) 116 var c [2]uint64 117 118 if length := len(data); length > BlockSize { 119 n := length &^ (BlockSize - 1) 120 if length == n { 121 n -= BlockSize 122 } 123 hashBlocks(&h, &c, 0, data[:n]) 124 data = data[n:] 125 } 126 127 var block [BlockSize]byte 128 offset := copy(block[:], data) 129 remaining := uint64(BlockSize - offset) 130 if c[0] < remaining { 131 c[1]-- 132 } 133 c[0] -= remaining 134 135 hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) 136 137 for i, v := range h[:(hashSize+7)/8] { 138 binary.LittleEndian.PutUint64(sum[8*i:], v) 139 } 140} 141 142type digest struct { 143 h [8]uint64 144 c [2]uint64 145 size int 146 block [BlockSize]byte 147 offset int 148 149 key [BlockSize]byte 150 keyLen int 151} 152 153func (d *digest) BlockSize() int { return BlockSize } 154 155func (d *digest) Size() int { return d.size } 156 157func (d *digest) Reset() { 158 d.h = iv 159 d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) 160 d.offset, d.c[0], d.c[1] = 0, 0, 0 161 if d.keyLen > 0 { 162 d.block = d.key 163 d.offset = BlockSize 164 } 165} 166 167func (d *digest) Write(p []byte) (n int, err error) { 168 n = len(p) 169 170 if d.offset > 0 { 171 remaining := BlockSize - d.offset 172 if n <= remaining { 173 d.offset += copy(d.block[d.offset:], p) 174 return 175 } 176 copy(d.block[d.offset:], p[:remaining]) 177 hashBlocks(&d.h, &d.c, 0, d.block[:]) 178 d.offset = 0 179 p = p[remaining:] 180 } 181 182 if length := len(p); length > BlockSize { 183 nn := length &^ (BlockSize - 1) 184 if length == nn { 185 nn -= BlockSize 186 } 187 hashBlocks(&d.h, &d.c, 0, p[:nn]) 188 p = p[nn:] 189 } 190 191 if len(p) > 0 { 192 d.offset += copy(d.block[:], p) 193 } 194 195 return 196} 197 198func (d *digest) Sum(sum []byte) []byte { 199 var hash [Size]byte 200 d.finalize(&hash) 201 return append(sum, hash[:d.size]...) 202} 203 204func (d *digest) finalize(hash *[Size]byte) { 205 var block [BlockSize]byte 206 copy(block[:], d.block[:d.offset]) 207 remaining := uint64(BlockSize - d.offset) 208 209 c := d.c 210 if c[0] < remaining { 211 c[1]-- 212 } 213 c[0] -= remaining 214 215 h := d.h 216 hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) 217 218 for i, v := range h { 219 binary.LittleEndian.PutUint64(hash[8*i:], v) 220 } 221} 222