20190826 15:46:25 +00:00



#!/usr/bin/env python




"""




ECC blind signature functionality based on "An Efficient Blind Signature Scheme




Based on the Elliptic CurveDiscrete Logarithm Problem" by Morteza Nikooghadama




<mnikooghadam@sbu.ac.ir> and Ali Zakerolhosseini <azaker@sbu.ac.ir>,




http://www.isecurejournal.com/article_39171_47f9ec605dd3918c2793565ec21fcd7a.pdf




"""








# variable names are based on the math in the paper, so they don't conform




# to PEP8




# pylint: disable=invalidname








from .openssl import OpenSSL












class ECCBlind(object): # pylint: disable=toomanyinstanceattributes




"""




Class for ECC blind signature functionality




"""








# init




k = None




R = None




keypair = None




F = None




Q = None




a = None




b = None




c = None




binv = None




r = None




m = None




m_ = None




s_ = None




signature = None








@staticmethod




def ec_get_random(group, ctx):




"""




Random point from finite field




"""




order = OpenSSL.BN_new()




OpenSSL.EC_GROUP_get_order(group, order, ctx)




OpenSSL.BN_rand(order, OpenSSL.BN_num_bits(order), 0, 0)




return order








@staticmethod




def ec_invert(group, a, ctx):




"""




ECC inversion




"""




order = OpenSSL.BN_new()




OpenSSL.EC_GROUP_get_order(group, order, ctx)




inverse = OpenSSL.BN_mod_inverse(0, a, order, ctx)




return inverse








@staticmethod




def ec_gen_keypair(group, ctx):




"""




Generate an ECC keypair




"""




d = ECCBlind.ec_get_random(group, ctx)




Q = OpenSSL.EC_POINT_new(group)




OpenSSL.EC_POINT_mul(group, Q, d, 0, 0, 0)




return (d, Q)





20190827 21:11:42 +00:00



@staticmethod




def ec_Ftor(F, group, ctx):




"""




x0 coordinate of F




"""




# F = (x0, y0)




x0 = OpenSSL.BN_new()




y0 = OpenSSL.BN_new()




OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, F, x0, y0,




ctx)




return x0








def __init__(self, curve="secp256k1", pubkey=None):

20190826 15:46:25 +00:00



self.ctx = OpenSSL.BN_CTX_new()





20190827 21:11:42 +00:00



if pubkey:




self.group, self.G, self.n, self.Q = pubkey




else:




self.group = OpenSSL.EC_GROUP_new_by_curve_name(OpenSSL.get_curve(curve))




# Order n




self.n = OpenSSL.BN_new()




OpenSSL.EC_GROUP_get_order(self.group, self.n, self.ctx)








# Generator G




self.G = OpenSSL.EC_GROUP_get0_generator(self.group)








# new keypair




self.keypair = ECCBlind.ec_gen_keypair(self.group, self.ctx)








self.Q = self.keypair[1]








self.pubkey = (self.group, self.G, self.n, self.Q)

20190826 15:46:25 +00:00







# Identity O (infinity)




self.iO = OpenSSL.EC_POINT_new(self.group)




OpenSSL.EC_POINT_set_to_infinity(self.group, self.iO)








def signer_init(self):




"""




Init signer




"""




# Signer: Random integer k




self.k = ECCBlind.ec_get_random(self.group, self.ctx)








# R = kG




self.R = OpenSSL.EC_POINT_new(self.group)




OpenSSL.EC_POINT_mul(self.group, self.R, self.k, 0, 0, 0)





20190827 21:11:42 +00:00



return self.R








def create_signing_request(self, R, msg):

20190826 15:46:25 +00:00



"""




Requester creates a new signing request




"""

20190827 21:11:42 +00:00



self.R = R

20190826 15:46:25 +00:00







# Requester: 3 random blinding factors




self.F = OpenSSL.EC_POINT_new(self.group)




OpenSSL.EC_POINT_set_to_infinity(self.group, self.F)




temp = OpenSSL.EC_POINT_new(self.group)




abinv = OpenSSL.BN_new()








# F != O




while OpenSSL.EC_POINT_cmp(self.group, self.F, self.iO, self.ctx) == 0:




self.a = ECCBlind.ec_get_random(self.group, self.ctx)




self.b = ECCBlind.ec_get_random(self.group, self.ctx)




self.c = ECCBlind.ec_get_random(self.group, self.ctx)








# F = b^1 * R...




self.binv = ECCBlind.ec_invert(self.group, self.b, self.ctx)




OpenSSL.EC_POINT_mul(self.group, temp, 0, self.R, self.binv, 0)




OpenSSL.EC_POINT_copy(self.F, temp)








# ... + a*b^1 * Q...




OpenSSL.BN_mul(abinv, self.a, self.binv, self.ctx)




OpenSSL.EC_POINT_mul(self.group, temp, 0, self.Q, abinv, 0)




OpenSSL.EC_POINT_add(self.group, self.F, self.F, temp, 0)








# ... + c*G




OpenSSL.EC_POINT_mul(self.group, temp, 0, self.G, self.c, 0)




OpenSSL.EC_POINT_add(self.group, self.F, self.F, temp, 0)








# F = (x0, y0)

20190827 21:11:42 +00:00



self.r = ECCBlind.ec_Ftor(self.F, self.group, self.ctx)

20190826 15:46:25 +00:00







# Requester: Blinding (m' = br(m) + a)




self.m = OpenSSL.BN_new()




OpenSSL.BN_bin2bn(msg, len(msg), self.m)








self.m_ = OpenSSL.BN_new()




OpenSSL.BN_mod_mul(self.m_, self.b, self.r, self.n, self.ctx)




OpenSSL.BN_mod_mul(self.m_, self.m_, self.m, self.n, self.ctx)




OpenSSL.BN_mod_add(self.m_, self.m_, self.a, self.n, self.ctx)

20190827 21:11:42 +00:00



return self.m_

20190826 15:46:25 +00:00




20190827 21:11:42 +00:00



def blind_sign(self, m_):

20190826 15:46:25 +00:00



"""




Signer blindsigns the request




"""

20190827 21:11:42 +00:00



self.m_ = m_

20190826 15:46:25 +00:00



self.s_ = OpenSSL.BN_new()




OpenSSL.BN_mod_mul(self.s_, self.keypair[0], self.m_, self.n, self.ctx)




OpenSSL.BN_mod_add(self.s_, self.s_, self.k, self.n, self.ctx)

20190827 21:11:42 +00:00



return self.s_

20190826 15:46:25 +00:00




20190827 21:11:42 +00:00



def unblind(self, s_):

20190826 15:46:25 +00:00



"""




Requester unblinds the signature




"""

20190827 21:11:42 +00:00



self.s_ = s_

20190826 15:46:25 +00:00



s = OpenSSL.BN_new()




OpenSSL.BN_mod_mul(s, self.binv, self.s_, self.n, self.ctx)




OpenSSL.BN_mod_add(s, s, self.c, self.n, self.ctx)




self.signature = (s, self.F)

20190827 21:11:42 +00:00



return self.signature

20190826 15:46:25 +00:00




20190827 21:11:42 +00:00



def verify(self, msg, signature):

20190826 15:46:25 +00:00



"""




Verify signature with certifier's pubkey




"""

20190827 21:11:42 +00:00







# convert msg to BIGNUM




self.m = OpenSSL.BN_new()




OpenSSL.BN_bin2bn(msg, len(msg), self.m)








# init




s, self.F = signature




if self.r is None:




self.r = ECCBlind.ec_Ftor(self.F, self.group, self.ctx)





20190826 15:46:25 +00:00



lhs = OpenSSL.EC_POINT_new(self.group)




rhs = OpenSSL.EC_POINT_new(self.group)





20190827 21:11:42 +00:00



OpenSSL.EC_POINT_mul(self.group, lhs, s, 0, 0, 0)





20190826 15:46:25 +00:00



OpenSSL.EC_POINT_mul(self.group, rhs, 0, self.Q, self.m, 0)




OpenSSL.EC_POINT_mul(self.group, rhs, 0, rhs, self.r, 0)




OpenSSL.EC_POINT_add(self.group, rhs, rhs, self.F, self.ctx)








retval = OpenSSL.EC_POINT_cmp(self.group, lhs, rhs, self.ctx)




if retval == 1:




raise RuntimeError("EC_POINT_cmp returned an error")




else:




return retval == 0
