Skip to content

Instantly share code, notes, and snippets.

@Goatghosts
Last active October 1, 2023 15:14
Show Gist options
  • Save Goatghosts/680d4538a3650fcdfe2364c987946f61 to your computer and use it in GitHub Desktop.
Save Goatghosts/680d4538a3650fcdfe2364c987946f61 to your computer and use it in GitHub Desktop.
I was playing with the constants related to the implementation of endomorphism on the secp256k1 curve, and through strange manipulations, I was able to derive LAMBDA and LAMBDA^2 from B1 and B2. I am not familiar with the original document, so this was a bit of a discovery for me. But overall, there's probably nothing useful here.
import copy
import random
P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
a = 0x0000000000000000000000000000000000000000000000000000000000000000
b = 0x0000000000000000000000000000000000000000000000000000000000000007
PLUS_G = (
55066263022277343669578718895168534326250603453777594175500187360389116729240,
32670510020758816978083085130507043184471273380659243275938904335757337482424,
)
N = 115792089237316195423570985008687907852837564279074904382605163141518161494337
A1 = 64502973549206556628585045361533709077
B1 = -303414439467246543595250775667605759171
B1_NEG = 303414439467246543595250775667605759171
A2 = 367917413016453100223835821029139468248
B2 = 64502973549206556628585045361533709077
B3 = N - (B1_NEG + B2)
def double_point(point):
x, y = point
s = ((3 * x * x + a) * pow(2 * y, P - 2, P)) % P
x3 = (s * s - 2 * x) % P
y3 = (s * (x - x3) - y) % P
return (x3, y3)
def add_points(point1, point2):
if point1 == point2:
return double_point(point1)
x1, y1 = point1
x2, y2 = point2
s = ((y2 - y1) * pow(x2 - x1, P - 2, P)) % P
x3 = (s * s - x1 - x2) % P
y3 = (s * (x1 - x3) - y1) % P
return (x3, y3)
def scalar_mult(scalar, point):
current_point = copy.copy(point)
bits = bin(scalar)[2:]
for bit in bits[1:]:
current_point = double_point(current_point)
if bit == "1":
current_point = add_points(current_point, point)
return current_point
def base_test():
k = int.from_bytes(random.randbytes(2), "big")
k_point = scalar_mult(k, PLUS_G)
print("random scalar:", k, "| random point:", k_point)
k1 = (B2 * k) % N
k2 = (B3 * k) % N
k3 = (B1_NEG * k) % N
k1_point = scalar_mult(B2, k_point)
k2_point = scalar_mult(B3, k_point)
k3_point = scalar_mult(B1_NEG, k_point)
print("k1_point", k1, k1_point)
print("k2_point", k2, k2_point)
print("k3_point", k3, k3_point)
def check_constants(k, b1, b2, b3):
k1 = (b2 * k) % N
k2 = (b1 * k) % N
k3 = (b3 * k) % N
k1_point = scalar_mult(k1, PLUS_G)
k2_point = scalar_mult(k2, PLUS_G)
k3_point = scalar_mult(k3, PLUS_G)
assert k1_point[1] == k2_point[1] == k3_point[1]
def main():
k = int.from_bytes(random.randbytes(32), "big")
b1 = B1_NEG % N
b2 = B2 % N
while b1 != 1 and b2 != 1:
distance = N // b2 + 1
b1 = b1 * distance % N
b2 = b2 * distance % N
b3 = N - (b2 + b1)
print(f"B1 = {b1} ({b1.bit_length()} bits), B2 = {b2} ({b2.bit_length()} bits)")
check_constants(k, b1, b2, b3)
print("LAMBDA:", b2)
print("LAMBDA (x1):", b3)
print("LAMBDA (x2):", b1)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment