vrf.py 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. from ouroboros.logger import Logger
  2. import random as rnd
  3. from tate_bilinear_pairing import eta, ecc
  4. from ouroboros.utils import inverse_of
  5. from ouroboros.utils import vrf_hash
  6. eta.init(369)
  7. '''
  8. verify signature
  9. @param x: signed messaged
  10. @param y: signature
  11. @param pi: [inf, x, y] proof components
  12. @param pk: [inf, x, y] public key components of the prover
  13. @param g: group base
  14. '''
  15. def verify(x, y, pi, pk_raw, g):
  16. gx = ecc.scalar_mult(x, g)
  17. rhs = eta.pairing(*ecc.scalar_mult(1,g)[1:], *pi[1:])
  18. if not y == rhs:
  19. print(f"y: {y}, rhs: {rhs}")
  20. return False
  21. gxs = ecc.add(gx, pk_raw)
  22. lhs = eta.pairing(*gxs[1:], *pi[1:])
  23. rhs = eta.pairing(*ecc.scalar_mult(1, g)[1:], *ecc.scalar_mult(1, g)[1:])
  24. if not lhs==rhs:
  25. print(f"proposed {x}, {y}, {pi}, {pk_raw}, {g}")
  26. print(f"lhs: {lhs},\nrhs: {rhs}")
  27. return False
  28. return True
  29. class VRF(object):
  30. '''
  31. verifiable random function implementation
  32. '''
  33. def __init__(self, seed):
  34. self.log = Logger(self)
  35. self.order = ecc.order()
  36. #TODO use ecc to gen sk
  37. sk = vrf_hash(seed) % self.order
  38. g = ecc.gen()
  39. pk = ecc.scalar_mult(sk, g)
  40. #
  41. self.pk = pk
  42. self.sk = sk
  43. self.g=g
  44. '''
  45. short signature without random oracle
  46. @param x: message to be signed
  47. @return y (the signature), pi (the proof)
  48. '''
  49. def sign(self, x):
  50. pi = ecc.scalar_mult(inverse_of(x+self.sk, self.order), self.g)
  51. y = eta.pairing(*self.g[1:], *pi[1:])
  52. self.log.highlight(f"signing slot {x}\nsigma {y}\nproof {pi}\npk {self.pk} \nbase {self.g}")
  53. return (y, pi)
  54. def update(self, pk, sk, g):
  55. self.pk = pk
  56. self.sk = sk
  57. self.g = g
  58. '''
  59. verify signature
  60. @param x: signed messaged
  61. @param y: signature
  62. @param pi: [inf, x, y] proof components
  63. '''
  64. def verify(self, x, y, pi):
  65. gx = ecc.scalar_mult(x, self.g)
  66. rhs = eta.pairing(*ecc.scalar_mult(1,self.g)[1:], *pi[1:])
  67. if not y == rhs:
  68. print(f"y: {y}, rhs: {rhs}")
  69. return False
  70. gxs = ecc.add(gx, self.pk)
  71. lhs = eta.pairing(*gxs[1:], *pi[1:])
  72. rhs = eta.pairing(*ecc.scalar_mult(1, self.g)[1:], *ecc.scalar_mult(1, self.g)[1:])
  73. if not lhs==rhs:
  74. print(f"proposed {x}, {y}, {pi}, {self.pk}, {self.g}")
  75. print(f"lhs: {lhs},\nrhs: {rhs}")
  76. return False
  77. return True