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