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