### Start of implementation: message 1 complete

Ian Goldberg 4 years ago
commit
6887efdc22
2 changed files with 258 additions and 0 deletions
1. 194 0
gk15.go
2. 64 0
main.go

#### + 194 - 0 gk15.go View File

 ``@@ -0,0 +1,194 @@`` ``+/*`` ``+ * An implementation of Groth and Kohlweiss, "One-out-of-Many Proofs: Or`` ``+ * How to Leak a Secret and Spend a Coin", Eurocrypt 2015`` ``+ * https://eprint.iacr.org/2014/764.pdf`` ``+ */`` ``+`` ``+package main`` ``+`` ``+import (`` ``+ "fmt"`` ``+ "go.dedis.ch/kyber"`` ``+ "go.dedis.ch/kyber/util/random"`` ``+)`` ``+`` ``+type GroupParams struct {`` ``+ /* A group of prime order */`` ``+ group kyber.Group`` ``+ /* Three generators of the group; the relative discrete logs`` ``+ * must be unknown. Commitments to a value x with randomness r`` ``+ * are x*A + r*B. Y is used to pad the list of commitments to a`` ``+ * power of 2. */`` ``+ A, B, Y kyber.Point`` ``+}`` ``+`` ``+type PubState struct {`` ``+ cl, ca, cb, cd []kyber.Point`` ``+}`` ``+`` ``+type PrivState struct {`` ``+ r, a, s, t, rho []kyber.Scalar`` ``+}`` ``+`` ``+type Proof struct {`` ``+}`` ``+`` ``+// Multiply a polynomial expressed as a slice of coefficients by the`` ``+// scalar a`` ``+func polymul(group kyber.Group, poly []kyber.Scalar, a kyber.Scalar) {`` ``+ numcoeffs := len(poly)`` ``+ for i := 0 ; i < numcoeffs ; i++ {`` ``+ poly[i] = group.Scalar().Mul(poly[i], a)`` ``+ }`` ``+}`` ``+`` ``+// Multiply a polynomial expressed as a slice of coefficients by`` ``+// the linear polynomial x+a`` ``+func polymul_xplus(group kyber.Group, poly []kyber.Scalar, a kyber.Scalar) {`` ``+ numcoeffs := len(poly)`` ``+ if !poly[numcoeffs-1].Equal(group.Scalar().Zero()) {`` ``+ panic("Degree too large in multiplication")`` ``+ }`` ``+ for i := numcoeffs-1 ; i > 0 ; i-- {`` ``+ poly[i] = group.Scalar().Add(`` ``+ group.Scalar().Mul(poly[i], a), poly[i-1])`` ``+ }`` ``+ poly[0] = group.Scalar().Mul(poly[0], a)`` ``+}`` ``+`` ``+/* Sigma protocol for one out of N commitments containing 0`` ``+ * Section 3 of https://eprint.iacr.org/2014/764.pdf`` ``+ */`` ``+func ProofStep1(params GroupParams, c []kyber.Point, ell uint32, privkey kyber.Scalar) (PubState, PrivState) {`` ``+ N := uint32(len(c))`` ``+ rand := random.New()`` ``+ group := params.group`` ``+`` ``+ // Find n := ceil(log_2(N))`` ``+ n := uint32(1)`` ``+ two_n := uint32(2) // 2^n`` ``+ for ; two_n < N ; {`` ``+ n += 1`` ``+ two_n *= 2`` ``+ }`` ``+ fmt.Printf("n = %d\n", n);`` ``+`` ``+ // We will keep the notation of the paper:`` ``+ // r, a, s, t, cl, ca, cb are 1-based,`` ``+ // c, rho, cd are 0-based. The 1-based ones, we`` ``+ // just allocate an extra array element, and never`` ``+ // use element 0.`` ``+ var pub PubState`` ``+ var priv PrivState`` ``+ priv.r = make([]kyber.Scalar, n+1)`` ``+ priv.a = make([]kyber.Scalar, n+1)`` ``+ priv.s = make([]kyber.Scalar, n+1)`` ``+ priv.t = make([]kyber.Scalar, n+1)`` ``+ priv.rho = make([]kyber.Scalar, n)`` ``+ pub.cl = make([]kyber.Point, n+1)`` ``+ pub.ca = make([]kyber.Point, n+1)`` ``+ pub.cb = make([]kyber.Point, n+1)`` ``+ pub.cd = make([]kyber.Point, n)`` ``+`` ``+ var j, k, mask uint32`` ``+ // mask = 2^k`` ``+ j = 1`` ``+ k = 0`` ``+ mask = 1`` ``+ for ; k < n ; {`` ``+ priv.r[j] = group.Scalar().Pick(rand)`` ``+ priv.a[j] = group.Scalar().Pick(rand)`` ``+ priv.s[j] = group.Scalar().Pick(rand)`` ``+ priv.t[j] = group.Scalar().Pick(rand)`` ``+ priv.rho[k] = group.Scalar().Pick(rand)`` ``+`` ``+ pub.cl[j] = group.Point().Mul(priv.r[j], params.B)`` ``+ if (ell & mask) != 0 {`` ``+ pub.cl[j] = group.Point().Add(pub.cl[j], params.A)`` ``+ }`` ``+ pub.ca[j] = group.Point().Add(`` ``+ group.Point().Mul(priv.a[j], params.A),`` ``+ group.Point().Mul(priv.s[j], params.B))`` ``+ pub.cb[j] = group.Point().Mul(priv.t[j], params.B)`` ``+ if (ell & mask) != 0 {`` ``+ pub.cb[j] = group.Point().Add(pub.cb[j],`` ``+ group.Point().Mul(priv.a[j], params.A))`` ``+ }`` ``+`` ``+ j++`` ``+ k++`` ``+ mask *= 2`` ``+ }`` ``+`` ``+ k = 0`` ``+ for ; k < n ; {`` ``+ pub.cd[k] = group.Point().Mul(priv.rho[k], params.B)`` ``+ for i := uint32(0); i < two_n; i++ {`` ``+ // Compute the coefficients of p_i`` ``+ p_i := make([]kyber.Scalar, n+1)`` ``+ p_i[0] = group.Scalar().One()`` ``+ for t := uint32(1); t <= n; t++ {`` ``+ p_i[t] = group.Scalar().Zero()`` ``+ }`` ``+`` ``+ // TODO: finish computation of p_i`` ``+ j = 1`` ``+ // jmask = 2^(j-1)`` ``+ jmask := uint32(1)`` ``+ for ; j <= n ; {`` ``+ if (i & jmask) != 0 {`` ``+ if (ell & jmask) != 0 {`` ``+ // Multiply p_i by x + a[j]`` ``+ polymul_xplus(group, p_i, priv.a[j])`` ``+ } else {`` ``+ // Multiply p_i by a[j]`` ``+ polymul(group, p_i, priv.a[j])`` ``+ }`` ``+ } else {`` ``+ negaj := group.Scalar().Neg(priv.a[j])`` ``+ if (ell & jmask) != 0 {`` ``+ // Multiply p_i by -a[j]`` ``+ polymul(group, p_i, negaj)`` ``+ } else {`` ``+ // Multiply p_i by x - a[j]`` ``+ polymul_xplus(group, p_i, negaj)`` ``+ }`` ``+ }`` ``+`` ``+ j++`` ``+ jmask *= 2`` ``+ }`` ``+`` ``+ if i == ell && !p_i[n].Equal(group.Scalar().One()) {`` ``+ panic("Leading coeff should be 1 but was not")`` ``+ }`` ``+ if i != ell && !p_i[n].Equal(group.Scalar().Zero()) {`` ``+ panic("Leading coeff should be 0 but was not")`` ``+ }`` ``+ if i < N {`` ``+ pub.cd[k] = group.Point().Add(pub.cd[k],`` ``+ group.Point().Mul(p_i[k], c[i]))`` ``+ } else {`` ``+ pub.cd[k] = group.Point().Add(pub.cd[k],`` ``+ group.Point().Mul(p_i[k], params.Y))`` ``+ }`` ``+ }`` ``+`` ``+ k++`` ``+ mask *= 2`` ``+ }`` ``+`` ``+ return pub, priv`` ``+}`` ``+`` ``+func GenChallenge(params GroupParams, pub PubState) kyber.Scalar {`` ``+ return params.group.Scalar()`` ``+}`` ``+`` ``+func ProofStep2(params GroupParams, priv PrivState, x kyber.Scalar) Proof {`` ``+ return Proof{}`` ``+}`` ``+`` ``+func Verify(params GroupParams, pub PubState, x kyber.Scalar, proof Proof) bool {`` ``+ return false`` ``+}``

#### + 64 - 0 main.go View File

 ``@@ -0,0 +1,64 @@`` ``+package main`` ``+`` ``+import (`` ``+ "fmt"`` ``+ "os"`` ``+ "strconv"`` ``+ "math/big"`` ``+ "go.dedis.ch/kyber"`` ``+ "go.dedis.ch/kyber/pairing/bn256"`` ``+ "go.dedis.ch/kyber/util/random"`` ``+)`` ``+`` ``+func main() {`` ``+ /* Command-line arg is N, the number of commitments */`` ``+ var N int`` ``+ var err error`` ``+ if len(os.Args) > 1 {`` ``+ N, err = strconv.Atoi(os.Args[1])`` ``+ if err != nil {`` ``+ panic(err)`` ``+ }`` ``+ } else {`` ``+ N = 25`` ``+ }`` ``+ if (N < 2) {`` ``+ panic("N must be at least 2")`` ``+ }`` ``+ N32 := uint32(N)`` ``+ group := bn256.NewSuite().G1()`` ``+ rand := random.New()`` ``+ params := GroupParams {`` ``+ group,`` ``+ group.Point().Pick(rand),`` ``+ group.Point().Pick(rand),`` ``+ group.Point().Pick(rand),`` ``+ }`` ``+`` ``+ // Create an array of commitments, one of which is a commitment`` ``+ // to 0`` ``+ Cs := make([]kyber.Point, N32)`` ``+`` ``+ // Which one do we know? Pick a random 0 <= ell < N`` ``+ Nbig := big.NewInt(int64(N))`` ``+ ell := uint32(random.Int(Nbig, rand).Int64())`` ``+ var privkey kyber.Scalar`` ``+ var i uint32`` ``+ for i = 0; i < N32; i++ {`` ``+ if i == ell {`` ``+ privkey = group.Scalar().Pick(rand)`` ``+ Cs[i] = group.Point().Mul(privkey, params.B)`` ``+ } else {`` ``+ Cs[i] = group.Point().Pick(rand)`` ``+ }`` ``+ }`` ``+`` ``+ pub, priv := ProofStep1(params, Cs, ell, privkey)`` ``+ x := GenChallenge(params, pub)`` ``+ proof := ProofStep2(params, priv, x)`` ``+ if Verify(params, pub, x, proof) {`` ``+ fmt.Printf("SUCCESS\n")`` ``+ } else {`` ``+ fmt.Printf("VERIFICATION FAILED\n")`` ``+ }`` ``+}``