You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
2.5 KiB

  1. from hashlib import sha256
  2. # Ring Signatures
  3. # bLSAG: Back’s Linkable Spontaneous Anonymous Group signatures
  4. # A Rust implementation of this scheme can be found at:
  5. # https://github.com/arnaucube/ring-signatures-rs
  6. def hashToPoint(a):
  7. # TODO use a proper hash-to-point
  8. h = sha256((str(a)).encode('utf-8'))
  9. r = int(h.hexdigest(), 16) * g
  10. return r
  11. def hash(R, m, A, B, q):
  12. h = sha256((
  13. str(R) + str(m) + str(A) + str(B)
  14. ).encode('utf-8'))
  15. r = int(h.hexdigest(), 16)
  16. return int(mod(r, q))
  17. def print_ring(a):
  18. print("ring of c's:")
  19. for i in range(len(a)):
  20. print(i, a[i])
  21. print("")
  22. class Prover(object):
  23. def __init__(self, F, g):
  24. self.F = F # Z_p
  25. self.g = g # elliptic curve generator
  26. self.q = self.g.order() # order of group
  27. def new_key(self):
  28. self.w = int(self.F.random_element())
  29. self.K = self.g * self.w
  30. return self.K
  31. def sign(self, m, R):
  32. # determine pi (the position of signer's public key in R
  33. pi = -1
  34. for i in range(len(R)):
  35. if self.K == R[i]:
  36. pi = i
  37. break
  38. assert pi>=0
  39. a = int(self.F.random_element())
  40. r = [None] * len(R)
  41. # for i \in {1, 2, ..., n} \ {i=pi}
  42. for i in range(0, len(R)):
  43. if i==pi:
  44. continue
  45. r[i] = int(mod(int(self.F.random_element()), self.q))
  46. c = [None] * len(R)
  47. # c_{pi+1}
  48. pi1 = mod(pi + 1, len(R))
  49. c[pi1] = hash(R, m, a * self.g, hashToPoint(R[pi]) * a, self.q)
  50. key_image = self.w * hashToPoint(self.K)
  51. # do c_{i+1} from i=pi+1 to pi-1:
  52. for j in range(0, len(R)-1):
  53. i = mod(pi1+j, len(R))
  54. i1 = mod(pi1+j +1, len(R))
  55. c[i1] = hash(R, m, r[i] * self.g + c[i] * R[i], r[i] * hashToPoint(R[i]) + c[i] * key_image, self.q)
  56. # compute r_pi
  57. r[pi] = int(mod(a - c[pi] * self.w, self.q))
  58. print_ring(c)
  59. return [c[0], r]
  60. def verify(g, R, m, key_image, sig):
  61. q = g.order()
  62. c1 = sig[0]
  63. r = sig[1]
  64. assert len(R) == len(r)
  65. # check that key_image \in G (EC), by l * key_image == 0
  66. assert q * key_image == 0 # in sage 0 EC point is interpreted as (0:1:0)
  67. # for i \in 1,2,...,n
  68. c = [None] * len(R)
  69. c[0] = c1
  70. for j in range(0, len(R)):
  71. i = mod(j, len(R))
  72. i1 = mod(j+1, len(R))
  73. c[i1] = hash(R, m, r[i] * g + c[i] * R[i], r[i] * hashToPoint(R[i]) + c[i] * key_image, q)
  74. print_ring(c)
  75. assert c1 == c[0]