github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/ledger/common/hash/sha3.go (about) 1 package hash 2 3 import ( 4 "encoding/binary" 5 ) 6 7 // All functions are copied and modified from golang.org/x/crypto/sha3 8 // This is a specific version of sha3 optimized only for the functions in 9 // this package and must not be used elsewhere 10 // 11 // Copyright (c) 2009 The Go Authors. All rights reserved. 12 13 // Redistribution and use in source and binary forms, with or without 14 // modification, are permitted provided that the following conditions are 15 // met: 16 17 // * Redistributions of source code must retain the above copyright 18 // notice, this list of conditions and the following disclaimer. 19 // * Redistributions in binary form must reproduce the above 20 // copyright notice, this list of conditions and the following disclaimer 21 // in the documentation and/or other materials provided with the 22 // distribution. 23 // * Neither the name of Google Inc. nor the names of its 24 // contributors may be used to endorse or promote products derived from 25 // this software without specific prior written permission. 26 27 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 33 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 39 const ( 40 // rate is size of the internal buffer. 41 rate = 136 42 43 // state size in 64-bit words 44 stateSize = 1600 / 64 45 46 // dsbyte contains the "domain separation" bits and the first bit of 47 // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the 48 // SHA-3 and SHAKE functions by appending bitstrings to the message. 49 // Using a little-endian bit-ordering convention, these are "01" for SHA-3 50 // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the 51 // padding rule from section 5.1 is applied to pad the message to a multiple 52 // of the rate, which involves adding a "1" bit, zero or more "0" bits, and 53 // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, 54 // giving 00000110b (0x06) and 00011111b (0x1f). 55 // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf 56 // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and 57 // Extendable-Output Functions (May 2014)" 58 dsbyte = byte(0x06) 59 paddingEnd = uint64(1 << 63) 60 ) 61 62 type state struct { 63 a [stateSize]uint64 // main state of the hash 64 } 65 66 // xor a buffer into the state at a given index. 67 func xorInAtIndex(d *state, buf []byte, index int) { 68 n := len(buf) >> 3 69 aAtIndex := d.a[index:] 70 71 for i := 0; i < n; i++ { 72 a := binary.LittleEndian.Uint64(buf) 73 aAtIndex[i] ^= a 74 buf = buf[8:] 75 } 76 } 77 78 func (d *state) hash256Plus(p1 Hash, p2 []byte) Hash { 79 //write p1 into the state 80 copyIn256(d, p1) 81 written := 32 // written bytes in the state 82 83 for len(p2)+written >= rate { 84 xorInAtIndex(d, p2[:rate-written], written>>3) 85 keccakF1600(&d.a) 86 p2 = p2[rate-written:] 87 written = 0 88 } 89 90 // xorIn the left over bytes of p2, 64 bits at a time 91 for len(p2) >= 8 { 92 a := binary.LittleEndian.Uint64(p2[:8]) 93 d.a[written>>3] ^= a 94 p2 = p2[8:] 95 written += 8 96 } 97 98 var tmp [8]byte 99 copy(tmp[:], p2) 100 tmp[len(p2)] = dsbyte 101 a := binary.LittleEndian.Uint64(tmp[:]) 102 d.a[written>>3] ^= a 103 104 // the last padding 105 d.a[16] ^= paddingEnd 106 107 // permute 108 keccakF1600(&d.a) 109 110 // reverse and output 111 return copyOut(d) 112 } 113 114 // hash256plus256 absorbs two 256 bits slices of data into the hash's state 115 // applies the permutation, and outpute the result in out 116 func (d *state) hash256plus256(p1, p2 Hash) Hash { 117 copyIn512(d, p1, p2) 118 // permute 119 keccakF1600(&d.a) 120 // reverse the endianess to the output 121 return copyOut(d) 122 }