mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-31 10:41:08 +00:00
14e56970cb Merge bitcoin-core/secp256k1#1794: ecmult: Use size_t for array indices c7a52400d6 Merge bitcoin-core/secp256k1#1809: release cleanup: bump version after 0.7.1 ae7eb729c0 release cleanup: bump version after 0.7.1 1a53f4961f Merge bitcoin-core/secp256k1#1808: Prepare for 0.7.1 20a209f11c release: prepare for 0.7.1 c4b6a81a60 changelog: update in preparation for the v0.7.1 release ebb35882da Merge bitcoin-core/secp256k1#1796: bench: fail early if user inputs invalid value for SECP256K1_BENCH_ITERS c09215f7af bench: fail early if user inputs invalid value for SECP256K1_BENCH_ITERS 471e3a130d Merge bitcoin-core/secp256k1#1800: sage: verify Eisenstein integer connection for GLV constants 29ac4d8491 sage: verify Eisenstein integer connection for GLV constants 4721e077b4 Merge bitcoin-core/secp256k1#1793: doc/bench: added help text for SECP256K1_BENCH_ITERS env var for bench_ecmult bd5ced1fe1 doc/bench: added help text for SECP256K1_BENCH_ITERS env var for bench_ecmult 47eb70959a ecmult: Use size_t for array indices in _odd_multiplies_table bb1d199de5 ecmult: Use size_t for array indices into tables 2d9137ce9d Merge bitcoin-core/secp256k1#1764: group: Avoid using infinity field directly in other modules f9a944ff2d Merge bitcoin-core/secp256k1#1790: doc: include arg -DSECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS=ON for cmake 0406cfc4d1 doc: include arg -DUSE_EXTERNAL_DEFAULT_CALLBACKS=1 for cmake 8d445730ec Merge bitcoin-core/secp256k1#1783: Add VERIFY_CHECKs and documentation that flags must be 0 or 1 aa2a39c1a7 Merge bitcoin-core/secp256k1#1778: doc/bench: Added cmake build options to bench error messages 540fec8ae9 Merge bitcoin-core/secp256k1#1788: test: split monolithic ellswift test into independent cases d822b29021 test: split monolithic ellswift test into independent cases ae00c552df Add VERIFY_CHECKs that flags are 0 or 1 5c75183344 Merge bitcoin-core/secp256k1#1784: refactor: remove ret from secp256k1_ec_pubkey_serialize be5e4f02fd Merge bitcoin-core/secp256k1#1779: Add ARG_CHECKs to ensure "array of pointers" elements are non-NULL 3daab83a60 refactor: remove ret from secp256k1_ec_pubkey_serialize 8bcda186d2 test: Add non-NULL checks for "pointer of array" API functions 5a08c1bcdc Add ARG_CHECKs to ensure "array of pointers" elements are non-NULL 3b5b03f301 doc/bench: Added cmake build options to bench error messages e7f7083b53 Merge bitcoin-core/secp256k1#1774: refactor: split up internal pubkey serialization function into compressed/uncompressed variants b6c2a3cd77 Merge bitcoin-core/secp256k1#1761: ecmult_multi: reduce strauss memory usage by 30% f5e815f430 remove secp256k1_eckey_pubkey_serialize function 0d3659c547 use new `_eckey_pubkey_serialize{33,65}` functions in modules (ellswift,musig) adb76f82ea use new `_eckey_pubkey_serialize{33,65}` functions in public API fc7458ca3e introduce `secp256k1_eckey_pubkey_serialize{33,65}` functions c8206b1ce6 Merge bitcoin-core/secp256k1#1771: ci: Use Python virtual environment in "x86_64-macos-native" job f252da7e6e ci: Use Python virtual environment in "x86_64-macos-native" job 115b135fe8 Merge bitcoin-core/secp256k1#1763: bench: Use `ALIGNMENT` macro instead of hardcoded value 2f73e5281d group: Avoid using infinity field directly in other modules 153eea20c2 bench: Use `ALIGNMENT` macro instead of hardcoded value 26166c4f5f ecmult_multi: reduce strauss memory usage by 30% 7a2fff85e8 Merge bitcoin-core/secp256k1#1758: ci: Drop workaround for Valgrind older than 3.20.0 43e7b115f7 Merge bitcoin-core/secp256k1#1759: ci: Switch to macOS 15 Sequoia Intel-based image 8bc50b72ff ci: Switch to macOS 15 Sequoia Intel-based image c09519f0e3 ci: Drop workaround for Valgrind older than 3.20.0 git-subtree-dir: src/secp256k1 git-subtree-split: 14e56970cba37ffe4ee992c1e08707a16e22e345
124 lines
4.0 KiB
Python
124 lines
4.0 KiB
Python
""" Generates the constants used in secp256k1_scalar_split_lambda.
|
|
|
|
See the comments for secp256k1_scalar_split_lambda in src/scalar_impl.h for detailed explanations.
|
|
"""
|
|
|
|
load("secp256k1_params.sage")
|
|
|
|
def inf_norm(v):
|
|
"""Returns the infinity norm of a vector."""
|
|
return max(map(abs, v))
|
|
|
|
def gauss_reduction(i1, i2):
|
|
v1, v2 = i1.copy(), i2.copy()
|
|
while True:
|
|
if inf_norm(v2) < inf_norm(v1):
|
|
v1, v2 = v2, v1
|
|
# This is essentially
|
|
# m = round((v1[0]*v2[0] + v1[1]*v2[1]) / (inf_norm(v1)**2))
|
|
# (rounding to the nearest integer) without relying on floating point arithmetic.
|
|
m = ((v1[0]*v2[0] + v1[1]*v2[1]) + (inf_norm(v1)**2) // 2) // (inf_norm(v1)**2)
|
|
if m == 0:
|
|
return v1, v2
|
|
v2[0] -= m*v1[0]
|
|
v2[1] -= m*v1[1]
|
|
|
|
def find_split_constants_gauss():
|
|
"""Find constants for secp256k1_scalar_split_lamdba using gauss reduction."""
|
|
(v11, v12), (v21, v22) = gauss_reduction([0, N], [1, int(LAMBDA)])
|
|
|
|
# We use related vectors in secp256k1_scalar_split_lambda.
|
|
A1, B1 = -v21, -v11
|
|
A2, B2 = v22, -v21
|
|
|
|
return A1, B1, A2, B2
|
|
|
|
def find_split_constants_explicit_tof():
|
|
"""Find constants for secp256k1_scalar_split_lamdba using the trace of Frobenius.
|
|
|
|
See Benjamin Smith: "Easy scalar decompositions for efficient scalar multiplication on
|
|
elliptic curves and genus 2 Jacobians" (https://eprint.iacr.org/2013/672), Example 2
|
|
"""
|
|
assert P % 3 == 1 # The paper says P % 3 == 2 but that appears to be a mistake, see [10].
|
|
assert C.j_invariant() == 0
|
|
|
|
t = C.trace_of_frobenius()
|
|
|
|
c = Integer(sqrt((4*P - t**2)/3))
|
|
A1 = Integer((t - c)/2 - 1)
|
|
B1 = c
|
|
|
|
A2 = Integer((t + c)/2 - 1)
|
|
B2 = Integer(1 - (t - c)/2)
|
|
|
|
# We use a negated b values in secp256k1_scalar_split_lambda.
|
|
B1, B2 = -B1, -B2
|
|
|
|
return A1, B1, A2, B2
|
|
|
|
A1, B1, A2, B2 = find_split_constants_explicit_tof()
|
|
|
|
# For extra fun, use an independent method to recompute the constants.
|
|
assert (A1, B1, A2, B2) == find_split_constants_gauss()
|
|
|
|
# PHI : Z[l] -> Z_n where phi(a + b*l) == a + b*lambda mod n.
|
|
def PHI(a,b):
|
|
return Z(a + LAMBDA*b)
|
|
|
|
# Check that (A1, B1) and (A2, B2) are in the kernel of PHI.
|
|
assert PHI(A1, B1) == Z(0)
|
|
assert PHI(A2, B2) == Z(0)
|
|
|
|
# Check that the parallelogram generated by (A1, A2) and (B1, B2)
|
|
# is a fundamental domain by containing exactly N points.
|
|
# Since the LHS is the determinant and N != 0, this also checks that
|
|
# (A1, A2) and (B1, B2) are linearly independent. By the previous
|
|
# assertions, (A1, A2) and (B1, B2) are a basis of the kernel.
|
|
assert A1*B2 - B1*A2 == N
|
|
|
|
# Check that their components are short enough.
|
|
assert (A1 + A2)/2 < sqrt(N)
|
|
assert B1 < sqrt(N)
|
|
assert B2 < sqrt(N)
|
|
|
|
# Verify connection to Eisenstein integers Z[w] where w = (-1 + sqrt(-3))/2.
|
|
# The group order N factors as N = pi * conj(pi) in Z[w], where pi = A - B*w
|
|
# is an Eisenstein prime with norm A^2 + A*B + B^2. The GLV endomorphism
|
|
# eigenvalue LAMBDA equals B/A mod N, which is the image of w^2 under the
|
|
# isomorphism Z[w]/(pi) -> Z/NZ (since w -> A/B and (A/B)^2 = B/A in Z/NZ).
|
|
A_EIS, B_EIS = -B1, A1
|
|
assert A_EIS**2 + A_EIS*B_EIS + B_EIS**2 == N
|
|
assert Z(B_EIS / A_EIS) == LAMBDA
|
|
|
|
G1 = round((2**384)*B2/N)
|
|
G2 = round((2**384)*(-B1)/N)
|
|
|
|
def rnddiv2(v):
|
|
if v & 1:
|
|
v += 1
|
|
return v >> 1
|
|
|
|
def scalar_lambda_split(k):
|
|
"""Equivalent to secp256k1_scalar_lambda_split()."""
|
|
c1 = rnddiv2((k * G1) >> 383)
|
|
c2 = rnddiv2((k * G2) >> 383)
|
|
c1 = (c1 * -B1) % N
|
|
c2 = (c2 * -B2) % N
|
|
r2 = (c1 + c2) % N
|
|
r1 = (k + r2 * -LAMBDA) % N
|
|
return (r1, r2)
|
|
|
|
# The result of scalar_lambda_split can depend on the representation of k (mod n).
|
|
SPECIAL = (2**383) // G2 + 1
|
|
assert scalar_lambda_split(SPECIAL) != scalar_lambda_split(SPECIAL + N)
|
|
|
|
print(' A1 =', hex(A1))
|
|
print(' -B1 =', hex(-B1))
|
|
print(' A2 =', hex(A2))
|
|
print(' -B2 =', hex(-B2))
|
|
print(' =', hex(Z(-B2)))
|
|
print(' -LAMBDA =', hex(-LAMBDA))
|
|
|
|
print(' G1 =', hex(G1))
|
|
print(' G2 =', hex(G2))
|