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: int |
---|
mask_bits
45 | mask_bits: int |
---|
word_format
46 | word_format: str |
---|
R1
48 | R1: int |
---|
R2
49 | R2: int |
---|
R3
50 | R3: int |
---|
R4
51 | R4: int |
---|
max_word
Largest value for a given Blake2 flavor.
53 | @property |
---|
def max_word(self) -> int:
55 | """ |
---|---|
56 | Largest value for a given Blake2 flavor. |
57 | """ |
58 | return 2**self.w |
w_R1
(w - R1) value for a given Blake2 flavor. Used in the function G
60 | @property |
---|
def w_R1(self) -> int:
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) -> int:
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) -> int:
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) -> int:
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 = ( |
---|---|
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 = ( |
---|---|
106 | 0x6A09E667F3BCC908, |
107 | 0xBB67AE8584CAA73B, |
108 | 0x3C6EF372FE94F82B, |
109 | 0xA54FF53A5F1D36F1, |
110 | 0x510E527FADE682D1, |
111 | 0x9B05688C2B3E6C1F, |
112 | 0x1F83D9ABFB41BD6B, |
113 | 0x5BE0CD19137E2179, |
114 | ) |
sigma_len
Length of the sigma parameter.
116 | @property |
---|
def sigma_len(self) -> int:
118 | """ |
---|---|
119 | Length of the sigma parameter. |
120 | """ |
121 | 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:
124 | """ |
---|---|
125 | Extract the parameters required in the Blake2 compression function |
126 | from the provided bytes data. |
127 |
|
128 | Parameters |
129 | ---------- |
130 | data : |
131 | The bytes data that has been passed in the message. |
132 | """ |
133 | rounds = Uint.from_be_bytes(data[:4]) |
134 | h = spit_le_to_uint(data, 4, 8) |
135 | m = spit_le_to_uint(data, 68, 16) |
136 | t_0, t_1 = spit_le_to_uint(data, 196, 2) |
137 | f = Uint.from_be_bytes(data[212:]) |
138 | |
139 | 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: int, b: int, c: int, d: int, x: int, y: int) -> List:
144 | """ |
---|---|
145 | The mixing function used in Blake2 |
146 | https://datatracker.ietf.org/doc/html/rfc7693#section-3.1 |
147 |
|
148 | Parameters |
149 | ---------- |
150 | v : |
151 | The working vector to be mixed. |
152 | a, b, c, d : |
153 | Indexes within v of the words to be mixed. |
154 | x, y : |
155 | The two input words for the mixing. |
156 | """ |
157 | v[a] = (v[a] + v[b] + x) % self.max_word |
158 | v[d] = ((v[d] ^ v[a]) >> self.R1) ^ ( |
159 | (v[d] ^ v[a]) << self.w_R1 |
160 | ) % self.max_word |
161 | |
162 | v[c] = (v[c] + v[d]) % self.max_word |
163 | v[b] = ((v[b] ^ v[c]) >> self.R2) ^ ( |
164 | (v[b] ^ v[c]) << self.w_R2 |
165 | ) % self.max_word |
166 | |
167 | v[a] = (v[a] + v[b] + y) % self.max_word |
168 | v[d] = ((v[d] ^ v[a]) >> self.R3) ^ ( |
169 | (v[d] ^ v[a]) << self.w_R3 |
170 | ) % self.max_word |
171 | |
172 | v[c] = (v[c] + v[d]) % self.max_word |
173 | v[b] = ((v[b] ^ v[c]) >> self.R4) ^ ( |
174 | (v[b] ^ v[c]) << self.w_R4 |
175 | ) % self.max_word |
176 | |
177 | 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:
188 | """ |
---|---|
189 | 'F Compression' from section 3.2 of RFC 7693: |
190 | https://tools.ietf.org/html/rfc7693#section-3.2 |
191 |
|
192 | Parameters |
193 | ---------- |
194 | num_rounds : |
195 | The number of rounds. A 32-bit unsigned big-endian word |
196 | h : |
197 | The state vector. 8 unsigned 64-bit little-endian words |
198 | m : |
199 | The message block vector. 16 unsigned 64-bit little-endian words |
200 | t_0, t_1 : |
201 | Offset counters. 2 unsigned 64-bit little-endian words |
202 | f: |
203 | The final block indicator flag. An 8-bit word |
204 | """ |
205 | # Initialize local work vector v[0..15] |
206 | v = [0] * 16 |
207 | v[0:8] = h # First half from state |
208 | v[8:15] = self.IV # Second half from IV |
209 | |
210 | v[12] = t_0 ^ self.IV[4] # Low word of the offset |
211 | v[13] = t_1 ^ self.IV[5] # High word of the offset |
212 | |
213 | if f: |
214 | v[14] = v[14] ^ self.mask_bits # Invert all bits for last block |
215 | |
216 | # Mixing |
217 | for r in range(num_rounds): |
218 | # for more than sigma_len rounds, the schedule |
219 | # wraps around to the beginning |
220 | s = self.sigma[r % self.sigma_len] |
221 |
|
222 | v = self.G(v, 0, 4, 8, 12, m[s[0]], m[s[1]]) |
223 | v = self.G(v, 1, 5, 9, 13, m[s[2]], m[s[3]]) |
224 | v = self.G(v, 2, 6, 10, 14, m[s[4]], m[s[5]]) |
225 | v = self.G(v, 3, 7, 11, 15, m[s[6]], m[s[7]]) |
226 | v = self.G(v, 0, 5, 10, 15, m[s[8]], m[s[9]]) |
227 | v = self.G(v, 1, 6, 11, 12, m[s[10]], m[s[11]]) |
228 | v = self.G(v, 2, 7, 8, 13, m[s[12]], m[s[13]]) |
229 | v = self.G(v, 3, 4, 9, 14, m[s[14]], m[s[15]]) |
230 | |
231 | result_message_words = (h[i] ^ v[i] ^ v[i + 8] for i in range(8)) |
232 | 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.
236 | @dataclass |
---|
class Blake2b:
w
243 | w: int = 64 |
---|
mask_bits
244 | mask_bits: int = 0xFFFFFFFFFFFFFFFF |
---|
word_format
245 | word_format: str = "Q" |
---|
R1
247 | R1: int = 32 |
---|
R2
248 | R2: int = 24 |
---|
R3
249 | R3: int = 16 |
---|
R4
250 | R4: int = 63 |
---|