ethereum.crypto.finite_field
Finite Fields ^^^^^^^^^^^^^
F
14 | F = TypeVar("F", bound="Field") |
---|
Field
A type protocol for defining fields.
class Field:
__slots__
22 | __slots__ = () |
---|
zero
from_int
__radd__
__add__
__iadd__
__sub__
__rsub__
__mul__
__rmul__
__imul__
__pow__
__ipow__
__neg__
__truediv__
T
69 | T = TypeVar("T", bound="PrimeField") |
---|
PrimeField
Superclass for integers modulo a prime. Not intended to be used directly, but rather to be subclassed.
class PrimeField:
__slots__
78 | __slots__ = () |
---|
PRIME
79 | PRIME: int |
---|
from_be_bytes
Converts a sequence of bytes into a element of the field. Parameters
buffer : Bytes to decode. Returns
self : T
Unsigned integer decoded from buffer
.
81 | @classmethod |
---|
def from_be_bytes(cls: Type[T], buffer: "Bytes") -> T:
83 | """ |
---|---|
84 | Converts a sequence of bytes into a element of the field. |
85 | Parameters |
86 | ---------- |
87 | buffer : |
88 | Bytes to decode. |
89 | Returns |
90 | ------- |
91 | self : `T` |
92 | Unsigned integer decoded from `buffer`. |
93 | """ |
94 | return cls(int.from_bytes(buffer, "big")) |
zero
from_int
__new__
__radd__
__add__
__iadd__
__sub__
__rsub__
__mul__
__rmul__
__imul__
__floordiv__
143 | __floordiv__ = None |
---|
__rfloordiv__
144 | __rfloordiv__ = None |
---|
__ifloordiv__
145 | __ifloordiv__ = None |
---|
__divmod__
146 | __divmod__ = None |
---|
__rdivmod__
147 | __rdivmod__ = None |
---|
__pow__
__rpow__
156 | __rpow__ = None |
---|
__ipow__
__and__
161 | __and__ = None |
---|
__or__
162 | __or__ = None |
---|
__xor__
163 | __xor__ = None |
---|
__rxor__
164 | __rxor__ = None |
---|
__ixor__
165 | __ixor__ = None |
---|
__rshift__
166 | __rshift__ = None |
---|
__lshift__
167 | __lshift__ = None |
---|
__irshift__
168 | __irshift__ = None |
---|
__ilshift__
169 | __ilshift__ = None |
---|
__neg__
__truediv__
multiplicative_inverse
to_be_bytes32
Converts this arbitrarily sized unsigned integer into its big endian representation with exactly 32 bytes. Returns
big_endian : Bytes32
Big endian (most significant bits first) representation.
def to_be_bytes32(self) -> "Bytes32":
181 | """ |
---|---|
182 | Converts this arbitrarily sized unsigned integer into its big endian |
183 | representation with exactly 32 bytes. |
184 | Returns |
185 | ------- |
186 | big_endian : `Bytes32` |
187 | Big endian (most significant bits first) representation. |
188 | """ |
189 | return Bytes32(self.to_bytes(32, "big")) |
U
192 | U = TypeVar("U", bound="GaloisField") |
---|
GaloisField
Superclass for defining finite fields. Not intended to be used directly, but rather to be subclassed.
Fields are represented as F_p[x]/(x^n + ...)
where the MODULUS
is a
tuple of the non-leading coefficients of the defining polynomial. For
example x^3 + 2x^2 + 3x + 4
is (2, 3, 4)
.
In practice the polynomial is likely to be sparse and you should overload
the __mul__()
function to take advantage of this fact.
class GaloisField:
__slots__
208 | __slots__ = () |
---|
PRIME
210 | PRIME: int |
---|
MODULUS
211 | MODULUS: Tuple[int, ...] |
---|
FROBENIUS_COEFFICIENTS
212 | FROBENIUS_COEFFICIENTS: Tuple["GaloisField", ...] |
---|
zero
from_int
__new__
__add__
__radd__
__iadd__
__sub__
__rsub__
__mul__
def __mul__(self: U, right: U) -> U:
272 | modulus = self.MODULUS |
---|---|
273 | degree = len(modulus) |
274 | prime = self.PRIME |
275 | mul = [0] * (degree * 2) |
276 | |
277 | for i in range(degree): |
278 | for j in range(degree): |
279 | mul[i + j] += self[i] * right[j] |
280 | |
281 | for i in range(degree * 2 - 1, degree - 1, -1): |
282 | for j in range(i - degree, i): |
283 | mul[j] -= (mul[i] * modulus[degree - (i - j)]) % prime |
284 | |
285 | return self.__new__( |
286 | type(self), |
287 | mul[:degree], |
288 | ) |
__rmul__
__imul__
__truediv__
__neg__
scalar_mul
Multiply a field element by a integer. This is faster than using
from_int()
and field multiplication.
deg
This is a support function for multiplicative_inverse()
.
def deg(self: U) -> int:
310 | """ |
---|---|
311 | This is a support function for `multiplicative_inverse()`. |
312 | """ |
313 | for i in range(len(self.MODULUS) - 1, -1, -1): |
314 | if self[i] != 0: |
315 | return i |
316 | raise ValueError("deg() does not support zero") |
multiplicative_inverse
Calculate the multiplicative inverse. Uses the Euclidean algorithm.
def multiplicative_inverse(self: U) -> U:
319 | """ |
---|---|
320 | Calculate the multiplicative inverse. Uses the Euclidean algorithm. |
321 | """ |
322 | x2: List[int] |
323 | p = self.PRIME |
324 | x1, f1 = list(self.MODULUS), [0] * len(self) |
325 | x2, f2, d2 = list(self), [1] + [0] * (len(self) - 1), self.deg() |
326 | q_0 = pow(x2[d2], -1, p) |
327 | for i in range(d2): |
328 | x1[i + len(x1) - d2] = (x1[i + len(x1) - d2] - q_0 * x2[i]) % p |
329 | f1[i + len(x1) - d2] = (f1[i + len(x1) - d2] - q_0 * f2[i]) % p |
330 | for i in range(len(self.MODULUS) - 1, -1, -1): |
331 | if x1[i] != 0: |
332 | d1 = i |
333 | break |
334 | while True: |
335 | if d1 == 0: |
336 | ans = f1 |
337 | q = pow(x1[0], -1, self.PRIME) |
338 | for i in range(len(ans)): |
339 | ans[i] *= q |
340 | break |
341 | elif d2 == 0: |
342 | ans = f2 |
343 | q = pow(x2[0], -1, self.PRIME) |
344 | for i in range(len(ans)): |
345 | ans *= q |
346 | break |
347 | if d1 < d2: |
348 | q = x2[d2] * pow(x1[d1], -1, self.PRIME) |
349 | for i in range(len(self.MODULUS) - (d2 - d1)): |
350 | x2[i + (d2 - d1)] = (x2[i + (d2 - d1)] - q * x1[i]) % p |
351 | f2[i + (d2 - d1)] = (f2[i + (d2 - d1)] - q * f1[i]) % p |
352 | while x2[d2] == 0: |
353 | d2 -= 1 |
354 | else: |
355 | q = x1[d1] * pow(x2[d2], -1, self.PRIME) |
356 | for i in range(len(self.MODULUS) - (d1 - d2)): |
357 | x1[i + (d1 - d2)] = (x1[i + (d1 - d2)] - q * x2[i]) % p |
358 | f1[i + (d1 - d2)] = (f1[i + (d1 - d2)] - q * f2[i]) % p |
359 | while x1[d1] == 0: |
360 | d1 -= 1 |
361 | return self.__new__(type(self), ans) |
__pow__
def __pow__(self: U, exponent: int) -> U:
364 | degree = len(self.MODULUS) |
---|---|
365 | if exponent < 0: |
366 | self = self.multiplicative_inverse() |
367 | exponent = -exponent |
368 | |
369 | res = self.__new__(type(self), [1] + [0] * (degree - 1)) |
370 | s = self |
371 | while exponent != 0: |
372 | if exponent % 2 == 1: |
373 | res *= s |
374 | s *= s |
375 | exponent //= 2 |
376 | return res |
__ipow__
calculate_frobenius_coefficients
Calculate the coefficients needed by frobenius()
.
381 | @classmethod |
---|
def calculate_frobenius_coefficients(cls: Type[U]) -> Tuple[U, ...]:
383 | """ |
---|---|
384 | Calculate the coefficients needed by `frobenius()`. |
385 | """ |
386 | coefficients = [] |
387 | for i in range(len(cls.MODULUS)): |
388 | x = [0] * len(cls.MODULUS) |
389 | x[i] = 1 |
390 | coefficients.append(cls.__new__(cls, x) ** cls.PRIME) |
391 | return tuple(coefficients) |
frobenius
Returns self ** p
. This function is known as the Frobenius
endomorphism and has many special mathematical properties. In
particular it is extremely cheap to compute compared to other
exponentiations.
def frobenius(self: U) -> U:
394 | """ |
---|---|
395 | Returns `self ** p`. This function is known as the Frobenius |
396 | endomorphism and has many special mathematical properties. In |
397 | particular it is extremely cheap to compute compared to other |
398 | exponentiations. |
399 | """ |
400 | ans = self.from_int(0) |
401 | a: int |
402 | for i, a in enumerate(self): |
403 | ans += cast(U, self.FROBENIUS_COEFFICIENTS[i]).scalar_mul(a) |
404 | return ans |