github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/cryptonight/keccak.go (about) 1 // Copyright 2017-2018 DERO Project. All rights reserved. 2 // Use of this source code in any form is governed by RESEARCH license. 3 // license can be found in the LICENSE file. 4 // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8 5 // 6 // 7 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 8 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 10 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 12 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 13 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 14 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 15 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 17 // TODO keccak is available in 3 of our packages we need to merge them when the alpha version is out 18 // Package keccak implements the Keccak (SHA-3) hash algorithm. 19 // http://keccak.noekeon.org / FIPS 202 draft. 20 package cryptonight 21 22 // import "fmt" 23 import "hash" 24 25 const ( 26 domainNone = 1 27 domainSHA3 = 0x06 28 domainSHAKE = 0x1f 29 ) 30 31 const rounds = 24 32 33 var roundConstants = []uint64{ 34 0x0000000000000001, 0x0000000000008082, 35 0x800000000000808A, 0x8000000080008000, 36 0x000000000000808B, 0x0000000080000001, 37 0x8000000080008081, 0x8000000000008009, 38 0x000000000000008A, 0x0000000000000088, 39 0x0000000080008009, 0x000000008000000A, 40 0x000000008000808B, 0x800000000000008B, 41 0x8000000000008089, 0x8000000000008003, 42 0x8000000000008002, 0x8000000000000080, 43 0x000000000000800A, 0x800000008000000A, 44 0x8000000080008081, 0x8000000000008080, 45 0x0000000080000001, 0x8000000080008008, 46 } 47 48 type keccak struct { 49 S [25]uint64 50 size int 51 blockSize int 52 buf []byte 53 domain byte 54 } 55 56 func newKeccak(capacity, output int, domain byte) hash.Hash { 57 var h keccak 58 h.size = output / 8 59 h.blockSize = (200 - capacity/8) 60 h.domain = domain 61 return &h 62 } 63 64 func New224() hash.Hash { 65 return newKeccak(224*2, 224, domainNone) 66 } 67 68 func New256() hash.Hash { 69 return newKeccak(256*2, 256, domainNone) 70 } 71 72 func New384() hash.Hash { 73 return newKeccak(384*2, 384, domainNone) 74 } 75 76 func New512() hash.Hash { 77 return newKeccak(512*2, 512, domainNone) 78 } 79 80 func (k *keccak) Write(b []byte) (int, error) { 81 n := len(b) 82 83 if len(k.buf) > 0 { 84 x := k.blockSize - len(k.buf) 85 if x > len(b) { 86 x = len(b) 87 } 88 k.buf = append(k.buf, b[:x]...) 89 b = b[x:] 90 91 if len(k.buf) < k.blockSize { 92 return n, nil 93 } 94 95 k.absorb(k.buf) 96 k.buf = nil 97 } 98 99 for len(b) >= k.blockSize { 100 k.absorb(b[:k.blockSize]) 101 b = b[k.blockSize:] 102 } 103 104 k.buf = b 105 106 return n, nil 107 } 108 109 func (k0 *keccak) Sum(b []byte) []byte { 110 k := *k0 111 k.final() 112 return k.squeeze(b) 113 } 114 115 func (k *keccak) Reset() { 116 for i := range k.S { 117 k.S[i] = 0 118 } 119 k.buf = nil 120 } 121 122 func (k *keccak) Size() int { 123 return k.size 124 } 125 126 func (k *keccak) BlockSize() int { 127 return k.blockSize 128 } 129 130 func (k *keccak) absorb(block []byte) { 131 if len(block) != k.blockSize { 132 panic("absorb() called with invalid block size") 133 } 134 135 for i := 0; i < k.blockSize/8; i++ { 136 k.S[i] ^= uint64le(block[i*8:]) 137 } 138 keccakf(&k.S) 139 } 140 141 func (k *keccak) pad(block []byte) []byte { 142 143 padded := make([]byte, k.blockSize) 144 145 copy(padded, k.buf) 146 padded[len(k.buf)] = k.domain 147 padded[len(padded)-1] |= 0x80 148 149 return padded 150 } 151 152 func (k *keccak) final() { 153 last := k.pad(k.buf) 154 k.absorb(last) 155 } 156 157 func (k *keccak) squeeze(b []byte) []byte { 158 buf := make([]byte, 8*len(k.S)) 159 n := k.size 160 for { 161 for i := range k.S { 162 putUint64le(buf[i*8:], k.S[i]) 163 } 164 if n <= k.blockSize { 165 b = append(b, buf[:n]...) 166 break 167 } 168 b = append(b, buf[:k.blockSize]...) 169 n -= k.blockSize 170 keccakf(&k.S) 171 } 172 return b 173 } 174 175 func keccakf(S *[25]uint64) { 176 var bc0, bc1, bc2, bc3, bc4 uint64 177 var S0, S1, S2, S3, S4 uint64 178 var S5, S6, S7, S8, S9 uint64 179 var S10, S11, S12, S13, S14 uint64 180 var S15, S16, S17, S18, S19 uint64 181 var S20, S21, S22, S23, S24 uint64 182 var tmp uint64 183 184 //S[0]=0x2073692073696854; 185 //S[1]=0x1747365742061 186 // S[16]=0x8000000000000000; 187 188 /* for i :=0; i< 25;i++{ 189 fmt.Printf("%2d %X\n", i, S[i]) 190 } 191 */ 192 193 S0, S1, S2, S3, S4 = S[0], S[1], S[2], S[3], S[4] 194 S5, S6, S7, S8, S9 = S[5], S[6], S[7], S[8], S[9] 195 S10, S11, S12, S13, S14 = S[10], S[11], S[12], S[13], S[14] 196 S15, S16, S17, S18, S19 = S[15], S[16], S[17], S[18], S[19] 197 S20, S21, S22, S23, S24 = S[20], S[21], S[22], S[23], S[24] 198 199 for r := 0; r < rounds; r++ { 200 // theta 201 bc0 = S0 ^ S5 ^ S10 ^ S15 ^ S20 202 bc1 = S1 ^ S6 ^ S11 ^ S16 ^ S21 203 bc2 = S2 ^ S7 ^ S12 ^ S17 ^ S22 204 bc3 = S3 ^ S8 ^ S13 ^ S18 ^ S23 205 bc4 = S4 ^ S9 ^ S14 ^ S19 ^ S24 206 tmp = bc4 ^ (bc1<<1 | bc1>>(64-1)) 207 S0 ^= tmp 208 S5 ^= tmp 209 S10 ^= tmp 210 S15 ^= tmp 211 S20 ^= tmp 212 tmp = bc0 ^ (bc2<<1 | bc2>>(64-1)) 213 S1 ^= tmp 214 S6 ^= tmp 215 S11 ^= tmp 216 S16 ^= tmp 217 S21 ^= tmp 218 tmp = bc1 ^ (bc3<<1 | bc3>>(64-1)) 219 S2 ^= tmp 220 S7 ^= tmp 221 S12 ^= tmp 222 S17 ^= tmp 223 S22 ^= tmp 224 tmp = bc2 ^ (bc4<<1 | bc4>>(64-1)) 225 S3 ^= tmp 226 S8 ^= tmp 227 S13 ^= tmp 228 S18 ^= tmp 229 S23 ^= tmp 230 tmp = bc3 ^ (bc0<<1 | bc0>>(64-1)) 231 S4 ^= tmp 232 S9 ^= tmp 233 S14 ^= tmp 234 S19 ^= tmp 235 S24 ^= tmp 236 237 // rho phi 238 tmp = S1 239 tmp, S10 = S10, tmp<<1|tmp>>(64-1) 240 tmp, S7 = S7, tmp<<3|tmp>>(64-3) 241 tmp, S11 = S11, tmp<<6|tmp>>(64-6) 242 tmp, S17 = S17, tmp<<10|tmp>>(64-10) 243 tmp, S18 = S18, tmp<<15|tmp>>(64-15) 244 tmp, S3 = S3, tmp<<21|tmp>>(64-21) 245 tmp, S5 = S5, tmp<<28|tmp>>(64-28) 246 tmp, S16 = S16, tmp<<36|tmp>>(64-36) 247 tmp, S8 = S8, tmp<<45|tmp>>(64-45) 248 tmp, S21 = S21, tmp<<55|tmp>>(64-55) 249 tmp, S24 = S24, tmp<<2|tmp>>(64-2) 250 tmp, S4 = S4, tmp<<14|tmp>>(64-14) 251 tmp, S15 = S15, tmp<<27|tmp>>(64-27) 252 tmp, S23 = S23, tmp<<41|tmp>>(64-41) 253 tmp, S19 = S19, tmp<<56|tmp>>(64-56) 254 tmp, S13 = S13, tmp<<8|tmp>>(64-8) 255 tmp, S12 = S12, tmp<<25|tmp>>(64-25) 256 tmp, S2 = S2, tmp<<43|tmp>>(64-43) 257 tmp, S20 = S20, tmp<<62|tmp>>(64-62) 258 tmp, S14 = S14, tmp<<18|tmp>>(64-18) 259 tmp, S22 = S22, tmp<<39|tmp>>(64-39) 260 tmp, S9 = S9, tmp<<61|tmp>>(64-61) 261 tmp, S6 = S6, tmp<<20|tmp>>(64-20) 262 S1 = tmp<<44 | tmp>>(64-44) 263 264 // chi 265 bc0 = S0 266 bc1 = S1 267 bc2 = S2 268 bc3 = S3 269 bc4 = S4 270 S0 ^= (^bc1) & bc2 271 S1 ^= (^bc2) & bc3 272 S2 ^= (^bc3) & bc4 273 S3 ^= (^bc4) & bc0 274 S4 ^= (^bc0) & bc1 275 bc0 = S5 276 bc1 = S6 277 bc2 = S7 278 bc3 = S8 279 bc4 = S9 280 S5 ^= (^bc1) & bc2 281 S6 ^= (^bc2) & bc3 282 S7 ^= (^bc3) & bc4 283 S8 ^= (^bc4) & bc0 284 S9 ^= (^bc0) & bc1 285 bc0 = S10 286 bc1 = S11 287 bc2 = S12 288 bc3 = S13 289 bc4 = S14 290 S10 ^= (^bc1) & bc2 291 S11 ^= (^bc2) & bc3 292 S12 ^= (^bc3) & bc4 293 S13 ^= (^bc4) & bc0 294 S14 ^= (^bc0) & bc1 295 bc0 = S15 296 bc1 = S16 297 bc2 = S17 298 bc3 = S18 299 bc4 = S19 300 S15 ^= (^bc1) & bc2 301 S16 ^= (^bc2) & bc3 302 S17 ^= (^bc3) & bc4 303 S18 ^= (^bc4) & bc0 304 S19 ^= (^bc0) & bc1 305 bc0 = S20 306 bc1 = S21 307 bc2 = S22 308 bc3 = S23 309 bc4 = S24 310 S20 ^= (^bc1) & bc2 311 S21 ^= (^bc2) & bc3 312 S22 ^= (^bc3) & bc4 313 S23 ^= (^bc4) & bc0 314 S24 ^= (^bc0) & bc1 315 316 // iota 317 S0 ^= roundConstants[r] 318 } 319 320 S[0], S[1], S[2], S[3], S[4] = S0, S1, S2, S3, S4 321 S[5], S[6], S[7], S[8], S[9] = S5, S6, S7, S8, S9 322 S[10], S[11], S[12], S[13], S[14] = S10, S11, S12, S13, S14 323 S[15], S[16], S[17], S[18], S[19] = S15, S16, S17, S18, S19 324 S[20], S[21], S[22], S[23], S[24] = S20, S21, S22, S23, S24 325 326 } 327 328 func uint64le(v []byte) uint64 { 329 return uint64(v[0]) | 330 uint64(v[1])<<8 | 331 uint64(v[2])<<16 | 332 uint64(v[3])<<24 | 333 uint64(v[4])<<32 | 334 uint64(v[5])<<40 | 335 uint64(v[6])<<48 | 336 uint64(v[7])<<56 337 338 } 339 340 func putUint64le(v []byte, x uint64) { 341 v[0] = byte(x) 342 v[1] = byte(x >> 8) 343 v[2] = byte(x >> 16) 344 v[3] = byte(x >> 24) 345 v[4] = byte(x >> 32) 346 v[5] = byte(x >> 40) 347 v[6] = byte(x >> 48) 348 v[7] = byte(x >> 56) 349 }