| 1 | // Copyright (c) 2023 Kim Shrier. All rights reserved. |
| 2 | // Use of this source code is governed by an MIT license |
| 3 | // that can be found in the LICENSE file. |
| 4 | // Package sha3 implements the 512, 384, 256, and 224 |
| 5 | // bit hash algorithms and the 128 and 256 bit |
| 6 | // extended output functions as defined in |
| 7 | // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf. |
| 8 | // Last updated: August 2015 |
| 9 | module sha3 |
| 10 | |
| 11 | import math.bits |
| 12 | |
| 13 | // when the state is 1600 bits, a lane is 64 bits |
| 14 | type Lane = u64 |
| 15 | |
| 16 | // the state is a 5 x 5 array of lanes |
| 17 | struct State { |
| 18 | mut: |
| 19 | a [5][5]Lane |
| 20 | } |
| 21 | |
| 22 | @[direct_array_access; inline] |
| 23 | fn read_u64_le_at(b []u8, offset int) u64 { |
| 24 | _ = b[offset] |
| 25 | _ = b[offset + 7] |
| 26 | return u64(b[offset]) | (u64(b[offset + 1]) << 8) | (u64(b[offset + 2]) << 16) | (u64(b[ |
| 27 | offset + 3]) << 24) | (u64(b[offset + 4]) << 32) | (u64(b[offset + 5]) << 40) | (u64(b[ |
| 28 | offset + 6]) << 48) | (u64(b[offset + 7]) << 56) |
| 29 | } |
| 30 | |
| 31 | @[direct_array_access; inline] |
| 32 | fn put_u64_le_at(mut b []u8, value u64, offset int) { |
| 33 | _ = b[offset] |
| 34 | _ = b[offset + 7] |
| 35 | b[offset] = u8(value) |
| 36 | b[offset + 1] = u8(value >> 8) |
| 37 | b[offset + 2] = u8(value >> 16) |
| 38 | b[offset + 3] = u8(value >> 24) |
| 39 | b[offset + 4] = u8(value >> 32) |
| 40 | b[offset + 5] = u8(value >> 40) |
| 41 | b[offset + 6] = u8(value >> 48) |
| 42 | b[offset + 7] = u8(value >> 56) |
| 43 | } |
| 44 | |
| 45 | // to_bytes converts the state into a byte array |
| 46 | // |
| 47 | // A 1600 bit state fits into 200 bytes. |
| 48 | // |
| 49 | // The state consists of 25 u64 values arranged in a |
| 50 | // 5 x 5 array. |
| 51 | // |
| 52 | // The state is not modified by this method. |
| 53 | @[direct_array_access] |
| 54 | fn (s State) to_bytes() []u8 { |
| 55 | mut byte_array := []u8{len: 200} |
| 56 | mut index := 0 |
| 57 | |
| 58 | for y in 0 .. 5 { |
| 59 | for x in 0 .. 5 { |
| 60 | put_u64_le_at(mut byte_array, s.a[x][y], index) |
| 61 | index += 8 |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | return byte_array |
| 66 | } |
| 67 | |
| 68 | // from_bytes sets the state from an array of bytes |
| 69 | // |
| 70 | // A 1600 bit state fits into 200 bytes. It is expected |
| 71 | // that the input byte array is 200 bytes long. |
| 72 | // |
| 73 | // All 25 u64 values are set from the input byte array. |
| 74 | @[direct_array_access] |
| 75 | fn (mut s State) from_bytes(byte_array []u8) { |
| 76 | mut index := 0 |
| 77 | |
| 78 | for y in 0 .. 5 { |
| 79 | for x in 0 .. 5 { |
| 80 | s.a[x][y] = read_u64_le_at(byte_array, index) |
| 81 | index += 8 |
| 82 | } |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | // xor_bytes xor's an array of bytes into the state |
| 87 | // |
| 88 | // This is how new data gets absorbed into the sponge. |
| 89 | // |
| 90 | // It is expected that the length of the byte array is |
| 91 | // the same as the rate. The rate is how many bytes |
| 92 | // can be absorbed at one permutation of the state. |
| 93 | // |
| 94 | // The rate must be less than the size of the state |
| 95 | // in bytes. |
| 96 | @[direct_array_access] |
| 97 | fn (mut s State) xor_bytes(byte_array []u8, rate int) { |
| 98 | mut index := 0 |
| 99 | |
| 100 | for y in 0 .. 5 { |
| 101 | for x in 0 .. 5 { |
| 102 | s.a[x][y] ^= read_u64_le_at(byte_array, index) |
| 103 | index += 8 |
| 104 | |
| 105 | if index >= rate { |
| 106 | return |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | // kaccak_p_1600_24 performs 24 rounnds on a 1600 bit state. |
| 113 | // |
| 114 | @[direct_array_access] |
| 115 | fn (mut s State) kaccak_p_1600_24() { |
| 116 | mut b := [5][5]Lane{} |
| 117 | for round_index in 0 .. 24 { |
| 118 | // theta |
| 119 | // C[x] = A[x,0] xor A[x,1] xor A[x,2] xor A[x,3] xor A[x,4], for x in 0…4 |
| 120 | // D[x] = C[x-1] xor rot(C[x+1],1), for x in 0…4 |
| 121 | // A[x,y] = A[x,y] xor D[x], for (x,y) in (0…4,0…4) |
| 122 | c0 := s.a[0][0] ^ s.a[0][1] ^ s.a[0][2] ^ s.a[0][3] ^ s.a[0][4] |
| 123 | c1 := s.a[1][0] ^ s.a[1][1] ^ s.a[1][2] ^ s.a[1][3] ^ s.a[1][4] |
| 124 | c2 := s.a[2][0] ^ s.a[2][1] ^ s.a[2][2] ^ s.a[2][3] ^ s.a[2][4] |
| 125 | c3 := s.a[3][0] ^ s.a[3][1] ^ s.a[3][2] ^ s.a[3][3] ^ s.a[3][4] |
| 126 | c4 := s.a[4][0] ^ s.a[4][1] ^ s.a[4][2] ^ s.a[4][3] ^ s.a[4][4] |
| 127 | |
| 128 | d0 := c4 ^ bits.rotate_left_64(c1, 1) |
| 129 | d1 := c0 ^ bits.rotate_left_64(c2, 1) |
| 130 | d2 := c1 ^ bits.rotate_left_64(c3, 1) |
| 131 | d3 := c2 ^ bits.rotate_left_64(c4, 1) |
| 132 | d4 := c3 ^ bits.rotate_left_64(c0, 1) |
| 133 | |
| 134 | // vfmt off |
| 135 | s.a[0][0] ^= d0 s.a[0][1] ^= d0 s.a[0][2] ^= d0 s.a[0][3] ^= d0 s.a[0][4] ^= d0 |
| 136 | s.a[1][0] ^= d1 s.a[1][1] ^= d1 s.a[1][2] ^= d1 s.a[1][3] ^= d1 s.a[1][4] ^= d1 |
| 137 | s.a[2][0] ^= d2 s.a[2][1] ^= d2 s.a[2][2] ^= d2 s.a[2][3] ^= d2 s.a[2][4] ^= d2 |
| 138 | s.a[3][0] ^= d3 s.a[3][1] ^= d3 s.a[3][2] ^= d3 s.a[3][3] ^= d3 s.a[3][4] ^= d3 |
| 139 | s.a[4][0] ^= d4 s.a[4][1] ^= d4 s.a[4][2] ^= d4 s.a[4][3] ^= d4 s.a[4][4] ^= d4 |
| 140 | // vfmt on |
| 141 | |
| 142 | // rho and pi |
| 143 | // B[y,2*x+3*y] = rot(A[x,y], r[x,y]), for (x,y) in (0…4,0…4) |
| 144 | b[0][0] = s.a[0][0] |
| 145 | b[0][1] = bits.rotate_left_64(s.a[3][0], 28) |
| 146 | b[0][2] = bits.rotate_left_64(s.a[1][0], 1) |
| 147 | b[0][3] = bits.rotate_left_64(s.a[4][0], 27) |
| 148 | b[0][4] = bits.rotate_left_64(s.a[2][0], 62) |
| 149 | |
| 150 | b[1][0] = bits.rotate_left_64(s.a[1][1], 44) |
| 151 | b[1][1] = bits.rotate_left_64(s.a[4][1], 20) |
| 152 | b[1][2] = bits.rotate_left_64(s.a[2][1], 6) |
| 153 | b[1][3] = bits.rotate_left_64(s.a[0][1], 36) |
| 154 | b[1][4] = bits.rotate_left_64(s.a[3][1], 55) |
| 155 | |
| 156 | b[2][0] = bits.rotate_left_64(s.a[2][2], 43) |
| 157 | b[2][1] = bits.rotate_left_64(s.a[0][2], 3) |
| 158 | b[2][2] = bits.rotate_left_64(s.a[3][2], 25) |
| 159 | b[2][3] = bits.rotate_left_64(s.a[1][2], 10) |
| 160 | b[2][4] = bits.rotate_left_64(s.a[4][2], 39) |
| 161 | |
| 162 | b[3][0] = bits.rotate_left_64(s.a[3][3], 21) |
| 163 | b[3][1] = bits.rotate_left_64(s.a[1][3], 45) |
| 164 | b[3][2] = bits.rotate_left_64(s.a[4][3], 8) |
| 165 | b[3][3] = bits.rotate_left_64(s.a[2][3], 15) |
| 166 | b[3][4] = bits.rotate_left_64(s.a[0][3], 41) |
| 167 | |
| 168 | b[4][0] = bits.rotate_left_64(s.a[4][4], 14) |
| 169 | b[4][1] = bits.rotate_left_64(s.a[2][4], 61) |
| 170 | b[4][2] = bits.rotate_left_64(s.a[0][4], 18) |
| 171 | b[4][3] = bits.rotate_left_64(s.a[3][4], 56) |
| 172 | b[4][4] = bits.rotate_left_64(s.a[1][4], 2) |
| 173 | |
| 174 | // chi |
| 175 | // A[x,y] = B[x,y] xor ((not B[x+1,y]) and B[x+2,y]), for (x,y) in (0…4,0…4) |
| 176 | for y in 0 .. 5 { |
| 177 | s.a[0][y] = b[0][y] ^ (~b[1][y] & b[2][y]) |
| 178 | s.a[1][y] = b[1][y] ^ (~b[2][y] & b[3][y]) |
| 179 | s.a[2][y] = b[2][y] ^ (~b[3][y] & b[4][y]) |
| 180 | s.a[3][y] = b[3][y] ^ (~b[4][y] & b[0][y]) |
| 181 | s.a[4][y] = b[4][y] ^ (~b[0][y] & b[1][y]) |
| 182 | } |
| 183 | |
| 184 | // iota |
| 185 | // A[0,0] = A[0,0] xor RC |
| 186 | s.a[0][0] ^= iota_round_constants[round_index] |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | // iota_round_constants are precomputed xor masks for the iota function |
| 191 | const iota_round_constants = [u64(0x0000000000000001), 0x0000000000008082, 0x800000000000808a, |
| 192 | 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, |
| 193 | 0x8000000000008009, 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, |
| 194 | 0x000000008000000a, 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, |
| 195 | 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, |
| 196 | 0x800000008000000a, 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, |
| 197 | 0x8000000080008008] |
| 198 | |