github.com/devops-filetransfer/sshego@v7.0.4+incompatible/_vendor/golang.org/x/crypto/blake2s/blake2s.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 blake2s implements the BLAKE2s hash algorithm as 6 // defined in RFC 7693. 7 package blake2s // import "golang.org/x/crypto/blake2s" 8 9 import ( 10 "encoding/binary" 11 "errors" 12 "hash" 13 ) 14 15 const ( 16 // The blocksize of BLAKE2s in bytes. 17 BlockSize = 64 18 // The hash size of BLAKE2s-256 in bytes. 19 Size = 32 20 ) 21 22 var errKeySize = errors.New("blake2s: invalid key size") 23 24 var iv = [8]uint32{ 25 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 26 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, 27 } 28 29 // Sum256 returns the BLAKE2s-256 checksum of the data. 30 func Sum256(data []byte) [Size]byte { 31 var sum [Size]byte 32 checkSum(&sum, Size, data) 33 return sum 34 } 35 36 // New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil 37 // key turns the hash into a MAC. The key must between zero and 32 bytes long. 38 func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) } 39 40 func newDigest(hashSize int, key []byte) (*digest, error) { 41 if len(key) > Size { 42 return nil, errKeySize 43 } 44 d := &digest{ 45 size: hashSize, 46 keyLen: len(key), 47 } 48 copy(d.key[:], key) 49 d.Reset() 50 return d, nil 51 } 52 53 func checkSum(sum *[Size]byte, hashSize int, data []byte) { 54 var ( 55 h [8]uint32 56 c [2]uint32 57 ) 58 59 h = iv 60 h[0] ^= uint32(hashSize) | (1 << 16) | (1 << 24) 61 62 if length := len(data); length > BlockSize { 63 n := length &^ (BlockSize - 1) 64 if length == n { 65 n -= BlockSize 66 } 67 hashBlocks(&h, &c, 0, data[:n]) 68 data = data[n:] 69 } 70 71 var block [BlockSize]byte 72 offset := copy(block[:], data) 73 remaining := uint32(BlockSize - offset) 74 75 if c[0] < remaining { 76 c[1]-- 77 } 78 c[0] -= remaining 79 80 hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) 81 82 for i, v := range h { 83 binary.LittleEndian.PutUint32(sum[4*i:], v) 84 } 85 } 86 87 type digest struct { 88 h [8]uint32 89 c [2]uint32 90 size int 91 block [BlockSize]byte 92 offset int 93 94 key [BlockSize]byte 95 keyLen int 96 } 97 98 func (d *digest) BlockSize() int { return BlockSize } 99 100 func (d *digest) Size() int { return d.size } 101 102 func (d *digest) Reset() { 103 d.h = iv 104 d.h[0] ^= uint32(d.size) | (uint32(d.keyLen) << 8) | (1 << 16) | (1 << 24) 105 d.offset, d.c[0], d.c[1] = 0, 0, 0 106 if d.keyLen > 0 { 107 d.block = d.key 108 d.offset = BlockSize 109 } 110 } 111 112 func (d *digest) Write(p []byte) (n int, err error) { 113 n = len(p) 114 115 if d.offset > 0 { 116 remaining := BlockSize - d.offset 117 if n <= remaining { 118 d.offset += copy(d.block[d.offset:], p) 119 return 120 } 121 copy(d.block[d.offset:], p[:remaining]) 122 hashBlocks(&d.h, &d.c, 0, d.block[:]) 123 d.offset = 0 124 p = p[remaining:] 125 } 126 127 if length := len(p); length > BlockSize { 128 nn := length &^ (BlockSize - 1) 129 if length == nn { 130 nn -= BlockSize 131 } 132 hashBlocks(&d.h, &d.c, 0, p[:nn]) 133 p = p[nn:] 134 } 135 136 d.offset += copy(d.block[:], p) 137 return 138 } 139 140 func (d *digest) Sum(b []byte) []byte { 141 var block [BlockSize]byte 142 h := d.h 143 c := d.c 144 145 copy(block[:], d.block[:d.offset]) 146 remaining := uint32(BlockSize - d.offset) 147 if c[0] < remaining { 148 c[1]-- 149 } 150 c[0] -= remaining 151 152 hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) 153 154 var sum [Size]byte 155 for i, v := range h { 156 binary.LittleEndian.PutUint32(sum[4*i:], v) 157 } 158 159 return append(b, sum[:d.size]...) 160 }