// ShuffleDecrypt performs a shuffle and partial decyption of the given ciphertexts, producing correctness // proofs in the process func ShuffleDecrypt(suite abstract.Suite, ciphertexts []*elgamal.CipherText, pks []*elgamal.PubKey, sk *elgamal.PriKey, nonce string, position int) (*VerifiableShuffle, error) { amount := len(ciphertexts) if amount == 0 { panic("Can't shuffle 0 ciphertexts") } c1, c2 := elgamal.Unpack(ciphertexts) // The ciphertexts are encrypted against these public keys; it still includes ours // The proof of the shuffle will also be w.r.t. this public key sumpk := elgamal.SumKeys(pks[position:]) // Do the shuffle, create a proof of its correctness shuffledC1, shuffledC2, prover := shuffle.Shuffle(suite, sumpk.Base, sumpk.Key, c1, c2, suite.Cipher(nil)) shuffleProof, err := proof.HashProve(suite, "ElGamalShuffle"+nonce, suite.Cipher(nil), prover) if err != nil { return nil, err } shuffled := elgamal.Pack(shuffledC1, shuffledC2) // Do the partial decryption, create a proof of its correctness decryptionProofs, decrypted := make([][]byte, amount), make([]*elgamal.CipherText, amount) for i := range shuffledC1 { decrypted[i], decryptionProofs[i], err = sk.PartialProofDecrypt(shuffled[i], nonce) if err != nil { return nil, err } } return &VerifiableShuffle{shuffled, decrypted, decryptionProofs, shuffleProof}, nil }
func (v *stateVector) addShuffle(suite abstract.Suite, shuf *shuffler, rand abstract.Cipher) error { // Get the previous shuffle state. i := len(v.States) prev := v.States[i-1] X, Y := prev.X, prev.Dec // Compute the new base using the public keys of the remaining // servers. H := suite.Point().Null() for j := i - 1; j < shuf.N; j++ { H = suite.Point().Add(H, shuf.HH[j]) } // Do a key-shuffle. Xbar, Ybar, prover := shuffle.Shuffle(suite, nil, H, X, Y, rand) prf, err := proof.HashProve(suite, "PairShuffle", rand, prover) if err != nil { return err } // Seeded random for the decryption proof. seed := abstract.Sum(suite, prf) prfRand := suite.Cipher(seed) // Scratch space for calculations. zs := suite.Secret() zp := suite.Point() // Peel off a layer of encryption. dec := make([]abstract.Point, len(Xbar)) decPrf := make([]*decryptionProof, len(Xbar)) for j := range Xbar { // Decryption. zp.Mul(Xbar[j], shuf.h) dec[j] = suite.Point().Sub(Ybar[j], zp) // Decryption proof. t := suite.Secret().Pick(rand) T := suite.Point().Mul(Xbar[j], t) c := suite.Secret().Pick(prfRand) s := suite.Secret().Add(t, zs.Mul(c, shuf.h)) decPrf[j] = &decryptionProof{T, s} } // Append the new state to the state vector. state := &shuffleState{H, Xbar, Ybar, dec, prf, decPrf} v.States = append(v.States, state) return nil }