gk15.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. * An implementation of Groth and Kohlweiss, "One-out-of-Many Proofs: Or
  3. * How to Leak a Secret and Spend a Coin", Eurocrypt 2015
  4. * https://eprint.iacr.org/2014/764.pdf
  5. */
  6. package main
  7. import (
  8. "fmt"
  9. "go.dedis.ch/kyber"
  10. "go.dedis.ch/kyber/util/random"
  11. )
  12. type GroupParams struct {
  13. /* A group of prime order */
  14. group kyber.Group
  15. /* Three generators of the group; the relative discrete logs
  16. * must be unknown. Commitments to a value x with randomness r
  17. * are x*A + r*B. Y is used to pad the list of commitments to a
  18. * power of 2. */
  19. A, B, Y kyber.Point
  20. }
  21. type PubState struct {
  22. cl, ca, cb, cd []kyber.Point
  23. }
  24. type PrivState struct {
  25. r, a, s, t, rho []kyber.Scalar
  26. ell uint32
  27. privkey kyber.Scalar
  28. }
  29. type Proof struct {
  30. f, za, zb []kyber.Scalar
  31. zd kyber.Scalar
  32. }
  33. // Multiply a polynomial expressed as a slice of coefficients by the
  34. // scalar a
  35. func polymul(group kyber.Group, poly []kyber.Scalar, a kyber.Scalar) {
  36. numcoeffs := len(poly)
  37. for i := 0 ; i < numcoeffs ; i++ {
  38. poly[i] = group.Scalar().Mul(poly[i], a)
  39. }
  40. }
  41. // Multiply a polynomial expressed as a slice of coefficients by
  42. // the linear polynomial x+a
  43. func polymul_xplus(group kyber.Group, poly []kyber.Scalar, a kyber.Scalar) {
  44. numcoeffs := len(poly)
  45. if !poly[numcoeffs-1].Equal(group.Scalar().Zero()) {
  46. panic("Degree too large in multiplication")
  47. }
  48. for i := numcoeffs-1 ; i > 0 ; i-- {
  49. poly[i] = group.Scalar().Add(
  50. group.Scalar().Mul(poly[i], a), poly[i-1])
  51. }
  52. poly[0] = group.Scalar().Mul(poly[0], a)
  53. }
  54. /* Sigma protocol for one out of N commitments containing 0
  55. * Section 3 of https://eprint.iacr.org/2014/764.pdf
  56. */
  57. func ProofStep1(params GroupParams, c []kyber.Point, ell uint32, privkey kyber.Scalar) (PubState, PrivState) {
  58. N := uint32(len(c))
  59. rand := random.New()
  60. group := params.group
  61. // Find n := ceil(log_2(N))
  62. n := uint32(1)
  63. two_n := uint32(2) // 2^n
  64. for ; two_n < N ; {
  65. n += 1
  66. two_n *= 2
  67. }
  68. fmt.Printf("n = %d\n", n);
  69. // We will keep the notation of the paper:
  70. // r, a, s, t, cl, ca, cb are 1-based,
  71. // c, rho, cd are 0-based. The 1-based ones, we
  72. // just allocate an extra array element, and never
  73. // use element 0.
  74. var pub PubState
  75. var priv PrivState
  76. priv.r = make([]kyber.Scalar, n+1)
  77. priv.a = make([]kyber.Scalar, n+1)
  78. priv.s = make([]kyber.Scalar, n+1)
  79. priv.t = make([]kyber.Scalar, n+1)
  80. priv.rho = make([]kyber.Scalar, n)
  81. priv.ell = ell
  82. priv.privkey = privkey.Clone()
  83. pub.cl = make([]kyber.Point, n+1)
  84. pub.ca = make([]kyber.Point, n+1)
  85. pub.cb = make([]kyber.Point, n+1)
  86. pub.cd = make([]kyber.Point, n)
  87. var j, k, mask uint32
  88. // mask = 2^k
  89. j = 1
  90. k = 0
  91. mask = 1
  92. for ; k < n ; {
  93. priv.r[j] = group.Scalar().Pick(rand)
  94. priv.a[j] = group.Scalar().Pick(rand)
  95. priv.s[j] = group.Scalar().Pick(rand)
  96. priv.t[j] = group.Scalar().Pick(rand)
  97. priv.rho[k] = group.Scalar().Pick(rand)
  98. pub.cl[j] = group.Point().Mul(priv.r[j], params.B)
  99. if (ell & mask) != 0 {
  100. pub.cl[j] = group.Point().Add(pub.cl[j], params.A)
  101. }
  102. pub.ca[j] = group.Point().Add(
  103. group.Point().Mul(priv.a[j], params.A),
  104. group.Point().Mul(priv.s[j], params.B))
  105. pub.cb[j] = group.Point().Mul(priv.t[j], params.B)
  106. if (ell & mask) != 0 {
  107. pub.cb[j] = group.Point().Add(pub.cb[j],
  108. group.Point().Mul(priv.a[j], params.A))
  109. }
  110. j++
  111. k++
  112. mask *= 2
  113. }
  114. k = 0
  115. for ; k < n ; {
  116. pub.cd[k] = group.Point().Mul(priv.rho[k], params.B)
  117. for i := uint32(0); i < two_n; i++ {
  118. // Compute the coefficients of p_i
  119. p_i := make([]kyber.Scalar, n+1)
  120. p_i[0] = group.Scalar().One()
  121. for t := uint32(1); t <= n; t++ {
  122. p_i[t] = group.Scalar().Zero()
  123. }
  124. // TODO: finish computation of p_i
  125. j = 1
  126. // jmask = 2^(j-1)
  127. jmask := uint32(1)
  128. for ; j <= n ; {
  129. if (i & jmask) != 0 {
  130. if (ell & jmask) != 0 {
  131. // Multiply p_i by x + a[j]
  132. polymul_xplus(group, p_i, priv.a[j])
  133. } else {
  134. // Multiply p_i by a[j]
  135. polymul(group, p_i, priv.a[j])
  136. }
  137. } else {
  138. negaj := group.Scalar().Neg(priv.a[j])
  139. if (ell & jmask) != 0 {
  140. // Multiply p_i by -a[j]
  141. polymul(group, p_i, negaj)
  142. } else {
  143. // Multiply p_i by x - a[j]
  144. polymul_xplus(group, p_i, negaj)
  145. }
  146. }
  147. j++
  148. jmask *= 2
  149. }
  150. if i == ell && !p_i[n].Equal(group.Scalar().One()) {
  151. panic("Leading coeff should be 1 but was not")
  152. }
  153. if i != ell && !p_i[n].Equal(group.Scalar().Zero()) {
  154. panic("Leading coeff should be 0 but was not")
  155. }
  156. if i < N {
  157. pub.cd[k] = group.Point().Add(pub.cd[k],
  158. group.Point().Mul(p_i[k], c[i]))
  159. } else {
  160. pub.cd[k] = group.Point().Add(pub.cd[k],
  161. group.Point().Mul(p_i[k], params.Y))
  162. }
  163. }
  164. k++
  165. mask *= 2
  166. }
  167. return pub, priv
  168. }
  169. func GenChallenge(params GroupParams, pub PubState) kyber.Scalar {
  170. // In the interactive version, just pick a random challenge.
  171. // In the noninteractive version, this would be a hash of pub
  172. // and a message.
  173. rand := random.New()
  174. return params.group.Scalar().Pick(rand)
  175. }
  176. func ProofStep2(params GroupParams, priv PrivState, x kyber.Scalar) Proof {
  177. var proof Proof
  178. n := uint32(len(priv.rho))
  179. group := params.group
  180. proof.f = make([]kyber.Scalar, n+1)
  181. proof.za = make([]kyber.Scalar, n+1)
  182. proof.zb = make([]kyber.Scalar, n+1)
  183. var j, mask uint32
  184. // mask = 2^(j-1)
  185. j = 1
  186. mask = 1
  187. for ; j <= n ; {
  188. if (priv.ell & mask) != 0 {
  189. proof.f[j] = group.Scalar().Add(x, priv.a[j])
  190. } else {
  191. proof.f[j] = priv.a[j].Clone()
  192. }
  193. proof.za[j] = group.Scalar().Add(
  194. group.Scalar().Mul(x, priv.r[j]), priv.s[j])
  195. proof.zb[j] = group.Scalar().Add(
  196. group.Scalar().Mul(
  197. group.Scalar().Sub(x, proof.f[j]),
  198. priv.r[j]),
  199. priv.t[j])
  200. j++
  201. mask *= 2
  202. }
  203. proof.zd = group.Scalar().Zero()
  204. k := uint32(0)
  205. xk := group.Scalar().One() // x^k
  206. for ; k < n ; {
  207. proof.zd = group.Scalar().Sub(proof.zd,
  208. group.Scalar().Mul(priv.rho[k], xk))
  209. k++
  210. xk = group.Scalar().Mul(xk, x)
  211. }
  212. // At this point, xk = x^n
  213. proof.zd = group.Scalar().Add(proof.zd,
  214. group.Scalar().Mul(priv.privkey, xk))
  215. return proof
  216. }
  217. func Verify(params GroupParams, pub PubState, x kyber.Scalar, proof Proof) bool {
  218. return false
  219. }