View Javadoc
1   package civitas.crypto.proof1ofl;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.springframework.beans.factory.annotation.Autowired;
7   import org.springframework.stereotype.Controller;
8   
9   import civitas.crypto.Constants;
10  import civitas.crypto.CryptoBase;
11  import civitas.crypto.algorithms.ConvertHashToBigInt;
12  import civitas.crypto.ciphertext.ElGamalCiphertext;
13  import civitas.crypto.ciphertext.ElGamalCiphertextish;
14  import civitas.crypto.ciphertextlist.CiphertextList;
15  import civitas.crypto.messagedigest.CryptoHash;
16  import civitas.crypto.parameters.ElGamalParameters;
17  import civitas.crypto.publickey.ElGamalPublicKey;
18  import civitas.crypto.reencryptfactor.ElGamalReencryptFactor;
19  import civitas.util.CivitasBigInteger;
20  
21  @Controller
22  public class ConstructElGamalProof1OfL implements Constants {
23  	@Autowired
24  	CryptoBase cryptoBase;
25  
26  	@Autowired
27  	CryptoHash cryptoHash;
28  
29  	@Autowired
30  	private ConvertHashToBigInt convertHashToBigInt;
31  
32  	public ElGamalProof1OfL apply(
33  			final ElGamalPublicKey key,
34  			final CiphertextList ciphertexts,
35  			final int choice,
36  			final ElGamalCiphertextish m,
37  			final ElGamalReencryptFactor factor) {
38  
39  		int l = ciphertexts.size();
40  		ElGamalParameters ps = key.params;
41  		CivitasBigInteger u = m.getA();
42  		CivitasBigInteger v = m.getB();
43  		CivitasBigInteger r = factor.r();
44  
45  		ElGamalCiphertextish[] ms = new ElGamalCiphertext[l];
46  		for (int i = 0; i < l; i++) {
47  			ms[i] = ciphertexts.get(i);
48  		}
49  
50  		// choose d1 .. dL, and r1 ... rL at random.
51  		CivitasBigInteger[] ds = new CivitasBigInteger[l];
52  		for (int i = 0; i < l; i++) {
53  			ds[i] = cryptoBase.generateRandomElement(ps.q);
54  		}
55  		CivitasBigInteger[] rs = new CivitasBigInteger[l];
56  		for (int i = 0; i < l; i++) {
57  			rs[i] = cryptoBase.generateRandomElement(ps.q);
58  		}
59  
60  		// compute a_i's and b_i's
61  		CivitasBigInteger[] as = new CivitasBigInteger[l];
62  		CivitasBigInteger[] bs = new CivitasBigInteger[l];
63  		for (int i = 0; i < l; i++) {
64  			as[i] = ms[i].getA()
65  					.modDivide(u, ps.p)
66  					.modPow(ds[i], ps.p)
67  					.modMultiply(ps.g.modPow(rs[i], ps.p), ps.p)
68  					.mod(ps.p);
69  			bs[i] = ms[i].getB()
70  					.modDivide(v, ps.p)
71  					.modPow(ds[i], ps.p)
72  					.modMultiply(key.y.modPow(rs[i], ps.p), ps.p)
73  					.mod(ps.p);
74  		}
75  
76  		List<CivitasBigInteger> env = new ArrayList<>();
77  		env.add(u);
78  		env.add(v);
79  		for (int i = 0; i < l; i++) {
80  			env.add(ms[i].getA());
81  			env.add(ms[i].getB());
82  			env.add(as[i]);
83  			env.add(bs[i]);
84  		}
85  		CivitasBigInteger c = convertHashToBigInt.apply(cryptoHash.apply(env)).mod(ps.q);
86  		CivitasBigInteger w = r.modNegate(ps.q).modMultiply(ds[choice], ps.q).modAdd(rs[choice], ps.q);
87  		CivitasBigInteger sum = ZERO;
88  		for (int i = 0; i < l; i++) {
89  			if (i != choice) {
90  				sum = sum.modAdd(ds[i], ps.q);
91  			}
92  		}
93  
94  		CivitasBigInteger dprimet = c.modSubtract(sum, ps.q);
95  		CivitasBigInteger rprimet = w.modAdd(r.modMultiply(dprimet, ps.q), ps.q);
96  
97  		CivitasBigInteger[] dvs = new CivitasBigInteger[l];
98  		CivitasBigInteger[] rvs = new CivitasBigInteger[l];
99  		for (int i = 0; i < l; i++) {
100 			if (i == choice) {
101 				dvs[i] = dprimet;
102 				rvs[i] = rprimet;
103 			} else {
104 				dvs[i] = ds[i];
105 				rvs[i] = rs[i];
106 			}
107 		}
108 
109 		return new ElGamalProof1OfL(l, dvs, rvs);
110 	}
111 }