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)