From 3bf1cc4a59a90a6b8d44c796f4fc67de3e5eae30 Mon Sep 17 00:00:00 2001 From: mohab Date: Sat, 29 Jan 2022 13:34:22 +0200 Subject: [PATCH] added VRF(Verifiable Random Function) --- script/research/streamlet/vrf.py | 92 ++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 script/research/streamlet/vrf.py diff --git a/script/research/streamlet/vrf.py b/script/research/streamlet/vrf.py new file mode 100644 index 000000000..72419e6f0 --- /dev/null +++ b/script/research/streamlet/vrf.py @@ -0,0 +1,92 @@ +from msilib import type_string +from logger import Logger +import random as rnd +from tate_bilinear_pairing import eta, ecc + + +def extended_euclidean_algorithm(a, b): + """ + Returns a three-tuple (gcd, x, y) such that + a * x + b * y == gcd, where gcd is the greatest + common divisor of a and b. + + This function implements the extended Euclidean + algorithm and runs in O(log b) in the worst case. + """ + s, old_s = 0, 1 + t, old_t = 1, 0 + r, old_r = b, a + + while r != 0: + quotient = old_r // r + old_r, r = r, old_r - quotient * r + old_s, s = s, old_s - quotient * s + old_t, t = t, old_t - quotient * t + + return old_r, old_s, old_t + + +def inverse_of(n, p): + """ + Returns the multiplicative inverse of + n modulo p. + + This function returns an integer m such that + (n * m) % p == 1. + """ + gcd, x, y = extended_euclidean_algorithm(n, p) + assert (n * x + p * y) % p == gcd + + if gcd != 1: + # Either n is 0, or p is not a prime number. + raise ValueError( + '{} has no multiplicative inverse ' + 'modulo {}'.format(n, p)) + else: + return x % p + + +class VRF(object): + def __init__(self): + self.pk = None + self.sk = None + self.log = Logger(self) + eta.init(rnd.randint(0,369)) + self.g = ecc.gen() + self.password='somepasskey' + self.__gen() + self.order = ecc.order() + + def __gen(self): + ''' + generate pk/sk + ''' + # TODO implement that is simple sk choosing mechanism for poc; + self.sk = rnd.randint(0,1000) + self.pk = ecc.scalar_mult(self.sk, self.g) + + def prove(self, x): + pi = ecc.scalar_mult(inverse_of(x+self.sk, self.order), self.g) + y = eta.pairing(*self.g[1:], *pi[1:]) + return (y, pi) + + ''' + @param y: signed output + @param pi: [inf, x, y] proof components + @param pk: [inf, x, y] public key components of the prover + ''' + def verify(self, x, y, pi, pk): + gx = ecc.scalar_mult(x, self.g) + pk = ecc.scalar_mult(1, pk) + rhs = eta.pairing(*ecc.scalar_mult(1,self.g)[1:], *pi[1:]) + assert(y == rhs) + gxs = ecc.add(gx, pk) + lhs = eta.pairing(*gxs[1:], *pi[1:]) + rhs = eta.pairing(*ecc.scalar_mult(1,self.g)[1:], *ecc.scalar_mult(1,self.g)[1:]) + assert(lhs==rhs) + + +vrf = VRF() +x = 2 +y, pi = vrf.prove(x) +vrf.verify(x, y, pi, vrf.pk) \ No newline at end of file