| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- from typing import (
- Tuple,
- )
- from eth_keys.constants import (
- IDENTITY_POINTS,
- SECPK1_A as A,
- SECPK1_N as N,
- SECPK1_P as P,
- )
- def inv(a: int, n: int) -> int:
- if a == 0:
- return 0
- lm, hm = 1, 0
- low, high = a % n, n
- while low > 1:
- r = high // low
- nm, new = hm - lm * r, high - low * r
- lm, low, hm, high = nm, new, lm, low
- return lm % n
- def to_jacobian(p: Tuple[int, int]) -> Tuple[int, int, int]:
- o = (p[0], p[1], 1)
- return o
- def jacobian_double(p: Tuple[int, int, int]) -> Tuple[int, int, int]:
- if not p[1]:
- return (0, 0, 0)
- ysq = (p[1] ** 2) % P
- S = (4 * p[0] * ysq) % P
- M = (3 * p[0] ** 2 + A * p[2] ** 4) % P
- nx = (M**2 - 2 * S) % P
- ny = (M * (S - nx) - 8 * ysq**2) % P
- nz = (2 * p[1] * p[2]) % P
- return (nx, ny, nz)
- def jacobian_add(
- p: Tuple[int, int, int], q: Tuple[int, int, int]
- ) -> Tuple[int, int, int]:
- if not p[1]:
- return q
- if not q[1]:
- return p
- U1 = (p[0] * q[2] ** 2) % P
- U2 = (q[0] * p[2] ** 2) % P
- S1 = (p[1] * q[2] ** 3) % P
- S2 = (q[1] * p[2] ** 3) % P
- if U1 == U2:
- if S1 != S2:
- return (0, 0, 1)
- return jacobian_double(p)
- H = U2 - U1
- R = S2 - S1
- H2 = (H * H) % P
- H3 = (H * H2) % P
- U1H2 = (U1 * H2) % P
- nx = (R**2 - H3 - 2 * U1H2) % P
- ny = (R * (U1H2 - nx) - S1 * H3) % P
- nz = (H * p[2] * q[2]) % P
- return (nx, ny, nz)
- def from_jacobian(p: Tuple[int, int, int]) -> Tuple[int, int]:
- z = inv(p[2], P)
- return ((p[0] * z**2) % P, (p[1] * z**3) % P)
- def jacobian_multiply(a: Tuple[int, int, int], n: int) -> Tuple[int, int, int]:
- if a[1] == 0 or n == 0:
- return (0, 0, 1)
- if n == 1:
- return a
- if n < 0 or n >= N:
- return jacobian_multiply(a, n % N)
- if (n % 2) == 0:
- return jacobian_double(jacobian_multiply(a, n // 2))
- elif (n % 2) == 1:
- return jacobian_add(jacobian_double(jacobian_multiply(a, n // 2)), a)
- else:
- raise Exception("Invariant: Unreachable code path")
- def fast_multiply(a: Tuple[int, int], n: int) -> Tuple[int, int]:
- return from_jacobian(jacobian_multiply(to_jacobian(a), n))
- def fast_add(a: Tuple[int, int], b: Tuple[int, int]) -> Tuple[int, int]:
- return from_jacobian(jacobian_add(to_jacobian(a), to_jacobian(b)))
- def is_identity(p: Tuple[int, int, int]) -> bool:
- return p in IDENTITY_POINTS
|