mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-03 09:56:38 -05:00
afb7a6fe06
8746600eec Merge bitcoin-core/secp256k1#1093: hash: Make code agnostic of endianness 37d36927df tests: Add tests for _read_be32 and _write_be32 912b7ccc44 Merge bitcoin-core/secp256k1#1094: doc: Clarify configure flags for optional modules 55512d30b7 doc: clean up module help text in configure.ac d9d94a9969 doc: mention optional modules in README 616b43dd3b util: Remove endianness detection 8d89b9e6e5 hash: Make code agnostic of endianness d0ad5814a5 Merge bitcoin-core/secp256k1#995: build: stop treating schnorrsig, extrakeys modules as experimental 1ac7e31c5b Merge bitcoin-core/secp256k1#1089: Schnorrsig API improvements 587239dbe3 Merge bitcoin-core/secp256k1#731: Change SHA256 byte counter from size_t to uint64_t f8d9174357 Add SHA256 bit counter tests 7f09d0f311 README: mention that ARM assembly is experimental b8f8b99f0f docs: Fix return value for functions that don't have invalid inputs f813bb0df3 schnorrsig: Adapt example to new API 99e6568fc6 schnorrsig: Rename schnorrsig_sign to schnorsig_sign32 and deprecate fc94a2da44 Use SECP256K1_DEPRECATED for existing deprecated API functions 3db0560606 Add SECP256K1_DEPRECATED attribute for marking API parts as deprecated 80cf4eea5f build: stop treating schnorrsig, extrakeys modules as experimental e0508ee9db Merge bitcoin-core/secp256k1#1090: configure: Remove redundant pkg-config code 21b2ebaf74 configure: Remove redundant pkg-config code 0e5cbd01b3 Merge bitcoin-core/secp256k1#1088: configure: Use modern way to set AR 0d253d52e8 configure: Use modern way to set AR 9b514ce1d2 Add test vector for very long SHA256 messages 8e3dde1137 Simplify struct initializer for SHA256 padding eb28464a8b Change SHA256 byte counter from size_t to uint64_t ac83be33d0 Merge bitcoin-core/secp256k1#1079: configure: Add hidden --enable-dev-mode to enable all the stuff e0838d663d configure: Add hidden --enable-dev-mode to enable all the stuff fabd579dfa configure: Remove redundant code that sets _enable variables 0d4226c051 configure: Use canonical variable prefix _enable consistently 64b34979ed Merge bitcoin-core/secp256k1#748: Add usage examples 7c9502cece Add a copy of the CC0 license to the examples 42e03432e6 Add usage examples to the readme 517644eab1 Optionally compile the examples in autotools, compile+run in travis 422a7cc86a Add a ecdh shared secret example b0cfbcc143 Add a Schnorr signing and verifying example fee7d4bf9e Add an ECDSA signing and verifying example 1253a27756 Merge bitcoin-core/secp256k1#1033: Add _fe_half and use in _gej_add_ge and _gej_double 3ef94aa5ba Merge bitcoin-core/secp256k1#1026: ecdh: Add test computing shared_secret=basepoint with random inputs 3531a43b5b ecdh: Make generator_basepoint test depend on global iteration count c881dd49bd ecdh: Add test computing shared_secret=basepoint with random inputs 077528317d Merge bitcoin-core/secp256k1#1074: ci: Retry brew update a few times to avoid random failures e51ad3b737 ci: Retry `brew update` a few times to avoid random failures b1cb969e8a ci: Revert "Attempt to make macOS builds more reliable" 5dcc6f8dbd Merge bitcoin-core/secp256k1#1069: build: Replace use of deprecated autoconf macro AC_PROG_CC_C89 59547943d6 Merge bitcoin-core/secp256k1#1072: ci: Attempt to make macOS builds more reliable 85b00a1c65 Merge bitcoin-core/secp256k1#1068: sage: Fix incompatibility with sage 9.4 ebb1beea78 sage: Ensure that constraints are always fastfracs d8d54859ed ci: Run sage prover on CI 77cfa98dbc sage: Normalize sign of polynomial factors in prover eae75869cf sage: Exit with non-zero status in case of failures d9396a56da ci: Attempt to make macOS builds more reliable e0db3f8a25 build: Replace use of deprecated autoconf macro AC_PROG_CC_C89 e848c3799c Update sage files for new formulae d64bb5d4f3 Add fe_half tests for worst-case inputs b54d843eac sage: Fix printing of errors 4eb8b932ff Further improve doubling formula using fe_half 557b31fac3 Doubling formula using fe_half 2cbb4b1a42 Run more iterations of run_field_misc 9cc5c257ed Add test for secp256k1_fe_half 925f78d55e Add _fe_half and use in _gej_add_ge e108d0039c sage: Fix incompatibility with sage 9.4 d8a2463246 Merge bitcoin-core/secp256k1#899: Reduce stratch space needed by ecmult_strauss_wnaf. 0a40a4861a Merge bitcoin-core/secp256k1#1049: Faster fixed-input ecmult tests 070e772211 Faster fixed-input ecmult tests c8aa516b57 Merge bitcoin-core/secp256k1#1064: Modulo-reduce msg32 inside RFC6979 nonce fn to match spec. Fixes #1063 b797a500ec Create a SECP256K1_ECMULT_TABLE_VERIFY macro. a731200cc3 Replace ECMULT_TABLE_GET_GE_STORAGE macro with a function. fe34d9f341 Eliminate input_pos state field from ecmult_strauss_wnaf. 0397d00ba0 Eliminate na_1 and na_lam state fields from ecmult_strauss_wnaf. 7ba3ffcca0 Remove the unused pre_a_lam allocations. b3b57ad6ee Eliminate the pre_a_lam array from ecmult_strauss_wnaf. ae7ba0f922 Remove the unused prej allocations. e5c18892db Eliminate the prej array from ecmult_strauss_wnaf. c9da1baad1 Move secp256k1_fe_one to field.h 45f37b6506 Modulo-reduce msg32 inside RFC6979 nonce fn to match spec. Fixes #1063. a1102b1219 Merge bitcoin-core/secp256k1#1029: Simpler and faster ecdh skew fixup e82144edfb Fixup skew before global Z fixup 40b624c90b Add tests for _gej_cmov 8c13a9bfe1 ECDH skews by 0 or 1 1515099433 Simpler and faster ecdh skew fixup 39a36db94a Merge bitcoin-core/secp256k1#1054: tests: Fix test whose result is implementation-defined a310e79ee5 Merge bitcoin-core/secp256k1#1052: Use xoshiro256++ instead of RFC6979 for tests 423b6d19d3 Merge bitcoin-core/secp256k1#964: Add release-process.md 9281c9f4e1 Merge bitcoin-core/secp256k1#1053: ecmult: move `_ecmult_odd_multiples_table_globalz_windowa` 77a19750b4 Use xoshiro256++ PRNG instead of RFC6979 in tests 5f2efe684e secp256k1_testrand_int(2**N) -> secp256k1_testrand_bits(N) 05e049b73c ecmult: move `_ecmult_odd_multiples_table_globalz_windowa` 3d7cbafb5f tests: Fix test whose result is implementation-defined 3ed0d02bf7 doc: add CHANGELOG template 6f42dc16c8 doc: add release_process.md 0bd3e4243c build: set library version to 0.0.0 explicitly b4b02fd8c4 build: change libsecp version from 0.1 to 0.1.0-pre 09971a3ffd Merge bitcoin-core/secp256k1#1047: ci: Various improvements 0b83b203e1 Merge bitcoin-core/secp256k1#1030: doc: Fix upper bounds + cleanup in field_5x52_impl.h comment 1287786c7a doc: Add comment to top of field_10x26_impl.h 58da5bd589 doc: Fix upper bounds + cleanup in field_5x52_impl.h comment b39d431aed Merge bitcoin-core/secp256k1#1044: Add another ecmult_multi test b4ac1a1d5f ci: Run valgrind/memcheck tasks with 2 CPUs e70acab601 ci: Use Cirrus "greedy" flag to use idle CPU time when available d07e30176e ci: Update brew on macOS 22382f0ea0 ci: Test different ecmult window sizes a69df3ad24 Merge bitcoin-core/secp256k1#816: Improve checks at top of _fe_negate methods 22d25c8e0a Add another ecmult_multi test 515e7953ca Improve checks at top of _fe_negate methods 26a022a3a0 ci: Remove STATICPRECOMPUTATION 10461d8bd3 precompute_ecmult: Always compute all tables up to default WINDOW_G be6944ade9 Merge bitcoin-core/secp256k1#1042: Follow-ups to making all tables fully static e05da9e480 Fix c++ build c45386d994 Cleanup preprocessor indentation in precompute{,d}_ecmult{,_gen} 19d96e15f9 Split off .c file from precomputed_ecmult.h 1a6691adae Split off .c file from precomputed_ecmult_gen.h bb36331412 Simplify precompute_ecmult_print_* 38cd84a0cb Compute ecmult tables at runtime for tests_exhaustive e458ec26d6 Move ecmult table computation code to separate file fc1bf9f15f Split ecmult table computation and printing 31feab053b Rename function secp256k1_ecmult_gen_{create_prec -> compute}_table 725370c3f2 Rename ecmult_gen_prec -> ecmult_gen_compute_table 075252c1b7 Rename ecmult_static_pre_g -> precomputed_ecmult 7cf47f72bc Rename ecmult_gen_static_prec_table -> precomputed_ecmult_gen f95b8106d0 Rename gen_ecmult_static_pre_g -> precompute_ecmult bae77685eb Rename gen_ecmult_gen_static_prec_table -> precompute_ecmult_gen git-subtree-dir: src/secp256k1 git-subtree-split: 8746600eec5e7fcd35dabd480839a3a4bdfee87b
275 lines
9.6 KiB
Python
275 lines
9.6 KiB
Python
# Prover implementation for Weierstrass curves of the form
|
|
# y^2 = x^3 + A * x + B, specifically with a = 0 and b = 7, with group laws
|
|
# operating on affine and Jacobian coordinates, including the point at infinity
|
|
# represented by a 4th variable in coordinates.
|
|
|
|
load("group_prover.sage")
|
|
|
|
|
|
class affinepoint:
|
|
def __init__(self, x, y, infinity=0):
|
|
self.x = x
|
|
self.y = y
|
|
self.infinity = infinity
|
|
def __str__(self):
|
|
return "affinepoint(x=%s,y=%s,inf=%s)" % (self.x, self.y, self.infinity)
|
|
|
|
|
|
class jacobianpoint:
|
|
def __init__(self, x, y, z, infinity=0):
|
|
self.X = x
|
|
self.Y = y
|
|
self.Z = z
|
|
self.Infinity = infinity
|
|
def __str__(self):
|
|
return "jacobianpoint(X=%s,Y=%s,Z=%s,inf=%s)" % (self.X, self.Y, self.Z, self.Infinity)
|
|
|
|
|
|
def point_at_infinity():
|
|
return jacobianpoint(1, 1, 1, 1)
|
|
|
|
|
|
def negate(p):
|
|
if p.__class__ == affinepoint:
|
|
return affinepoint(p.x, -p.y)
|
|
if p.__class__ == jacobianpoint:
|
|
return jacobianpoint(p.X, -p.Y, p.Z)
|
|
assert(False)
|
|
|
|
|
|
def on_weierstrass_curve(A, B, p):
|
|
"""Return a set of zero-expressions for an affine point to be on the curve"""
|
|
return constraints(zero={p.x^3 + A*p.x + B - p.y^2: 'on_curve'})
|
|
|
|
|
|
def tangential_to_weierstrass_curve(A, B, p12, p3):
|
|
"""Return a set of zero-expressions for ((x12,y12),(x3,y3)) to be a line that is tangential to the curve at (x12,y12)"""
|
|
return constraints(zero={
|
|
(p12.y - p3.y) * (p12.y * 2) - (p12.x^2 * 3 + A) * (p12.x - p3.x): 'tangential_to_curve'
|
|
})
|
|
|
|
|
|
def colinear(p1, p2, p3):
|
|
"""Return a set of zero-expressions for ((x1,y1),(x2,y2),(x3,y3)) to be collinear"""
|
|
return constraints(zero={
|
|
(p1.y - p2.y) * (p1.x - p3.x) - (p1.y - p3.y) * (p1.x - p2.x): 'colinear_1',
|
|
(p2.y - p3.y) * (p2.x - p1.x) - (p2.y - p1.y) * (p2.x - p3.x): 'colinear_2',
|
|
(p3.y - p1.y) * (p3.x - p2.x) - (p3.y - p2.y) * (p3.x - p1.x): 'colinear_3'
|
|
})
|
|
|
|
|
|
def good_affine_point(p):
|
|
return constraints(nonzero={p.x : 'nonzero_x', p.y : 'nonzero_y'})
|
|
|
|
|
|
def good_jacobian_point(p):
|
|
return constraints(nonzero={p.X : 'nonzero_X', p.Y : 'nonzero_Y', p.Z^6 : 'nonzero_Z'})
|
|
|
|
|
|
def good_point(p):
|
|
return constraints(nonzero={p.Z^6 : 'nonzero_X'})
|
|
|
|
|
|
def finite(p, *affine_fns):
|
|
con = good_point(p) + constraints(zero={p.Infinity : 'finite_point'})
|
|
if p.Z != 0:
|
|
return con + reduce(lambda a, b: a + b, (f(affinepoint(p.X / p.Z^2, p.Y / p.Z^3)) for f in affine_fns), con)
|
|
else:
|
|
return con
|
|
|
|
def infinite(p):
|
|
return constraints(nonzero={p.Infinity : 'infinite_point'})
|
|
|
|
|
|
def law_jacobian_weierstrass_add(A, B, pa, pb, pA, pB, pC):
|
|
"""Check whether the passed set of coordinates is a valid Jacobian add, given assumptions"""
|
|
assumeLaw = (good_affine_point(pa) +
|
|
good_affine_point(pb) +
|
|
good_jacobian_point(pA) +
|
|
good_jacobian_point(pB) +
|
|
on_weierstrass_curve(A, B, pa) +
|
|
on_weierstrass_curve(A, B, pb) +
|
|
finite(pA) +
|
|
finite(pB) +
|
|
constraints(nonzero={pa.x - pb.x : 'different_x'}))
|
|
require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) +
|
|
colinear(pa, pb, negate(pc))))
|
|
return (assumeLaw, require)
|
|
|
|
|
|
def law_jacobian_weierstrass_double(A, B, pa, pb, pA, pB, pC):
|
|
"""Check whether the passed set of coordinates is a valid Jacobian doubling, given assumptions"""
|
|
assumeLaw = (good_affine_point(pa) +
|
|
good_affine_point(pb) +
|
|
good_jacobian_point(pA) +
|
|
good_jacobian_point(pB) +
|
|
on_weierstrass_curve(A, B, pa) +
|
|
on_weierstrass_curve(A, B, pb) +
|
|
finite(pA) +
|
|
finite(pB) +
|
|
constraints(zero={pa.x - pb.x : 'equal_x', pa.y - pb.y : 'equal_y'}))
|
|
require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) +
|
|
tangential_to_weierstrass_curve(A, B, pa, negate(pc))))
|
|
return (assumeLaw, require)
|
|
|
|
|
|
def law_jacobian_weierstrass_add_opposites(A, B, pa, pb, pA, pB, pC):
|
|
assumeLaw = (good_affine_point(pa) +
|
|
good_affine_point(pb) +
|
|
good_jacobian_point(pA) +
|
|
good_jacobian_point(pB) +
|
|
on_weierstrass_curve(A, B, pa) +
|
|
on_weierstrass_curve(A, B, pb) +
|
|
finite(pA) +
|
|
finite(pB) +
|
|
constraints(zero={pa.x - pb.x : 'equal_x', pa.y + pb.y : 'opposite_y'}))
|
|
require = infinite(pC)
|
|
return (assumeLaw, require)
|
|
|
|
|
|
def law_jacobian_weierstrass_add_infinite_a(A, B, pa, pb, pA, pB, pC):
|
|
assumeLaw = (good_affine_point(pa) +
|
|
good_affine_point(pb) +
|
|
good_jacobian_point(pA) +
|
|
good_jacobian_point(pB) +
|
|
on_weierstrass_curve(A, B, pb) +
|
|
infinite(pA) +
|
|
finite(pB))
|
|
require = finite(pC, lambda pc: constraints(zero={pc.x - pb.x : 'c.x=b.x', pc.y - pb.y : 'c.y=b.y'}))
|
|
return (assumeLaw, require)
|
|
|
|
|
|
def law_jacobian_weierstrass_add_infinite_b(A, B, pa, pb, pA, pB, pC):
|
|
assumeLaw = (good_affine_point(pa) +
|
|
good_affine_point(pb) +
|
|
good_jacobian_point(pA) +
|
|
good_jacobian_point(pB) +
|
|
on_weierstrass_curve(A, B, pa) +
|
|
infinite(pB) +
|
|
finite(pA))
|
|
require = finite(pC, lambda pc: constraints(zero={pc.x - pa.x : 'c.x=a.x', pc.y - pa.y : 'c.y=a.y'}))
|
|
return (assumeLaw, require)
|
|
|
|
|
|
def law_jacobian_weierstrass_add_infinite_ab(A, B, pa, pb, pA, pB, pC):
|
|
assumeLaw = (good_affine_point(pa) +
|
|
good_affine_point(pb) +
|
|
good_jacobian_point(pA) +
|
|
good_jacobian_point(pB) +
|
|
infinite(pA) +
|
|
infinite(pB))
|
|
require = infinite(pC)
|
|
return (assumeLaw, require)
|
|
|
|
|
|
laws_jacobian_weierstrass = {
|
|
'add': law_jacobian_weierstrass_add,
|
|
'double': law_jacobian_weierstrass_double,
|
|
'add_opposite': law_jacobian_weierstrass_add_opposites,
|
|
'add_infinite_a': law_jacobian_weierstrass_add_infinite_a,
|
|
'add_infinite_b': law_jacobian_weierstrass_add_infinite_b,
|
|
'add_infinite_ab': law_jacobian_weierstrass_add_infinite_ab
|
|
}
|
|
|
|
|
|
def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p):
|
|
"""Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field"""
|
|
F = Integers(p)
|
|
print("Formula %s on Z%i:" % (name, p))
|
|
points = []
|
|
for x in range(0, p):
|
|
for y in range(0, p):
|
|
point = affinepoint(F(x), F(y))
|
|
r, e = concrete_verify(on_weierstrass_curve(A, B, point))
|
|
if r:
|
|
points.append(point)
|
|
|
|
ret = True
|
|
for za in range(1, p):
|
|
for zb in range(1, p):
|
|
for pa in points:
|
|
for pb in points:
|
|
for ia in range(2):
|
|
for ib in range(2):
|
|
pA = jacobianpoint(pa.x * F(za)^2, pa.y * F(za)^3, F(za), ia)
|
|
pB = jacobianpoint(pb.x * F(zb)^2, pb.y * F(zb)^3, F(zb), ib)
|
|
for branch in range(0, branches):
|
|
assumeAssert, assumeBranch, pC = formula(branch, pA, pB)
|
|
pC.X = F(pC.X)
|
|
pC.Y = F(pC.Y)
|
|
pC.Z = F(pC.Z)
|
|
pC.Infinity = F(pC.Infinity)
|
|
r, e = concrete_verify(assumeAssert + assumeBranch)
|
|
if r:
|
|
match = False
|
|
for key in laws_jacobian_weierstrass:
|
|
assumeLaw, require = laws_jacobian_weierstrass[key](A, B, pa, pb, pA, pB, pC)
|
|
r, e = concrete_verify(assumeLaw)
|
|
if r:
|
|
if match:
|
|
print(" multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity))
|
|
else:
|
|
match = True
|
|
r, e = concrete_verify(require)
|
|
if not r:
|
|
ret = False
|
|
print(" failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e))
|
|
|
|
print()
|
|
return ret
|
|
|
|
|
|
def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC):
|
|
assumeLaw, require = f(A, B, pa, pb, pA, pB, pC)
|
|
return check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require)
|
|
|
|
def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula):
|
|
"""Verify an implementation of addition of Jacobian points on a Weierstrass curve symbolically"""
|
|
R.<ax,bx,ay,by,Az,Bz,Ai,Bi> = PolynomialRing(QQ,8,order='invlex')
|
|
lift = lambda x: fastfrac(R,x)
|
|
ax = lift(ax)
|
|
ay = lift(ay)
|
|
Az = lift(Az)
|
|
bx = lift(bx)
|
|
by = lift(by)
|
|
Bz = lift(Bz)
|
|
Ai = lift(Ai)
|
|
Bi = lift(Bi)
|
|
|
|
pa = affinepoint(ax, ay, Ai)
|
|
pb = affinepoint(bx, by, Bi)
|
|
pA = jacobianpoint(ax * Az^2, ay * Az^3, Az, Ai)
|
|
pB = jacobianpoint(bx * Bz^2, by * Bz^3, Bz, Bi)
|
|
|
|
res = {}
|
|
|
|
for key in laws_jacobian_weierstrass:
|
|
res[key] = []
|
|
|
|
print("Formula " + name + ":")
|
|
count = 0
|
|
ret = True
|
|
for branch in range(branches):
|
|
assumeFormula, assumeBranch, pC = formula(branch, pA, pB)
|
|
assumeBranch = assumeBranch.map(lift)
|
|
assumeFormula = assumeFormula.map(lift)
|
|
pC.X = lift(pC.X)
|
|
pC.Y = lift(pC.Y)
|
|
pC.Z = lift(pC.Z)
|
|
pC.Infinity = lift(pC.Infinity)
|
|
|
|
for key in laws_jacobian_weierstrass:
|
|
success, msg = check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC)
|
|
if not success:
|
|
ret = False
|
|
res[key].append((msg, branch))
|
|
|
|
for key in res:
|
|
print(" %s:" % key)
|
|
val = res[key]
|
|
for x in val:
|
|
if x[0] is not None:
|
|
print(" branch %i: %s" % (x[1], x[0]))
|
|
|
|
print()
|
|
return ret
|