arnaucube
arnaucube/mathPublic Self-hosted repository
math/blind-sign-over-ec.sage
blind-sign-over-ec.sageRaw
 1# Implementation of: https://sci-hub.se/10.1109/iccke.2013.6682844
 2# more details at: https://arnaucube.com/blog/blind-signatures-ec.html#the-scheme
 3# A Go implementation of this schema can be found at: https://github.com/arnaucube/go-blindsecp256k1
 4
 5from hashlib import sha256
 6
 7def hash(m):
 8    h_output = sha256(str(m).encode('utf-8'))
 9    return int(h_output.hexdigest(), 16)
10
11
12
13class User:
14    def __init__(self, F, G):
15        self.F = F # Z_q
16        self.G = G # elliptic curve generator
17
18    def blind_msg(self, m, R_):
19        self.a = self.F.random_element()
20        self.b = self.F.random_element()
21        self.R = self.a * R_ + self.b * self.G
22        m_ = self.F(self.a)^(-1) * self.F(self.R.xy()[0]) * self.F(hash(m))
23        return m_
24
25    def unblind_sig(self, s_):
26        s = self.a * s_ + self.b
27        return (self.R, s)
28
29
30class Signer:
31    def __init__(self, F, G):
32        self.F = F # Z_q
33        self.G = G # elliptic curve generator
34
35        # gen Signer's key pair
36        self.d = self.F.random_element()
37        self.Q = self.G * self.d
38
39
40    def new_request_params(self):
41        self.k = self.F.random_element()
42        R_ = self.G * self.k
43        return R_
44
45    def blind_sign(self, m_):
46        return self.d * m_ + self.k
47
48def verify(G, Q, sig, m):
49    (R, s) = sig
50    return s*G == R + (Fq(R.xy()[0]) * Fq(hash(m))) * Q
51
52
53
54# ethereum elliptic curve
55p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F # base field
56a = 0
57b = 7
58F = GF(p) # base field
59E = EllipticCurve(F, [a,b])
60GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
61GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
62g = E(GX,GY)
63n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
64q = g.order() # order of Fp
65assert is_prime(p)
66assert is_prime(q)
67Fq = GF(q) # scalar field
68
69
70
71# protocol flow:
72
73user = User(Fq, g)
74signer = Signer(Fq, g)
75
76R_ = signer.new_request_params()
77
78m = 12345 # user's message
79m_ = user.blind_msg(m, R_)
80
81s_ = signer.blind_sign(m_)
82
83sig = user.unblind_sig(s_)
84
85v = verify(g, signer.Q, sig, m)
86print(v)
87assert v