Beispiel #1
0
// 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
}
Beispiel #2
0
// ProofDecrypt decrypts the specified ciphertext, and include a proof that we did this correctly
// (i.e., that the ciphertext was indeed an encryption of the plaintext).
func (sk *PriKey) ProofDecrypt(ciphertext *CipherText, nonce string) (abstract.Point, []byte, error) {
	plaintext := sk.Decrypt(ciphertext)
	c2m := sk.Suite.Point().Sub(ciphertext.C2, plaintext)

	predicate := getProofPredicate()
	secret := map[string]abstract.Secret{"x": sk.Secret}
	public := map[string]abstract.Point{"h": sk.Key, "g": sk.Base, "c2/m": c2m, "c1": ciphertext.C1}

	prover := predicate.Prover(sk.Suite, secret, public, nil)
	proof, err := proof.HashProve(sk.Suite, "ElGamalDecryption"+nonce, sk.Suite.Cipher(nil), prover)

	return plaintext, proof, err
}
Beispiel #3
0
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
}
Beispiel #4
0
func TestShuffle(suite abstract.Suite, k int, N int) {

	rand := suite.Cipher(abstract.RandomKey)

	// Create a "server" private/public keypair
	h := suite.Scalar().Pick(rand)
	H := suite.Point().Mul(nil, h)

	// Create a set of ephemeral "client" keypairs to shuffle
	c := make([]abstract.Scalar, k)
	C := make([]abstract.Point, k)
	//	fmt.Println("\nclient keys:")
	for i := 0; i < k; i++ {
		c[i] = suite.Scalar().Pick(rand)
		C[i] = suite.Point().Mul(nil, c[i])
		//		fmt.Println(" "+C[i].String())
	}

	// ElGamal-encrypt all these keypairs with the "server" key
	X := make([]abstract.Point, k)
	Y := make([]abstract.Point, k)
	r := suite.Scalar() // temporary
	for i := 0; i < k; i++ {
		r.Pick(rand)
		X[i] = suite.Point().Mul(nil, r)
		Y[i] = suite.Point().Mul(H, r) // ElGamal blinding factor
		Y[i].Add(Y[i], C[i])           // Encrypted client public key
	}

	// Repeat only the actual shuffle portion for test purposes.
	for i := 0; i < N; i++ {

		// Do a key-shuffle
		Xbar, Ybar, prover := Shuffle(suite, nil, H, X, Y, rand)
		prf, err := proof.HashProve(suite, "PairShuffle", rand, prover)
		if err != nil {
			panic("Shuffle proof failed: " + err.Error())
		}
		//fmt.Printf("proof:\n%s\n",hex.Dump(prf))

		// Check it
		verifier := Verifier(suite, nil, H, X, Y, Xbar, Ybar)
		err = proof.HashVerify(suite, "PairShuffle", verifier, prf)
		if err != nil {
			panic("Shuffle verify failed: " + err.Error())
		}
	}
}
Beispiel #5
0
/* Create a blameProof that the Dealer maliciously constructed a shared secret.
 * This should be called if verifyShare fails due to the public polynomial
 * check failing. If it failed for other reasons (such as a bad index) it is not
 * advised to call this function since the share might actually be valid.
 *
 * Arguments
 *    i         = the index of the malicious shared secret
 *    gKeyPair  = the long term key pair of the insurer of share i
 *
 * Return
 *   A blameProof that the Dealer is malicious or nil if an error occurs
 *   An error object denoting the status of the blameProof construction
 *
 * TODO: Consider whether it is worthwile to produce some form of blame if
 *       the Dealer gives an invalid index.
 */
func (p *Deal) blame(i int, gKeyPair *config.KeyPair) (*blameProof, error) {
	diffieKey := p.suite.Point().Mul(p.pubKey, gKeyPair.Secret)
	insurerSig := p.sign(i, gKeyPair, sigBlameMsg)

	choice := make(map[proof.Predicate]int)
	pred := proof.Rep("D", "x", "P")
	choice[pred] = 1
	rand := p.suite.Cipher(abstract.RandomKey)
	sval := map[string]abstract.Secret{"x": gKeyPair.Secret}
	pval := map[string]abstract.Point{"D": diffieKey, "P": p.pubKey}
	prover := pred.Prover(p.suite, sval, pval, choice)
	proof, err := proof.HashProve(p.suite, protocolName, rand, prover)
	if err != nil {
		return nil, err
	}
	return new(blameProof).init(p.suite, diffieKey, proof, insurerSig), nil
}
Beispiel #6
0
// getCipherText is a helper function that, given the group elements, secrets, and choice,
// constructs the proof and ciphertext.
func (u *User) getCipherText(data *Data, msgs []abstract.Point, slot int, choice int,
	secrets map[string]abstract.Secret) (*UserCipherText, error) {

	var suite = crypto.Suite
	amount := len(msgs)

	// Get the statement we will prove
	pred := GetUserPredicate(amount)
	proofchoice := map[proof.Predicate]int{pred: choice}

	// Get the group elements occuring in the statement
	points := u.getProofPoints(data, msgs, slot)

	// Prove it and return
	prover := pred.Prover(suite, secrets, points, proofchoice)
	prf, err := proof.HashProve(suite, "VerdictUserCipher"+data.Nonce, suite.Cipher(nil), prover)

	return &UserCipherText{Points: msgs, Proof: prf, Index: u.Index, Slot: slot}, err
}
Beispiel #7
0
// GetCiphertext constructs a notary ciphertext along with the correctness proof.
func (n *Notary) GetCiphertext(data *Data, amount int) (*NotaryCipherText, error) {
	var suite = crypto.Suite
	msgs := make([]abstract.Point, amount)

	// Construct the secret and points
	secrets := map[string]abstract.Secret{"r_j": n.secretSum}
	points := map[string]abstract.Point{"R_j": n.commitmentsSum, "g_hat": crypto.Generator}

	for l := 0; l < amount; l++ {
		neggl := suite.Point().Neg(data.getGenerator(l))
		msgs[l] = suite.Point().Mul(neggl, n.secretSum)
		points["-g_"+strconv.Itoa(l)] = neggl
		points["S_j,"+strconv.Itoa(l)] = msgs[l]
	}

	// Construct the proof
	pred := getNotaryPredicate(amount)
	prover := pred.Prover(suite, secrets, points, nil)
	prf, err := proof.HashProve(suite, "VerdictNotaryCipher"+data.Nonce, crypto.Suite.Cipher(nil), prover)

	return &NotaryCipherText{Points: msgs, Proof: prf, Index: n.Index}, err
}
Beispiel #8
0
func (s *Server) shuffleKeys(_ uint64) {
	keys := <-s.keyShuffleChan

	serversLeft := len(s.servers) - s.id

	Xss := make([][]abstract.Point, serversLeft)
	Yss := make([][]abstract.Point, serversLeft)
	for i := range Xss {
		Xss[i] = make([]abstract.Point, s.totalClients)
		Yss[i] = make([]abstract.Point, s.totalClients)
		for j := range Xss[i] {
			Xss[i][j] = UnmarshalPoint(s.suite, keys.Xss[i+1][j])
			Yss[i][j] = UnmarshalPoint(s.suite, keys.Yss[i+1][j])
		}
	}

	Xbarss := make([][]abstract.Point, serversLeft)
	Ybarss := make([][]abstract.Point, serversLeft)
	decss := make([][]abstract.Point, serversLeft)
	prfs := make([][]byte, serversLeft)

	var shuffleWG sync.WaitGroup
	for i := 0; i < serversLeft; i++ {
		shuffleWG.Add(1)
		go func(i int, pk abstract.Point) {
			defer shuffleWG.Done()
			//only one chunk
			rand := s.suite.Cipher(abstract.RandomKey)
			var prover proof.Prover
			var err error
			Xbarss[i], Ybarss[i], prover = Shuffle(s.pi, s.g, nil, pk, Xss[i], Yss[i], rand)
			prfs[i], err = proof.HashProve(s.suite, "PairShuffle", rand, prover)
			if err != nil {
				log.Fatal("Shuffle proof failed: " + err.Error())
			}
			var decWG sync.WaitGroup
			decss[i] = make([]abstract.Point, s.totalClients)
			for j := range decss[i] {
				decWG.Add(1)
				go func(i int, j int) {
					defer decWG.Done()
					decss[i][j] = Decrypt(s.g, Xbarss[i][j], Ybarss[i][j], s.sk)
				}(i, j)
			}
			decWG.Wait()

		}(i, s.nextPks[i])
	}
	shuffleWG.Wait()

	//whatever is at index 0 belongs to me
	for i := range decss[0] {
		s.keys[i] = MarshalPoint(decss[0][i])
	}

	ik := InternalKey{
		Xss: make([][][]byte, serversLeft),
		Yss: make([][][]byte, serversLeft),
		SId: s.id,

		Ybarss: make([][][]byte, serversLeft),
		Proofs: prfs,
		Keys:   make([][]byte, serversLeft),
	}

	for i := range ik.Xss {
		ik.Xss[i] = make([][]byte, s.totalClients)
		ik.Yss[i] = make([][]byte, s.totalClients)
		ik.Ybarss[i] = make([][]byte, s.totalClients)
		for j := range ik.Xss[i] {
			ik.Xss[i][j] = MarshalPoint(Xbarss[i][j])
			if i == 0 {
				//i == 0 is my point, so don't pass it to next person
				ik.Yss[i][j] = MarshalPoint(s.g.Point().Base())
			} else {
				ik.Yss[i][j] = MarshalPoint(decss[i][j])
			}
			ik.Ybarss[i][j] = MarshalPoint(Ybarss[i][j])
		}
		ik.Keys[i] = s.nextPksBin[i]
	}

	var wg sync.WaitGroup
	for _, rpcServer := range s.rpcServers {
		wg.Add(1)
		go func(rpcServer *rpc.Client) {
			defer wg.Done()
			err := rpcServer.Call("Server.ShareServerKeys", &ik, nil)
			if err != nil {
				log.Fatal("Failed uploading shuffled and decoded blocks: ", err)
			}
		}(rpcServer)
	}
	wg.Wait()
}
func handleRoundEnd(params map[string]interface{}) {
	keyList := util.ProtobufDecodePointList(params["keys"].([]byte))
	size := len(keyList)
	byteValList := make([][]byte, size)
	if _, ok := params["is_start"]; ok {
		intValList := params["vals"].([]int)
		// The request is sent by coordinator, deserialize the data part
		for i := 0; i < len(intValList); i++ {
			byteValList[i] = util.IntToByte(intValList[i])
		}
	} else {
		// verify neff shuffle if needed
		verifyNeffShuffle(params)
		// deserialize data part
		byteArr := params["vals"].([]util.ByteArray)
		for i := 0; i < len(byteArr); i++ {
			byteValList[i] = byteArr[i].Arr
		}
	}

	rand1 := anonServer.Suite.Cipher([]byte("example"))
	// Create a public/private keypair (X[mine],x)
	X := make([]abstract.Point, 1)
	X[0] = anonServer.PublicKey

	newKeys := make([]abstract.Point, size)
	newVals := make([][]byte, size)
	for i := 0; i < size; i++ {
		// decrypt the public key
		newKeys[i] = anonServer.KeyMap[keyList[i].String()]
		// encrypt the reputation using ElGamal algorithm
		C := anon.Encrypt(anonServer.Suite, rand1, byteValList[i], anon.Set(X), false)
		newVals[i] = C
	}
	byteNewKeys := util.ProtobufEncodePointList(newKeys)

	// type is []ByteArr
	byteNewVals := util.SerializeTwoDimensionArray(newVals)

	if size <= 1 {
		// no need to shuffle, just send the package to next server
		pm := map[string]interface{}{
			"keys": byteNewKeys,
			"vals": byteNewVals,
		}
		event := &proto.Event{proto.ROUND_END, pm}
		util.Send(anonServer.Socket, anonServer.PreviousHop, util.Encode(event))
		// reset RoundKey and key map
		anonServer.Roundkey = anonServer.Suite.Secret().Pick(random.Stream)
		anonServer.KeyMap = make(map[string]abstract.Point)
		return
	}

	Xori := make([]abstract.Point, len(newVals))
	for i := 0; i < size; i++ {
		Xori[i] = anonServer.Suite.Point().Mul(nil, anonServer.PrivateKey)
	}
	byteOri := util.ProtobufEncodePointList(Xori)

	rand := anonServer.Suite.Cipher(abstract.RandomKey)
	// *** perform neff shuffle here ***
	Xbar, Ybar, _, Ytmp, prover := neffShuffle(Xori, newKeys, rand)
	prf, err := proof.HashProve(anonServer.Suite, "PairShuffle", rand, prover)
	util.CheckErr(err)

	// this is the shuffled key
	finalKeys := convertToOrigin(Ybar, Ytmp)
	finalVals := rebindReputation(newKeys, newVals, finalKeys)

	// send data to the next server
	byteXbar := util.ProtobufEncodePointList(Xbar)
	byteYbar := util.ProtobufEncodePointList(Ybar)
	byteFinalKeys := util.ProtobufEncodePointList(finalKeys)
	byteFinalVals := util.SerializeTwoDimensionArray(finalVals)
	bytePublicKey, _ := anonServer.PublicKey.MarshalBinary()
	// prev keys means the key before shuffle
	pm := map[string]interface{}{
		"xbar":       byteXbar,
		"ybar":       byteYbar,
		"keys":       byteFinalKeys,
		"vals":       byteFinalVals,
		"proof":      prf,
		"prev_keys":  byteOri,
		"prev_vals":  byteNewKeys,
		"shuffled":   true,
		"public_key": bytePublicKey,
	}
	event := &proto.Event{proto.ROUND_END, pm}
	util.Send(anonServer.Socket, anonServer.PreviousHop, util.Encode(event))

	// reset RoundKey and key map
	anonServer.Roundkey = anonServer.Suite.Secret().Pick(random.Stream)
	anonServer.KeyMap = make(map[string]abstract.Point)
}
func handleAnnouncement(params map[string]interface{}) {
	var g abstract.Point = nil
	keyList := util.ProtobufDecodePointList(params["keys"].([]byte))
	valList := params["vals"].([]util.ByteArray)
	size := len(keyList)

	if val, ok := params["g"]; ok {
		// contains g
		byteG := val.([]byte)
		g = anonServer.Suite.Point()
		g.UnmarshalBinary(byteG)
		g = anonServer.Suite.Point().Mul(g, anonServer.Roundkey)
		// verify the previous shuffle
		verifyNeffShuffle(params)
	} else {
		g = anonServer.Suite.Point().Mul(nil, anonServer.Roundkey)
	}

	X1 := make([]abstract.Point, 1)
	X1[0] = anonServer.PublicKey

	newKeys := make([]abstract.Point, size)
	newVals := make([][]byte, size)
	for i := 0; i < len(keyList); i++ {
		// encrypt the public key using modPow
		newKeys[i] = anonServer.Suite.Point().Mul(keyList[i], anonServer.Roundkey)
		// decrypt the reputation using ElGamal algorithm
		MM, err := anon.Decrypt(anonServer.Suite, valList[i].Arr, anon.Set(X1), 0, anonServer.PrivateKey, false)
		util.CheckErr(err)
		newVals[i] = MM
		// update key map
		anonServer.KeyMap[newKeys[i].String()] = keyList[i]
	}
	byteNewKeys := util.ProtobufEncodePointList(newKeys)
	byteNewVals := util.SerializeTwoDimensionArray(newVals)
	byteG, err := g.MarshalBinary()
	util.CheckErr(err)

	if size <= 1 {
		// no need to shuffle, just send the package to next server
		pm := map[string]interface{}{
			"keys": byteNewKeys,
			"vals": byteNewVals,
			"g":    byteG,
		}
		event := &proto.Event{proto.ANNOUNCEMENT, pm}
		util.Send(anonServer.Socket, anonServer.NextHop, util.Encode(event))
		return
	}

	Xori := make([]abstract.Point, len(newVals))
	for i := 0; i < size; i++ {
		Xori[i] = anonServer.Suite.Point().Mul(nil, anonServer.PrivateKey)
	}
	byteOri := util.ProtobufEncodePointList(Xori)

	rand := anonServer.Suite.Cipher(abstract.RandomKey)
	// *** perform neff shuffle here ***
	Xbar, Ybar, _, Ytmp, prover := neffShuffle(Xori, newKeys, rand)
	prf, err := proof.HashProve(anonServer.Suite, "PairShuffle", rand, prover)
	util.CheckErr(err)

	// this is the shuffled key
	finalKeys := convertToOrigin(Ybar, Ytmp)
	finalVals := rebindReputation(newKeys, newVals, finalKeys)

	// send data to the next server
	byteXbar := util.ProtobufEncodePointList(Xbar)
	byteYbar := util.ProtobufEncodePointList(Ybar)
	byteFinalKeys := util.ProtobufEncodePointList(finalKeys)
	byteFinalVals := util.SerializeTwoDimensionArray(finalVals)
	bytePublicKey, _ := anonServer.PublicKey.MarshalBinary()
	// prev keys means the key before shuffle
	pm := map[string]interface{}{
		"xbar":       byteXbar,
		"ybar":       byteYbar,
		"keys":       byteFinalKeys,
		"vals":       byteFinalVals,
		"proof":      prf,
		"prev_keys":  byteOri,
		"prev_vals":  byteNewKeys,
		"shuffled":   true,
		"public_key": bytePublicKey,
		"g":          byteG,
	}
	event := &proto.Event{proto.ANNOUNCEMENT, pm}
	util.Send(anonServer.Socket, anonServer.NextHop, util.Encode(event))
}