def derive(self, vk, m, D, sigma): D = set(D) universal = set(range(1, self.n + 1)) D_ = universal - D t = Bn.from_decimal(str(self.p)).random() r = Bn.from_decimal(str(self.p)).random() sigma1_ = bp.G1Elem.inf(self.G) sigma2_ = bp.G1Elem.inf(self.G) if len(D_) != 0: # if _D_ is not empty sigma1_ += t * self.G.gen1() for i in D_: sigma1_ += m[i - 1] * vk[1][i - 1] for i in D: sigma2_ += vk[1][i - 1] sigma2_ = t * sigma2_ for j in D_: temp_z = bp.G1Elem.inf(self.G) for i in D: temp_z += vk[3][max(i, j) * self.n + min(i, j)] temp_z *= m[j - 1] sigma2_ += temp_z else: sigma1_ = t * self.G.gen1() for i in range(self.n): sigma2_ += vk[1][i] sigma2_ *= t sigma1__ = r * sigma[2] sigma2__ = r * (sigma[3] + t * sigma[2]) return [sigma1_, sigma2_, sigma1__, sigma2__]
def sign(self, sk, m): # 输入类型检测,要求m属于Zp try: m = Bn.from_decimal(str(m)) if m < 0 or m > self.p: # if not a positive int print message and ask for input again print( "m is out of range, please ensure m to be an integer in [0,p)" ) except ValueError: print("m is not an int, please ensure m to be an integer in [0,p)") # 把这个整数类型的信息m转化为字符串类型,便于使用hashG1函数 # while语句使得x + m != 0 if self.x + m == 0: print("x有问题") theta = (Bn.from_decimal(str(self.x + m)).mod_inverse(self.G.order()) * self.g1) return theta
def sign(self, sk, m): # 输入类型检测,要求m属于Zp try: m = Bn.from_decimal(str(m)) if m < 0 or m > self.p: # if not a positive int print message and ask for input again print( "m is out of range, please ensure m to be an integer in [0,p)" ) except ValueError: print("m is not an int, please ensure m to be an integer in [0,p)") # while语句使得x + r*y + m != 0 while self.x + self.r * self.y + m == 0: self.r = Bn().from_decimal(str(self.p)).random() self.theta_prime = (Bn.from_decimal( str(self.x + self.r * self.y + m)).mod_inverse( self.G.order())) * self.g1 theta = (self.theta_prime, self.r) return theta
def sign(self, sk, m): if self.n < 0: raise "RS::sign(): keygen should be runned before other functions" r = Bn.from_decimal(str(self.p)).random() sigma1 = r * self.G.gen2() e = sk[0] for i in range(self.n): e += sk[1][i] * m[i] sigma2 = e * sigma1 return [bp.G1Elem.inf(self.G), bp.G1Elem.inf(self.G), sigma1, sigma2]
def keygen(self, n): self.n = n x = Bn.from_decimal(str(self.p)).random() X = x * self.G.gen1() y = [] Y = [] _Y = [] for i in range(n): y.append(Bn.from_decimal(str(self.p)).random()) Y.append(y[i] * self.G.gen1()) _Y.append(y[i] * self.G.gen2()) Z = {} for i in range(n): for j in range(i): # Z[i * n + j] is Z(i, j), 0 < j < i Z[(i + 1) * self.n + j + 1] = (y[i] * y[j]) * self.G.gen1() sk = [x, y] vk = [X, Y, _Y, Z] return sk, vk
def time_scalar_mul(): # Get EC Parameters G = EcGroup(713) d = G.parameters() a, b, p = d["a"], d["b"], d["p"] g = G.generator() x, y = g.get_affine() # Generate graph data double_add = list() fixed_double_add = list() montgomerry_ladder = list() n = 500 bits_set = range(1, n) for i in bits_set: scalar = Bn.from_decimal(("1" * i) + ("0" * (n - i - 1))) print i, scalar double_add.append( get_time_dif(point_scalar_multiplication_double_and_add, (a, b, p, x, y, scalar))) fixed_double_add.append( get_time_dif(fixed_point_scalar_multiplication_double_and_add, (a, b, p, x, y, scalar))) montgomerry_ladder.append( get_time_dif(point_scalar_multiplication_montgomerry_ladder, (a, b, p, x, y, scalar))) fig = plt.figure("Runtime graphs") gs = gridspec.GridSpec(4, 4) ax = plt.subplot(gs[0:2, 0:2]) ax.set_title("Double and Add") ax.plot(bits_set, double_add) ax.set_xlabel("Number of bits set") ax.set_ylabel("Time taken to multiply") ax = plt.subplot(gs[0:2, 2:]) ax.set_title("Montgomerry Ladder") ax.plot(bits_set, montgomerry_ladder) ax.set_xlabel("Number of bits set") ax.set_ylabel("Time taken to multiply") ax = plt.subplot(gs[2:4, 1:3]) ax.set_title("Fixed Double and Add") ax.plot(bits_set, fixed_double_add) ax.set_xlabel("Number of bits set") ax.set_ylabel("Time taken to multiply") gs.tight_layout(fig) plt.show()
def commit_str(ck, elements_str, rand=None): '''Computes vector commitment to elements using ck (and optionally using a given randomness). Outputs a point on the curve and the randomness used (if not given as input)''' G, key = ck #print 'test', len(key),len(elements) if len(elements_str) >= len(key): raise Exception('Too many elements!Longer key required') #term=(Bn.from_decimal(str(elements[i]))*key[i] for i in xrange(len(elements))) #bvec=_FFI.new("EC_POINT * []",len(elements)) #for i in xrange(len(elements)): bvec[i]=key[i].pt #evec=_FFI.new("BIGNUM * []",len(elements)) #for i in xrange(len(elements)): evec[i]=Bn.from_decimal(str(elements[i])).bn #comm = EcPt(G) #_C.EC_POINTs_mul(G.ecg, comm.pt, _FFI.NULL,len(elements), bvec, evec, _FFI.NULL) #comm=reduce(lambda x, y : x + y,term) #comm=mult_prod_str(ck,elements) if rand == None: rand = G.order().random() #random_point=rand*key[-1] #comm=comm+random_point #elements_str=list(elements_str)+[rand] elements = [Bn.from_decimal(str(int(x))) for x in elements_str] + [Bn.from_decimal(str(rand))] comm = mult_prod(G, key[:len(elements) - 1] + [key[-1]], elements) return comm, long(rand) #random_point=Bn.from_decimal(str(rand))*key[-1] #comm=comm+random_point #elements_str=list(elements_str)+[rand] elements = [Bn.from_decimal(str(x)) for x in elements_str] + [Bn.from_decimal(str(rand))] comm = mult_prod(G, key[:len(elements) - 1] + [key[-1]], elements) return comm
def sign(self, sk, m): # 输入类型检测,要求m属于Zp try: m = Bn.from_decimal(str(m)) if m < 0 or m > self.p: # if not a positive int print message and ask for input again print( "m is out of range, please ensure m to be an integer in [0,p)" ) except ValueError: print("m is not an int, please ensure m to be an integer in [0,p)") # 把这个整数类型的信息m转化为字符串类型,便于使用hashG1函数 m = str(m) self.h = self.G.hashG1(m.encode("utf8")) theta = self.x * self.h return theta
def mult_prod_str( G, key, elements ): #not actually used in commit_str, but could be potentially useful. Be careful that it was potentially causing segmentation fault. #G,key=ck bvec = _FFI.new("EC_POINT * []", len(elements)) for i in xrange(len(elements)): bvec[i] = key[i].pt evec = _FFI.new("BIGNUM * []", len(elements)) for i in xrange(len(elements)): evec[i] = Bn.from_decimal(str(elements[i])).bn comm = EcPt(G) _C.EC_POINTs_mul(G.ecg, comm.pt, _FFI.NULL, len(elements), bvec, evec, _FFI.NULL) return comm
def sign_pdf(pdfname, sk): # 这一版仅对原件做签名,不考虑待签名的证书已有签名的情况 print('signing',pdfname) # 先读出sigs 然后置为空写回 # pdf = PdfReader(pdfname) # print(pdf.Info) # try: # sigs = pdf.Info.signature #sigs: <class 'pdfrw.objects.pdfarray.PdfArray'> # except: # sigs = [] # metadata = PdfDict(signature = []) # pdf.Info.update(metadata) # PdfWriter().write(pdfname, pdf) sig = '' # 根据pdf名读取其中内容至m中 with open(pdfname, 'rb') as cert: content = cert.read() # content : bytes m:list m = list(content) params = setup() sk_bn = Bn.from_decimal(sk) sig = sign(params,sk_bn,m) # 将sig写回pdf metadata域 # sigs.append(sig) sig_bytes = sig.export() sig_str = base64.b64encode(sig_bytes).decode() metadata_new = PdfDict(signature = sig_str) """ Import a G1 point from bytes. Export: >>> G = BpGroup() >>> g1 = G.gen1() >>> buf = g1.export() >>> g1p = G1Elem.from_bytes(buf, G) >>> g1 == g1p True """ pdf = PdfReader(pdfname) pdf.Info.update(metadata_new) PdfWriter().write(pdfname, pdf)
def verifyMaskedCommitments(pm_vote_commitments, comm_pairs, tally): permuted_votes = [] for comm, unmask in zip(pm_vote_commitments, comm_pairs): permuted_votes.append(unmask[0]) assert (comm == commit(unmask[0], Bn.from_decimal(unmask[1]))) assert (tally == Counter(permuted_votes))
import random from petlib.bn import Bn from petlib.ec import EcGroup, EcPt from bplib import bp # 在FBB和WBB中遇到的一个Bug G = bp.BpGroup() p = 19 m = 16 x = Bn(p).random() print(x) # 这种情况会报错:TypeError: bad operand type for abs(): 'Bn' num = Bn(x + m).mod_inverse(G.order()) print(num) # 解决方案:改为如下写法 num = Bn(int(x + m)).mod_inverse(G.order()) print(num) # 在BLS,FBB,WBB中会遇到另外一个Bug # 无法使用大整数问题:如果是Bn(x),x不能超过2^32,而且必须是int类型,即最好写成Bn(int(x)),否则可能报错(上述 # 因此我们可以用别的方法来避免这种调用 Bn.from_decimal(str(x + m))
def verifyCommitment(x, vote, commitments, rx, G, h, g): everything = challengeHash(''.join(map(str,[vote] + list(chain(commitments)))), K) #alphabetize this result = commit(Bn.from_hex(everything), Bn.from_decimal(rx), h, g) assert(result == x)
def verifyMaskedCommitments(pm_vote_commitments, comm_pairs, tally, h, g): permuted_votes = [] for comm, unmask in zip(pm_vote_commitments, comm_pairs): permuted_votes.append(unmask[0]) assert(comm == commit(unmask[0], Bn.from_decimal(unmask[1]), h, g)) assert({str(k): v for k, v in Counter(permuted_votes).items()} == tally)
def get_sig_from_string(sig): sig = sig[1:-1] r, s = sig.split(", ") r = Bn.from_decimal(r) s = Bn.from_decimal(s) return r, s
import binascii import json import uuid import random import qrcode GROUP_ID = 713 G = EcGroup(GROUP_ID) order = G.order() h = G.generator() sleeve = "nothing_up_my_sleeve" g = G.hash_to_point(sleeve.encode('utf-8')) #secret!!! SECRET_KEY = "18469189115185335524321997938571387166948936114449139412337896248755" # NO ONE SHOULD SEE THIS LINE! sig_key = Bn.from_decimal(SECRET_KEY) kinv_rp = do_ecdsa_setup(G, sig_key) #not secret ver_key = sig_key * h def commit(a, r): return a * h + r * g def genRealCommitments(vote, k, R): real_commitment = commit(vote, R) rb = [order.random() for i in range(k)] masks = [commit(vote, R + rb[i]) for i in range(k)] return real_commitment, masks, rb