vrf.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. from logger import Logger
  2. import random as rnd
  3. from tate_bilinear_pairing import eta, ecc
  4. eta.init(369)
  5. def extended_euclidean_algorithm(a, b):
  6. """
  7. Returns a three-tuple (gcd, x, y) such that
  8. a * x + b * y == gcd, where gcd is the greatest
  9. common divisor of a and b.
  10. This function implements the extended Euclidean
  11. algorithm and runs in O(log b) in the worst case.
  12. """
  13. s, old_s = 0, 1
  14. t, old_t = 1, 0
  15. r, old_r = b, a
  16. while r != 0:
  17. quotient = old_r // r
  18. old_r, r = r, old_r - quotient * r
  19. old_s, s = s, old_s - quotient * s
  20. old_t, t = t, old_t - quotient * t
  21. return old_r, old_s, old_t
  22. def inverse_of(n, p):
  23. """
  24. Returns the multiplicative inverse of
  25. n modulo p.
  26. This function returns an integer m such that
  27. (n * m) % p == 1.
  28. """
  29. gcd, x, y = extended_euclidean_algorithm(n, p)
  30. assert (n * x + p * y) % p == gcd
  31. if gcd != 1:
  32. # Either n is 0, or p is not a prime number.
  33. raise ValueError(
  34. '{} has no multiplicative inverse '
  35. 'modulo {}'.format(n, p))
  36. else:
  37. return x % p
  38. class VRF(object):
  39. def __init__(self):
  40. self.pk = None
  41. self.sk = None
  42. self.log = Logger(self)
  43. #TODO (res) adhoc temporary
  44. self.g = ecc.gen()
  45. self.__gen()
  46. self.order = ecc.order()
  47. def __gen(self):
  48. '''
  49. generate pk/sk
  50. '''
  51. # TODO implement that is simple sk choosing mechanism for poc;
  52. self.sk = rnd.randint(0,1000)
  53. self.pk = ecc.scalar_mult(self.sk, self.g)
  54. '''
  55. short signature without random oracle
  56. @param x: message to be signed
  57. '''
  58. def sign(self, x):
  59. pi = ecc.scalar_mult(inverse_of(x+self.sk, self.order), self.g)
  60. y = eta.pairing(*self.g[1:], *pi[1:])
  61. return (y, pi, self.g)
  62. '''
  63. verify signature
  64. @param x: signed messaged
  65. @param y: signature
  66. @param pi: [inf, x, y] proof components
  67. @param pk: [inf, x, y] public key components of the prover
  68. @param g: group base
  69. '''
  70. def verify(x, y, pi, pk_raw, g):
  71. gx = ecc.scalar_mult(x, g)
  72. #pk = ecc.scalar_mult(1, pk_raw)
  73. rhs = eta.pairing(*ecc.scalar_mult(1,g)[1:], *pi[1:])
  74. if not y == rhs:
  75. print(f"y: {y}, rhs: {rhs}")
  76. return False
  77. gxs = ecc.add(gx, pk_raw)
  78. lhs = eta.pairing(*gxs[1:], *pi[1:])
  79. rhs = eta.pairing(*ecc.scalar_mult(1, g)[1:], *ecc.scalar_mult(1, g)[1:])
  80. if not lhs==rhs:
  81. print(f"proposed {x}, {y}, {pi}, {pk_raw}, {g}")
  82. print(f"lhs: {lhs},\nrhs: {rhs}")
  83. return False
  84. return True