ethereum.crypto.finite_field
Finite Fields ^^^^^^^^^^^^^
F
13 | F = TypeVar("F", bound="Field") |
---|
Field
A type protocol for defining fields.
class Field:
__slots__
21 | __slots__ = () |
---|
zero
from_int
__radd__
__add__
__iadd__
__sub__
__rsub__
__mul__
__rmul__
__imul__
__pow__
__ipow__
__neg__
__truediv__
T
68 | 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__
77 | __slots__ = () |
---|
PRIME
78 | 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
.
80 | @classmethod |
---|
def from_be_bytes(cls: Type[T], buffer: "Bytes") -> T:
82 | """ |
---|---|
83 | Converts a sequence of bytes into a element of the field. |
84 | Parameters |
85 | ---------- |
86 | buffer : |
87 | Bytes to decode. |
88 | Returns |
89 | ------- |
90 | self : `T` |
91 | Unsigned integer decoded from `buffer`. |
92 | """ |
93 | return cls(int.from_bytes(buffer, "big")) |
zero
from_int
__new__
__radd__
__add__
__iadd__
__sub__
__rsub__
__mul__
__rmul__
__imul__
__floordiv__
142 | __floordiv__ = None |
---|
__rfloordiv__
143 | __rfloordiv__ = None |
---|
__ifloordiv__
144 | __ifloordiv__ = None |
---|
__divmod__
145 | __divmod__ = None |
---|
__rdivmod__
146 | __rdivmod__ = None |
---|
__pow__
__rpow__
155 | __rpow__ = None |
---|
__ipow__
__and__
160 | __and__ = None |
---|
__or__
161 | __or__ = None |
---|
__xor__
162 | __xor__ = None |
---|
__rxor__
163 | __rxor__ = None |
---|
__ixor__
164 | __ixor__ = None |
---|
__rshift__
165 | __rshift__ = None |
---|
__lshift__
166 | __lshift__ = None |
---|
__irshift__
167 | __irshift__ = None |
---|
__ilshift__
168 | __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":
180 | """ |
---|---|
181 | Converts this arbitrarily sized unsigned integer into its big endian |
182 | representation with exactly 32 bytes. |
183 | Returns |
184 | ------- |
185 | big_endian : `Bytes32` |
186 | Big endian (most significant bits first) representation. |
187 | """ |
188 | return Bytes32(self.to_bytes(32, "big")) |
U
191 | 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__
207 | __slots__ = () |
---|
PRIME
209 | PRIME: int |
---|
MODULUS
210 | MODULUS: Tuple[int, ...] |
---|
FROBENIUS_COEFFICIENTS
211 | FROBENIUS_COEFFICIENTS: Tuple["GaloisField", ...] |
---|
zero
from_int
__new__
__add__
__radd__
__iadd__
__sub__
__rsub__
__mul__
def __mul__(self: U, right: U) -> U:
271 | modulus = self.MODULUS |
---|---|
272 | degree = len(modulus) |
273 | prime = self.PRIME |
274 | mul = [0] * (degree * 2) |
275 | |
276 | for i in range(degree): |
277 | for j in range(degree): |
278 | mul[i + j] += self[i] * right[j] |
279 | |
280 | for i in range(degree * 2 - 1, degree - 1, -1): |
281 | for j in range(i - degree, i): |
282 | mul[j] -= (mul[i] * modulus[degree - (i - j)]) % prime |
283 | |
284 | return self.__new__( |
285 | type(self), |
286 | mul[:degree], |
287 | ) |
__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:
309 | """ |
---|---|
310 | This is a support function for `multiplicative_inverse()`. |
311 | """ |
312 | for i in range(len(self.MODULUS) - 1, -1, -1): |
313 | if self[i] != 0: |
314 | return i |
315 | raise ValueError("deg() does not support zero") |
multiplicative_inverse
Calculate the multiplicative inverse. Uses the Euclidean algorithm.
def multiplicative_inverse(self: U) -> U:
318 | """ |
---|---|
319 | Calculate the multiplicative inverse. Uses the Euclidean algorithm. |
320 | """ |
321 | x2: List[int] |
322 | p = self.PRIME |
323 | x1, f1 = list(self.MODULUS), [0] * len(self) |
324 | x2, f2, d2 = list(self), [1] + [0] * (len(self) - 1), self.deg() |
325 | q_0 = pow(x2[d2], -1, p) |
326 | for i in range(d2): |
327 | x1[i + len(x1) - d2] = (x1[i + len(x1) - d2] - q_0 * x2[i]) % p |
328 | f1[i + len(x1) - d2] = (f1[i + len(x1) - d2] - q_0 * f2[i]) % p |
329 | for i in range(len(self.MODULUS) - 1, -1, -1): |
330 | if x1[i] != 0: |
331 | d1 = i |
332 | break |
333 | while True: |
334 | if d1 == 0: |
335 | ans = f1 |
336 | q = pow(x1[0], -1, self.PRIME) |
337 | for i in range(len(ans)): |
338 | ans[i] *= q |
339 | break |
340 | elif d2 == 0: |
341 | ans = f2 |
342 | q = pow(x2[0], -1, self.PRIME) |
343 | for i in range(len(ans)): |
344 | ans *= q |
345 | break |
346 | if d1 < d2: |
347 | q = x2[d2] * pow(x1[d1], -1, self.PRIME) |
348 | for i in range(len(self.MODULUS) - (d2 - d1)): |
349 | x2[i + (d2 - d1)] = (x2[i + (d2 - d1)] - q * x1[i]) % p |
350 | f2[i + (d2 - d1)] = (f2[i + (d2 - d1)] - q * f1[i]) % p |
351 | while x2[d2] == 0: |
352 | d2 -= 1 |
353 | else: |
354 | q = x1[d1] * pow(x2[d2], -1, self.PRIME) |
355 | for i in range(len(self.MODULUS) - (d1 - d2)): |
356 | x1[i + (d1 - d2)] = (x1[i + (d1 - d2)] - q * x2[i]) % p |
357 | f1[i + (d1 - d2)] = (f1[i + (d1 - d2)] - q * f2[i]) % p |
358 | while x1[d1] == 0: |
359 | d1 -= 1 |
360 | return self.__new__(type(self), ans) |
__pow__
def __pow__(self: U, exponent: int) -> U:
363 | degree = len(self.MODULUS) |
---|---|
364 | if exponent < 0: |
365 | self = self.multiplicative_inverse() |
366 | exponent = -exponent |
367 | |
368 | res = self.__new__(type(self), [1] + [0] * (degree - 1)) |
369 | s = self |
370 | while exponent != 0: |
371 | if exponent % 2 == 1: |
372 | res *= s |
373 | s *= s |
374 | exponent //= 2 |
375 | return res |
__ipow__
calculate_frobenius_coefficients
Calculate the coefficients needed by frobenius()
.
380 | @classmethod |
---|
def calculate_frobenius_coefficients(cls: Type[U]) -> Tuple[U, ...]:
382 | """ |
---|---|
383 | Calculate the coefficients needed by `frobenius()`. |
384 | """ |
385 | coefficients = [] |
386 | for i in range(len(cls.MODULUS)): |
387 | x = [0] * len(cls.MODULUS) |
388 | x[i] = 1 |
389 | coefficients.append(cls.__new__(cls, x) ** cls.PRIME) |
390 | 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:
393 | """ |
---|---|
394 | Returns `self ** p`. This function is known as the Frobenius |
395 | endomorphism and has many special mathematical properties. In |
396 | particular it is extremely cheap to compute compared to other |
397 | exponentiations. |
398 | """ |
399 | ans = self.from_int(0) |
400 | a: int |
401 | for i, a in enumerate(self): |
402 | ans += cast(U, self.FROBENIUS_COEFFICIENTS[i]).scalar_mul(a) |
403 | return ans |