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
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
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 }