github.com/onflow/flow-go/crypto@v0.24.8/hash/keccak.go (about) 1 package hash 2 3 // Size returns the output size of the hash function in bytes. 4 func (d *spongeState) Size() int { 5 return d.outputLen 6 } 7 8 // Algorithm returns the hashing algorithm of the instance. 9 func (s *spongeState) Algorithm() HashingAlgorithm { 10 return s.algo 11 } 12 13 // ComputeHash calculates and returns the digest of the input. 14 // It updates the state (and therefore not thread-safe) and doesn't allow 15 // further writing without calling Reset(). 16 func (s *spongeState) ComputeHash(data []byte) Hash { 17 s.Reset() 18 s.write(data) 19 return s.sum() 20 } 21 22 // SumHash returns the digest of the data written to the state. 23 // It updates the state and doesn't allow further writing without 24 // calling Reset(). 25 func (s *spongeState) SumHash() Hash { 26 return s.sum() 27 } 28 29 // Write absorbs more data into the hash's state. 30 // It returns the number of bytes written and never errors. 31 func (d *spongeState) Write(p []byte) (int, error) { 32 d.write(p) 33 return len(p), nil 34 } 35 36 // The functions below were copied and modified from golang.org/x/crypto/sha3. 37 // 38 // Copyright (c) 2009 The Go Authors. All rights reserved. 39 40 // Redistribution and use in source and binary forms, with or without 41 // modification, are permitted provided that the following conditions are 42 // met: 43 44 // * Redistributions of source code must retain the above copyright 45 // notice, this list of conditions and the following disclaimer. 46 // * Redistributions in binary form must reproduce the above 47 // copyright notice, this list of conditions and the following disclaimer 48 // in the documentation and/or other materials provided with the 49 // distribution. 50 // * Neither the name of Google Inc. nor the names of its 51 // contributors may be used to endorse or promote products derived from 52 // this software without specific prior written permission. 53 54 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 55 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 56 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 57 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 58 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 59 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 60 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 61 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 62 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 63 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 64 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 65 66 type spongeState struct { 67 // the hashing algorithm name 68 algo HashingAlgorithm 69 70 a [25]uint64 // main state of the hash 71 storage storageBuf // constant size array 72 // `buf` is a sub-slice that points into `storage` using `bufIndex` and `bufSize`: 73 // - `bufIndex` is the index of the first element of buf 74 // - `bufSize` is the size of buf 75 bufIndex int 76 bufSize int 77 rate int // the number of bytes of state to use 78 // dsbyte contains the domain separation bits (if any are defined) 79 // and the first bit of the 10*1 padding. 80 // Using a little-endian bit-ordering convention, it is 0b01 for SHA-3 81 // and not defined for legacy Keccak. 82 // The padding 10*1 is applied to pad the message to a multiple 83 // of the rate, which involves adding a "1" bit, zero or more "0" bits, and 84 // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, 85 // ( giving 0b00000110 for SHA-3 and 0b00000001 for legacy Keccak) 86 // [1] https://keccak.team/sponge_duplex.html 87 // "The sponge and duplex constructions" 88 dsByte byte // the domain separation byte with one bit padding 89 outputLen int // the default output size in bytes 90 } 91 92 const ( 93 // maxRate is the maximum size of the internal buffer. SHA3-256 94 // currently needs the largest buffer among supported sponge-based 95 // algorithms. 96 maxRate = rateSHA3_256 97 98 // initialization value of the buffer index 99 bufNilValue = -1 100 ) 101 102 // returns the current buf 103 func (d *spongeState) buf() []byte { 104 return d.storage.asBytes()[d.bufIndex : d.bufIndex+d.bufSize] 105 } 106 107 // setBuf assigns `buf` (sub-slice of `storage`) to a sub-slice of `storage` 108 // defined by a starting index and size. 109 func (d *spongeState) setBuf(start, size int) { 110 d.bufIndex = start 111 d.bufSize = size 112 } 113 114 // checks if `buf` is nil (not yet set) 115 func (d *spongeState) bufIsNil() bool { 116 return d.bufSize == bufNilValue 117 } 118 119 // appendBuf appends a slice to `buf` (sub-slice of `storage`) 120 // The function assumes the appended buffer still fits into `storage`. 121 func (d *spongeState) appendBuf(slice []byte) { 122 copy(d.storage.asBytes()[d.bufIndex+d.bufSize:], slice) 123 d.bufSize += len(slice) 124 } 125 126 // Reset clears the internal state. 127 func (d *spongeState) Reset() { 128 // Zero the permutation's state. 129 for i := range d.a { 130 d.a[i] = 0 131 } 132 d.setBuf(0, 0) 133 } 134 135 // permute applies the KeccakF-1600 permutation. 136 func (d *spongeState) permute() { 137 // xor the input into the state before applying the permutation. 138 xorIn(d, d.buf()) 139 d.setBuf(0, 0) 140 keccakF1600(&d.a) 141 } 142 143 func (d *spongeState) write(p []byte) { 144 if d.bufIsNil() { 145 d.setBuf(0, 0) 146 } 147 148 for len(p) > 0 { 149 if d.bufSize == 0 && len(p) >= d.rate { 150 // The fast path; absorb a full "rate" bytes of input and apply the permutation. 151 xorIn(d, p[:d.rate]) 152 p = p[d.rate:] 153 keccakF1600(&d.a) 154 } else { 155 // The slow path; buffer the input until we can fill the sponge, and then xor it in. 156 todo := d.rate - d.bufSize 157 if todo > len(p) { 158 todo = len(p) 159 } 160 d.appendBuf(p[:todo]) 161 p = p[todo:] 162 163 // If the sponge is full, apply the permutation. 164 if d.bufSize == d.rate { 165 d.permute() 166 } 167 } 168 } 169 } 170 171 // pads appends the domain separation bits in dsbyte, applies 172 // the multi-bitrate 10..1 padding rule, and permutes the state. 173 func (d *spongeState) padAndPermute() { 174 if d.bufIsNil() { 175 d.setBuf(0, 0) 176 } 177 // Pad with this instance with dsbyte. We know that there's 178 // at least one byte of space in d.buf because, if it were full, 179 // permute would have been called to empty it. dsbyte also contains the 180 // first one bit for the padding. See the comment in the state struct. 181 d.appendBuf([]byte{d.dsByte}) 182 zerosStart := d.bufSize 183 d.setBuf(0, d.rate) 184 buf := d.buf() 185 for i := zerosStart; i < d.rate; i++ { 186 buf[i] = 0 187 } 188 // This adds the final one bit for the padding. Because of the way that 189 // bits are numbered from the LSB upwards, the final bit is the MSB of 190 // the last byte. 191 buf[d.rate-1] ^= 0x80 192 // Apply the permutation 193 d.permute() 194 d.setBuf(0, d.rate) 195 } 196 197 // Sum applies padding to the hash state and then squeezes out the desired 198 // number of output bytes. 199 func (d *spongeState) sum() []byte { 200 hash := make([]byte, d.outputLen) 201 d.padAndPermute() 202 copyOut(hash, d) 203 return hash 204 }