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) |
---|