ethereum.crypto.blake2
The Blake2 Implementation.
spit_le_to_uint
Extracts 8 byte words from a given data.
Parameters
data : The data in bytes from which the words need to be extracted start : Position to start the extraction num_words: The number of words to be extracted
def spit_le_to_uint(data: bytes, start: int, num_words: int) -> List[Uint]:
| 11 | """ |
|---|---|
| 12 | Extracts 8 byte words from a given data. |
| 13 | |
| 14 | Parameters |
| 15 | ---------- |
| 16 | data : |
| 17 | The data in bytes from which the words need to be extracted |
| 18 | start : |
| 19 | Position to start the extraction |
| 20 | num_words: |
| 21 | The number of words to be extracted |
| 22 | |
| 23 | """ |
| 24 | words = [] |
| 25 | for i in range(num_words): |
| 26 | start_position = start + (i * 8) |
| 27 | words.append( |
| 28 | Uint.from_le_bytes(data[start_position : start_position + 8]) |
| 29 | ) |
| 30 | |
| 31 | return words |
Blake2
Implementation of the BLAKE2 cryptographic hashing algorithm.
Please refer the following document for details: https://datatracker.ietf.org/doc/html/rfc7693
| 34 | @dataclass |
|---|
class Blake2:
w
| 43 | w: Uint |
|---|
mask_bits
| 44 | mask_bits: Uint |
|---|
word_format
| 45 | word_format: str |
|---|
R1
| 47 | R1: Uint |
|---|
R2
| 48 | R2: Uint |
|---|
R3
| 49 | R3: Uint |
|---|
R4
| 50 | R4: Uint |
|---|
max_word
Largest value for a given Blake2 flavor.
| 52 | @property |
|---|
def max_word(self) -> Uint:
| 54 | """ |
|---|---|
| 55 | Largest value for a given Blake2 flavor. |
| 56 | """ |
| 57 | return Uint(2) ** self.w |
w_R1
(w - R1) value for a given Blake2 flavor. Used in the function G.
| 59 | @property |
|---|
def w_R1(self) -> Uint:
| 61 | """ |
|---|---|
| 62 | (w - R1) value for a given Blake2 flavor. |
| 63 | Used in the function G. |
| 64 | """ |
| 65 | return self.w - self.R1 |
w_R2
(w - R2) value for a given Blake2 flavor. Used in the function G.
| 67 | @property |
|---|
def w_R2(self) -> Uint:
| 69 | """ |
|---|---|
| 70 | (w - R2) value for a given Blake2 flavor. |
| 71 | Used in the function G. |
| 72 | """ |
| 73 | return self.w - self.R2 |
w_R3
(w - R3) value for a given Blake2 flavor. Used in the function G.
| 75 | @property |
|---|
def w_R3(self) -> Uint:
| 77 | """ |
|---|---|
| 78 | (w - R3) value for a given Blake2 flavor. |
| 79 | Used in the function G. |
| 80 | """ |
| 81 | return self.w - self.R3 |
w_R4
(w - R4) value for a given Blake2 flavor. Used in the function G.
| 83 | @property |
|---|
def w_R4(self) -> Uint:
| 85 | """ |
|---|---|
| 86 | (w - R4) value for a given Blake2 flavor. |
| 87 | Used in the function G. |
| 88 | """ |
| 89 | return self.w - self.R4 |
sigma
| 91 | sigma: Tuple[Tuple[int, ...], ...] = ( |
|---|---|
| 92 | (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), |
| 93 | (14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3), |
| 94 | (11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4), |
| 95 | (7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8), |
| 96 | (9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13), |
| 97 | (2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9), |
| 98 | (12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11), |
| 99 | (13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10), |
| 100 | (6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5), |
| 101 | (10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0), |
| 102 | ) |
IV
| 104 | IV: Tuple[Uint, ...] = ( |
|---|---|
| 105 | Uint(0x6A09E667F3BCC908), |
| 106 | Uint(0xBB67AE8584CAA73B), |
| 107 | Uint(0x3C6EF372FE94F82B), |
| 108 | Uint(0xA54FF53A5F1D36F1), |
| 109 | Uint(0x510E527FADE682D1), |
| 110 | Uint(0x9B05688C2B3E6C1F), |
| 111 | Uint(0x1F83D9ABFB41BD6B), |
| 112 | Uint(0x5BE0CD19137E2179), |
| 113 | ) |
MIX_TABLE
| 115 | MIX_TABLE: Final[Tuple[Tuple[Uint, Uint, Uint, Uint], ...]] = ( |
|---|---|
| 116 | (Uint(0), Uint(4), Uint(8), Uint(12)), |
| 117 | (Uint(1), Uint(5), Uint(9), Uint(13)), |
| 118 | (Uint(2), Uint(6), Uint(10), Uint(14)), |
| 119 | (Uint(3), Uint(7), Uint(11), Uint(15)), |
| 120 | (Uint(0), Uint(5), Uint(10), Uint(15)), |
| 121 | (Uint(1), Uint(6), Uint(11), Uint(12)), |
| 122 | (Uint(2), Uint(7), Uint(8), Uint(13)), |
| 123 | (Uint(3), Uint(4), Uint(9), Uint(14)), |
| 124 | ) |
sigma_len
Length of the sigma parameter.
| 126 | @property |
|---|
def sigma_len(self) -> int:
| 128 | """ |
|---|---|
| 129 | Length of the sigma parameter. |
| 130 | """ |
| 131 | return len(self.sigma) |
get_blake2_parameters
Extract the parameters required in the Blake2 compression function from the provided bytes data.
Parameters
data : The bytes data that has been passed in the message.
def get_blake2_parameters(self, data: bytes) -> Tuple:
| 134 | """ |
|---|---|
| 135 | Extract the parameters required in the Blake2 compression function |
| 136 | from the provided bytes data. |
| 137 | |
| 138 | Parameters |
| 139 | ---------- |
| 140 | data : |
| 141 | The bytes data that has been passed in the message. |
| 142 | |
| 143 | """ |
| 144 | rounds = Uint.from_be_bytes(data[:4]) |
| 145 | h = spit_le_to_uint(data, 4, 8) |
| 146 | m = spit_le_to_uint(data, 68, 16) |
| 147 | t_0, t_1 = spit_le_to_uint(data, 196, 2) |
| 148 | f = Uint.from_be_bytes(data[212:]) |
| 149 | |
| 150 | return (rounds, h, m, t_0, t_1, f) |
G
The mixing function used in Blake2.
See RFC 7693 for more details.
Parameters
v : The working vector to be mixed. a, b, c, d : Indexes within v of the words to be mixed. x, y : The two input words for the mixing.
def G(self, v: List, a: Uint, b: Uint, c: Uint, d: Uint, x: Uint, y: Uint) -> List:
| 155 | """ |
|---|---|
| 156 | The mixing function used in Blake2. |
| 157 | |
| 158 | See [RFC 7693] for more details. |
| 159 | |
| 160 | [RFC 7693]: https://datatracker.ietf.org/doc/html/rfc7693#section-3.1 |
| 161 | |
| 162 | Parameters |
| 163 | ---------- |
| 164 | v : |
| 165 | The working vector to be mixed. |
| 166 | a, b, c, d : |
| 167 | Indexes within v of the words to be mixed. |
| 168 | x, y : |
| 169 | The two input words for the mixing. |
| 170 | |
| 171 | """ |
| 172 | v[a] = (v[a] + v[b] + x) % self.max_word |
| 173 | v[d] = ((v[d] ^ v[a]) >> self.R1) ^ ( |
| 174 | (v[d] ^ v[a]) << self.w_R1 |
| 175 | ) % self.max_word |
| 176 | |
| 177 | v[c] = (v[c] + v[d]) % self.max_word |
| 178 | v[b] = ((v[b] ^ v[c]) >> self.R2) ^ ( |
| 179 | (v[b] ^ v[c]) << self.w_R2 |
| 180 | ) % self.max_word |
| 181 | |
| 182 | v[a] = (v[a] + v[b] + y) % self.max_word |
| 183 | v[d] = ((v[d] ^ v[a]) >> self.R3) ^ ( |
| 184 | (v[d] ^ v[a]) << self.w_R3 |
| 185 | ) % self.max_word |
| 186 | |
| 187 | v[c] = (v[c] + v[d]) % self.max_word |
| 188 | v[b] = ((v[b] ^ v[c]) >> self.R4) ^ ( |
| 189 | (v[b] ^ v[c]) << self.w_R4 |
| 190 | ) % self.max_word |
| 191 | |
| 192 | return v |
compress
'F Compression' from section 3.2 of RFC 7693.
Parameters
num_rounds : The number of rounds. A 32-bit unsigned big-endian word h : The state vector. 8 unsigned 64-bit little-endian words m : The message block vector. 16 unsigned 64-bit little-endian words t_0, t_1 : Offset counters. 2 unsigned 64-bit little-endian words f: The final block indicator flag. An 8-bit word
def compress(self, num_rounds: Uint, h: List[Uint], m: List[Uint], t_0: Uint, t_1: Uint, f: bool) -> bytes:
| 203 | """ |
|---|---|
| 204 | 'F Compression' from section 3.2 of RFC 7693. |
| 205 | |
| 206 | Parameters |
| 207 | ---------- |
| 208 | num_rounds : |
| 209 | The number of rounds. A 32-bit unsigned big-endian word |
| 210 | h : |
| 211 | The state vector. 8 unsigned 64-bit little-endian words |
| 212 | m : |
| 213 | The message block vector. 16 unsigned 64-bit little-endian words |
| 214 | t_0, t_1 : |
| 215 | Offset counters. 2 unsigned 64-bit little-endian words |
| 216 | f: |
| 217 | The final block indicator flag. An 8-bit word |
| 218 | |
| 219 | """ |
| 220 | # Initialize local work vector v[0..15] |
| 221 | v = [Uint(0)] * 16 |
| 222 | v[0:8] = h # First half from state |
| 223 | v[8:15] = self.IV # Second half from IV |
| 224 | |
| 225 | v[12] = t_0 ^ self.IV[4] # Low word of the offset |
| 226 | v[13] = t_1 ^ self.IV[5] # High word of the offset |
| 227 | |
| 228 | if f: |
| 229 | v[14] = v[14] ^ self.mask_bits # Invert all bits for last block |
| 230 | |
| 231 | # Mixing |
| 232 | for r in range(num_rounds): |
| 233 | # for more than sigma_len rounds, the schedule |
| 234 | # wraps around to the beginning |
| 235 | s = self.sigma[r % self.sigma_len] |
| 236 | |
| 237 | v = self.G(v, *self.MIX_TABLE[0], m[s[0]], m[s[1]]) |
| 238 | v = self.G(v, *self.MIX_TABLE[1], m[s[2]], m[s[3]]) |
| 239 | v = self.G(v, *self.MIX_TABLE[2], m[s[4]], m[s[5]]) |
| 240 | v = self.G(v, *self.MIX_TABLE[3], m[s[6]], m[s[7]]) |
| 241 | v = self.G(v, *self.MIX_TABLE[4], m[s[8]], m[s[9]]) |
| 242 | v = self.G(v, *self.MIX_TABLE[5], m[s[10]], m[s[11]]) |
| 243 | v = self.G(v, *self.MIX_TABLE[6], m[s[12]], m[s[13]]) |
| 244 | v = self.G(v, *self.MIX_TABLE[7], m[s[14]], m[s[15]]) |
| 245 | |
| 246 | result_message_words = (h[i] ^ v[i] ^ v[i + 8] for i in range(8)) |
| 247 | return struct.pack("<8%s" % self.word_format, *result_message_words) |
Blake2b
The Blake2b flavor (64-bits) of Blake2. This version is used in the pre-compiled contract.
| 251 | @dataclass |
|---|
class Blake2b:
w
| 258 | w: Uint = Uint(64) |
|---|
mask_bits
| 259 | mask_bits: Uint = Uint(0xFFFFFFFFFFFFFFFF) |
|---|
word_format
| 260 | word_format: str = "Q" |
|---|
R1
| 262 | R1: Uint = Uint(32) |
|---|
R2
| 263 | R2: Uint = Uint(24) |
|---|
R3
| 264 | R3: Uint = Uint(16) |
|---|
R4
| 265 | R4: Uint = Uint(63) |
|---|