github.com/devops-filetransfer/sshego@v7.0.4+incompatible/_vendor/golang.org/x/crypto/blake2b/blake2b.go (about) 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 as 6 // defined in RFC 7693. 7 package blake2b // import "golang.org/x/crypto/blake2b" 8 9 import ( 10 "encoding/binary" 11 "errors" 12 "hash" 13 ) 14 15 const ( 16 // The blocksize of BLAKE2b in bytes. 17 BlockSize = 128 18 // The hash size of BLAKE2b-512 in bytes. 19 Size = 64 20 // The hash size of BLAKE2b-384 in bytes. 21 Size384 = 48 22 // The hash size of BLAKE2b-256 in bytes. 23 Size256 = 32 24 ) 25 26 var ( 27 useAVX2 bool 28 useAVX bool 29 useSSE4 bool 30 ) 31 32 var errKeySize = errors.New("blake2b: invalid key size") 33 34 var iv = [8]uint64{ 35 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 36 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, 37 } 38 39 // Sum512 returns the BLAKE2b-512 checksum of the data. 40 func Sum512(data []byte) [Size]byte { 41 var sum [Size]byte 42 checkSum(&sum, Size, data) 43 return sum 44 } 45 46 // Sum384 returns the BLAKE2b-384 checksum of the data. 47 func Sum384(data []byte) [Size384]byte { 48 var sum [Size]byte 49 var sum384 [Size384]byte 50 checkSum(&sum, Size384, data) 51 copy(sum384[:], sum[:Size384]) 52 return sum384 53 } 54 55 // Sum256 returns the BLAKE2b-256 checksum of the data. 56 func Sum256(data []byte) [Size256]byte { 57 var sum [Size]byte 58 var sum256 [Size256]byte 59 checkSum(&sum, Size256, data) 60 copy(sum256[:], sum[:Size256]) 61 return sum256 62 } 63 64 // New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil 65 // key turns the hash into a MAC. The key must between zero and 64 bytes long. 66 func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } 67 68 // New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil 69 // key turns the hash into a MAC. The key must between zero and 64 bytes long. 70 func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } 71 72 // New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil 73 // key turns the hash into a MAC. The key must between zero and 64 bytes long. 74 func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } 75 76 func newDigest(hashSize int, key []byte) (*digest, error) { 77 if len(key) > Size { 78 return nil, errKeySize 79 } 80 d := &digest{ 81 size: hashSize, 82 keyLen: len(key), 83 } 84 copy(d.key[:], key) 85 d.Reset() 86 return d, nil 87 } 88 89 func checkSum(sum *[Size]byte, hashSize int, data []byte) { 90 h := iv 91 h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) 92 var c [2]uint64 93 94 if length := len(data); length > BlockSize { 95 n := length &^ (BlockSize - 1) 96 if length == n { 97 n -= BlockSize 98 } 99 hashBlocks(&h, &c, 0, data[:n]) 100 data = data[n:] 101 } 102 103 var block [BlockSize]byte 104 offset := copy(block[:], data) 105 remaining := uint64(BlockSize - offset) 106 if c[0] < remaining { 107 c[1]-- 108 } 109 c[0] -= remaining 110 111 hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) 112 113 for i, v := range h[:(hashSize+7)/8] { 114 binary.LittleEndian.PutUint64(sum[8*i:], v) 115 } 116 } 117 118 type digest struct { 119 h [8]uint64 120 c [2]uint64 121 size int 122 block [BlockSize]byte 123 offset int 124 125 key [BlockSize]byte 126 keyLen int 127 } 128 129 func (d *digest) BlockSize() int { return BlockSize } 130 131 func (d *digest) Size() int { return d.size } 132 133 func (d *digest) Reset() { 134 d.h = iv 135 d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) 136 d.offset, d.c[0], d.c[1] = 0, 0, 0 137 if d.keyLen > 0 { 138 d.block = d.key 139 d.offset = BlockSize 140 } 141 } 142 143 func (d *digest) Write(p []byte) (n int, err error) { 144 n = len(p) 145 146 if d.offset > 0 { 147 remaining := BlockSize - d.offset 148 if n <= remaining { 149 d.offset += copy(d.block[d.offset:], p) 150 return 151 } 152 copy(d.block[d.offset:], p[:remaining]) 153 hashBlocks(&d.h, &d.c, 0, d.block[:]) 154 d.offset = 0 155 p = p[remaining:] 156 } 157 158 if length := len(p); length > BlockSize { 159 nn := length &^ (BlockSize - 1) 160 if length == nn { 161 nn -= BlockSize 162 } 163 hashBlocks(&d.h, &d.c, 0, p[:nn]) 164 p = p[nn:] 165 } 166 167 if len(p) > 0 { 168 d.offset += copy(d.block[:], p) 169 } 170 171 return 172 } 173 174 func (d *digest) Sum(b []byte) []byte { 175 var block [BlockSize]byte 176 copy(block[:], d.block[:d.offset]) 177 remaining := uint64(BlockSize - d.offset) 178 179 c := d.c 180 if c[0] < remaining { 181 c[1]-- 182 } 183 c[0] -= remaining 184 185 h := d.h 186 hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) 187 188 var sum [Size]byte 189 for i, v := range h[:(d.size+7)/8] { 190 binary.LittleEndian.PutUint64(sum[8*i:], v) 191 } 192 193 return append(b, sum[:d.size]...) 194 }