-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathothercurves.py
118 lines (99 loc) · 4.02 KB
/
othercurves.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# Copyright (C) CodeGuro
# from pyschoof import reduced_computation_schoof
def legendre(a, p):
return pow(a, (p - 1) // 2, p)
def tonelli(n, p):
assert legendre(n, p) == 1, "not a square (mod p)"
q = p - 1
s = 0
while q % 2 == 0:
q //= 2
s += 1
if s == 1:
return pow(n, (p + 1) // 4, p)
for z in range(2, p):
if p - 1 == legendre(z, p):
break
c = pow(z, q, p)
r = pow(n, (q + 1) // 2, p)
t = pow(n, q, p)
m = s
t2 = 0
while (t - 1) % p != 0:
t2 = (t * t) % p
for i in range(1, m):
if (t2 - 1) % p == 0:
break
t2 = (t2 * t2) % p
b = pow(c, 1 << (m - i - 1), p)
r = (r * b) % p
c = (b * b) % p
t = (t * c) % p
m = i
return r
# Python 2.7.6 - Super simple Elliptic Curve Presentation. No imported libraries, wrappers, nothing. # For educational purposes only
# Below are the public specs for Bitcoin's curve - the secp256k1
Pcurve = 2 ** 256 - 2 ** 32 - 2 ** 9 - 2 ** 8 - 2 ** 7 - 2 ** 6 - 2 ** 4 - 1 # The proven prime
N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 # Number of points in the field
Acurve = 0
Bcurve = 7 # This defines the curve. y^2 = x^3 + Acurve * x + Bcurve
Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240
Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424
GPoint = (Gx, Gy) # This is our generator point. Tillions of dif ones possible
# Individual Transaction/Personal Information
privKey = 75263518707598184987916378021939673586055614731957507592904438851787542395619 # replace with any private key
RandNum = 28695618543805844332113829720373285210420739438570883203839696518176414791234 # replace with a truly random number
HashOfThingToSign = 8603211231910161104515253669637772856272773459297323797145286374828050 # the hash of your message/transaction
def modinv(a, n=Pcurve): # Extended Euclidean Algorithm/'division' in elliptic curves
lm, hm = 1, 0
low, high = a % n, n
while low > 1:
ratio = high // low
nm, new = hm - lm * ratio, high - low * ratio
lm, low, hm, high = nm, new, lm, low
return lm % n
def ECadd(xp, yp, xq, yq): # Not true addition, invented for EC. It adds Point-P with Point-Q.
m = ((yq - yp) * modinv(xq - xp, Pcurve)) % Pcurve
xr = (m * m - xp - xq) % Pcurve
yr = (m * (xp - xr) - yp) % Pcurve
return (xr, yr)
def ECdouble(xp, yp): # EC point doubling, invented for EC. It doubles Point-P.
LamNumer = 3 * xp * xp + Acurve
LamDenom = 2 * yp
Lam = (LamNumer * modinv(LamDenom, Pcurve)) % Pcurve
xr = (Lam * Lam - 2 * xp) % Pcurve
yr = (Lam * (xp - xr) - yp) % Pcurve
return (xr, yr)
def EccMultiply(xs, ys, Scalar): # Double & add. EC Multiplication, Not true multiplication
if Scalar == 0 or Scalar >= N:
raise Exception("Invalid Scalar/Private Key")
ScalarBin = str(bin(Scalar))[2:]
Qx, Qy = xs, ys
for i in range(1, len(ScalarBin)): # This is invented EC multiplication.
Qx, Qy = ECdouble(Qx, Qy) # print "DUB", Qx; print
if ScalarBin[i] == "1":
Qx, Qy = ECadd(Qx, Qy, xs, ys) # print "ADD", Qx; print
return (Qx, Qy)
print()
print("******* Public Key Generation *********")
xPublicKey, yPublicKey = EccMultiply(Gx, Gy, privKey)
print("the private key (in base 10 format):")
print(privKey)
print()
print("the uncompressed public key (starts with '04' & is not the public address):")
print("04", xPublicKey, yPublicKey)
print()
print("******* Signature Generation *********")
xRandSignPoint, yRandSignPoint = EccMultiply(Gx, Gy, RandNum)
r = xRandSignPoint % N
print("r =", r)
s = ((HashOfThingToSign + r * privKey) * (modinv(RandNum, N))) % N
print("s =", s)
print()
print("******* Signature Verification *********>>")
w = modinv(s, N)
xu1, yu1 = EccMultiply(Gx, Gy, (HashOfThingToSign * w) % N)
xu2, yu2 = EccMultiply(xPublicKey, yPublicKey, (r * w) % N)
x, y = ECadd(xu1, yu1, xu2, yu2)
print(r == x)
print()