diff --git a/blind-sign-over-ec.sage b/blind-sign-over-ec.sage new file mode 100644 index 0000000..6b7d82e --- /dev/null +++ b/blind-sign-over-ec.sage @@ -0,0 +1,87 @@ +# Implementation of: https://sci-hub.se/10.1109/iccke.2013.6682844 +# more details at: https://arnaucube.com/blog/blind-signatures-ec.html#the-scheme +# A Go implementation of this schema can be found at: https://github.com/arnaucube/go-blindsecp256k1 + +from hashlib import sha256 + +def hash(m): + h_output = sha256(str(m).encode('utf-8')) + return int(h_output.hexdigest(), 16) + + + +class User: + def __init__(self, F, G): + self.F = F # Z_q + self.G = G # elliptic curve generator + + def blind_msg(self, m, R_): + self.a = self.F.random_element() + self.b = self.F.random_element() + self.R = self.a * R_ + self.b * self.G + m_ = self.F(self.a)^(-1) * self.F(self.R.xy()[0]) * self.F(hash(m)) + return m_ + + def unblind_sig(self, s_): + s = self.a * s_ + self.b + return (self.R, s) + + +class Signer: + def __init__(self, F, G): + self.F = F # Z_q + self.G = G # elliptic curve generator + + # gen Signer's key pair + self.d = self.F.random_element() + self.Q = self.G * self.d + + + def new_request_params(self): + self.k = self.F.random_element() + R_ = self.G * self.k + return R_ + + def blind_sign(self, m_): + return self.d * m_ + self.k + +def verify(G, Q, sig, m): + (R, s) = sig + return s*G == R + (Fq(R.xy()[0]) * Fq(hash(m))) * Q + + + +# ethereum elliptic curve +p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F +a = 0 +b = 7 +F = GF(p) +E = EllipticCurve(F, [a,b]) +GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 +GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8 +g = E(GX,GY) +n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 +q = g.order() +assert is_prime(p) +assert is_prime(q) +Fq = GF(q) + + + +# protocol flow: + +user = User(Fq, g) +signer = Signer(Fq, g) + +R_ = signer.new_request_params() + +m = 12345 # user's message +m_ = user.blind_msg(m, R_) + +s_ = signer.blind_sign(m_) + +sig = user.unblind_sig(s_) + +v = verify(g, signer.Q, sig, m) +print(v) +assert v