gk15.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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. j = 1
  125. // jmask = 2^(j-1)
  126. jmask := uint32(1)
  127. for ; j <= n ; {
  128. if (i & jmask) != 0 {
  129. if (ell & jmask) != 0 {
  130. // Multiply p_i by x + a[j]
  131. polymul_xplus(group, p_i, priv.a[j])
  132. } else {
  133. // Multiply p_i by a[j]
  134. polymul(group, p_i, priv.a[j])
  135. }
  136. } else {
  137. negaj := group.Scalar().Neg(priv.a[j])
  138. if (ell & jmask) != 0 {
  139. // Multiply p_i by -a[j]
  140. polymul(group, p_i, negaj)
  141. } else {
  142. // Multiply p_i by x - a[j]
  143. polymul_xplus(group, p_i, negaj)
  144. }
  145. }
  146. j++
  147. jmask *= 2
  148. }
  149. if i == ell && !p_i[n].Equal(group.Scalar().One()) {
  150. panic("Leading coeff should be 1 but was not")
  151. }
  152. if i != ell && !p_i[n].Equal(group.Scalar().Zero()) {
  153. panic("Leading coeff should be 0 but was not")
  154. }
  155. if i < N {
  156. pub.cd[k] = group.Point().Add(pub.cd[k],
  157. group.Point().Mul(p_i[k], c[i]))
  158. } else {
  159. pub.cd[k] = group.Point().Add(pub.cd[k],
  160. group.Point().Mul(p_i[k], params.Y))
  161. }
  162. }
  163. k++
  164. mask *= 2
  165. }
  166. return pub, priv
  167. }
  168. func GenChallenge(params GroupParams, pub PubState) kyber.Scalar {
  169. // In the interactive version, just pick a random challenge.
  170. // In the noninteractive version, this would be a hash of pub
  171. // and a message.
  172. rand := random.New()
  173. return params.group.Scalar().Pick(rand)
  174. }
  175. func ProofStep2(params GroupParams, priv PrivState, x kyber.Scalar) Proof {
  176. var proof Proof
  177. n := uint32(len(priv.rho))
  178. group := params.group
  179. proof.f = make([]kyber.Scalar, n+1)
  180. proof.za = make([]kyber.Scalar, n+1)
  181. proof.zb = make([]kyber.Scalar, n+1)
  182. var j, mask uint32
  183. // mask = 2^(j-1)
  184. j = 1
  185. mask = 1
  186. for ; j <= n ; {
  187. if (priv.ell & mask) != 0 {
  188. proof.f[j] = group.Scalar().Add(x, priv.a[j])
  189. } else {
  190. proof.f[j] = priv.a[j].Clone()
  191. }
  192. proof.za[j] = group.Scalar().Add(
  193. group.Scalar().Mul(x, priv.r[j]), priv.s[j])
  194. proof.zb[j] = group.Scalar().Add(
  195. group.Scalar().Mul(
  196. group.Scalar().Sub(x, proof.f[j]),
  197. priv.r[j]),
  198. priv.t[j])
  199. j++
  200. mask *= 2
  201. }
  202. proof.zd = group.Scalar().Zero()
  203. k := uint32(0)
  204. xk := group.Scalar().One() // x^k
  205. for ; k < n ; {
  206. proof.zd = group.Scalar().Sub(proof.zd,
  207. group.Scalar().Mul(priv.rho[k], xk))
  208. k++
  209. xk = group.Scalar().Mul(xk, x)
  210. }
  211. // At this point, xk = x^n
  212. proof.zd = group.Scalar().Add(proof.zd,
  213. group.Scalar().Mul(priv.privkey, xk))
  214. return proof
  215. }
  216. // We assume that the checks that the Points are in fact in the right
  217. // group and the Scalars are in the right range were done at the time
  218. // the PubState and Proof structures were populated from data received
  219. // over the network. This function checks the relations between the
  220. // elements.
  221. func Verify(params GroupParams, c []kyber.Point, pub PubState, x kyber.Scalar, proof Proof) bool {
  222. N := uint32(len(c))
  223. group := params.group
  224. // Find n := ceil(log_2(N))
  225. n := uint32(1)
  226. two_n := uint32(2) // 2^n
  227. for ; two_n < N ; {
  228. n += 1
  229. two_n *= 2
  230. }
  231. // Check that the lengths of the arrays are correct
  232. if len(pub.cl) != int(n+1) || len(pub.ca) != int(n+1) ||
  233. len(pub.cb) != int(n+1) ||
  234. len(pub.cd) != int(n) ||
  235. len(proof.f) != int(n+1) ||
  236. len(proof.za) != int(n+1) ||
  237. len(proof.zb) != int(n+1) {
  238. fmt.Printf("Inputs not of the correct length\n")
  239. return false
  240. }
  241. for j := uint32(1) ; j <= n ; j++ {
  242. lhs1 := group.Point().Add(group.Point().Mul(x, pub.cl[j]),
  243. pub.ca[j])
  244. rhs1 := group.Point().Add(
  245. group.Point().Mul(proof.f[j], params.A),
  246. group.Point().Mul(proof.za[j], params.B))
  247. if !lhs1.Equal(rhs1) {
  248. fmt.Printf("Failed equality check 1\n")
  249. return false
  250. }
  251. lhs2 := group.Point().Add(
  252. group.Point().Mul(
  253. group.Scalar().Sub(x, proof.f[j]),
  254. pub.cl[j]),
  255. pub.cb[j])
  256. rhs2 := group.Point().Mul(proof.zb[j], params.B)
  257. if !lhs2.Equal(rhs2) {
  258. fmt.Printf("Failed equality check 2\n")
  259. return false
  260. }
  261. }
  262. lhs := group.Point().Null()
  263. for i := uint32(0) ; i < two_n ; i++ {
  264. fprod := group.Scalar().One()
  265. j := uint32(1)
  266. mask := uint32(1) // mask = 2^(j-1)
  267. for ; j <= n ; {
  268. if (i & mask) != 0 {
  269. fprod = group.Scalar().Mul(fprod,
  270. proof.f[j])
  271. } else {
  272. fprod = group.Scalar().Mul(fprod,
  273. group.Scalar().Sub(x,
  274. proof.f[j]))
  275. }
  276. j++
  277. mask *= 2
  278. }
  279. if i < N {
  280. lhs = group.Point().Add(lhs,
  281. group.Point().Mul(fprod, c[i]))
  282. } else {
  283. lhs = group.Point().Add(lhs,
  284. group.Point().Mul(fprod, params.Y))
  285. }
  286. }
  287. rhs := group.Point().Mul(proof.zd, params.B)
  288. k := uint32(0)
  289. xk := group.Scalar().One() // xk = x^k
  290. for ; k < n ; {
  291. rhs = group.Point().Add(rhs,
  292. group.Point().Mul(xk, pub.cd[k]))
  293. k++
  294. xk = group.Scalar().Mul(xk, x)
  295. }
  296. if !lhs.Equal(rhs) {
  297. fmt.Printf("Failed equality check\n")
  298. return false
  299. }
  300. return true
  301. }