· 9 years ago · Jan 23, 2017, 06:48 PM
1import java.io.*;
2import java.math.BigInteger;
3import com.google.common.base.Charsets;
4import com.google.common.hash.Hashing;
5import java.math.BigInteger;
6
7import com.google.gson.Gson;
8import com.google.gson.JsonObject;
9import com.google.gson.JsonParser;
10import org.bouncycastle.math.ec.ECPoint;
11import org.json.simple.JSONObject;
12
13import java.nio.file.Files;
14import java.nio.file.Paths;
15import java.nio.file.StandardOpenOption;
16import java.util.HashMap;
17import java.util.Random;
18import java.util.stream.Stream;
19
20/**
21 * Created by root on 1/20/17.
22 */
23public class Signer {
24 private ECPoint G;
25 private ECPoint ROwner;
26 private BigInteger S;
27 ECPoint publicKey;
28 BigInteger AOwner;
29 private BigInteger secretKey;
30
31 /**
32 * constructor in which signer generate secret key and write his public key to file
33 * @param id
34 */
35 Signer(int id) {
36 secretKey = generateSecretKey();
37 G = Main.ec.createPoint(Main.Gx, Main.Gy).normalize();
38 publicKey = G.multiply(secretKey).normalize();
39 writeToFile(id, publicKey);
40
41 }
42
43 /**
44 * method to sign
45 * @param id
46 */
47 JSONObject RSign(int id)
48 {
49 //size is always number of signers - 1 cause i must be different than j
50 BigInteger[] A = new BigInteger[Main.numberOfSigners-1];
51 ECPoint[] R = new ECPoint[Main.numberOfSigners-1];
52 String[] hash = new String[Main.numberOfSigners-1];
53 ECPoint[] Y = getPublicKeysFromFile(id);
54
55
56 for(int i = 0; i < Main.numberOfSigners - 1; i++)
57 {
58 A[i] = generateRandom();
59 R[i] = G.multiply(A[i]).normalize();
60 hash[i] = Hashing.sha1().hashString(Main.M + R[i].toString(), Charsets.UTF_8 ).toString();
61 }
62
63 AOwner = generateRandom();
64
65 ECPoint ecPoint = Y[0].multiply(Main.Q.subtract(new BigInteger(hash[0], 16))); //how to initialize it with default value?
66 for(int i = 1; i < Main.numberOfSigners - 1; i++) //from one cause have no idea how to initialize ECPoint with sth diffrent than null
67 {
68 BigInteger h = Main.Q.subtract(new BigInteger(hash[i], 16));
69 ecPoint = ecPoint.add(Y[i].multiply(h));
70 }
71 ROwner = G.multiply(AOwner).add(ecPoint);
72 String hashOwner = Hashing.sha1().hashString(Main.M + ROwner.toString(), Charsets.UTF_8 ).toString();
73 BigInteger hOwner = new BigInteger(hashOwner, 16);
74 BigInteger S = new BigInteger("0");
75 for(int i = 0; i < Main.numberOfSigners - 1; i++)
76 {
77 S = S.add(A[i]);
78 }
79 S = S.add(secretKey.multiply(hOwner));
80
81 return generateJsonWithSignature(id, ROwner, R, S); //we have everything- generate signature
82 }
83
84 /**
85 * method which generate json with signature=(Rs, S)
86 * @param id
87 * @param ROwner
88 * @param R
89 * @param S
90 * @return
91 */
92 private JSONObject generateJsonWithSignature(int id, ECPoint ROwner, ECPoint[] R, BigInteger S)
93 {
94 //does the order of R even matters?
95 JSONObject json = new JSONObject();
96 json.put("id", id);
97 json.put("R0", ROwner);
98 for(int i = 0; i < R.length; i++)
99 {
100 System.out.println("i: " + i + " R: " + R[i]);
101 }
102 for(int i = 0; i < R.length; i++)
103 {
104 json.put("R"+(i+1), R[i]); //just figured out its working. If sth is stupid but its working then its not stupid. In this case it is
105 }
106 json.put("S", S);
107 System.out.println("jsonSignature: " + json);
108 return json;
109 }
110
111
112 /**
113 * method to write id of signer and his public key to file
114 * @param id
115 * @param publicKey
116 */
117 private void writeToFile(int id, ECPoint publicKey) {
118 try {
119 HashMap params = new HashMap();
120 params.put("Yx", new BigInteger(publicKey.getAffineXCoord().toString(),16));
121 params.put("Yy", new BigInteger(publicKey.getAffineYCoord().toString(),16));
122 JSONObject json = new JSONObject();
123 json.put("id", id);
124 json.put("params", params);
125
126 Files.write(Paths.get(Main.pathToFile), (json.toString()+"\n").getBytes(), StandardOpenOption.APPEND);
127
128 }catch (IOException e) {
129 //exception handling left as an exercise for the Staniuch
130 }
131 }
132
133 /**
134 *
135 * @param id - we have to omit it cause we already have it
136 * @return
137 */
138 private ECPoint[] getPublicKeysFromFile(int id)
139 {
140 ECPoint[] Y = new ECPoint[Main.numberOfSigners-1];
141 File file = new File(Main.pathToFile);
142
143 try (BufferedReader br = new BufferedReader(new FileReader(file))) {
144 String line;
145 int indexInArray = 0; //yeah, could just use ArrayList
146 while ((line = br.readLine()) != null) {
147 //System.out.println("line: " + line);
148 com.google.gson.JsonObject json = new JsonParser().parse(line).getAsJsonObject();
149 if(Integer.parseInt(String.valueOf(json.get("id"))) != id)
150 {
151 BigInteger Yx = new BigInteger(json.getAsJsonObject("params").get("Yx").toString());
152 BigInteger Yy = new BigInteger(json.getAsJsonObject("params").get("Yy").toString());
153 Y[indexInArray] = Main.ec.createPoint(Yx, Yy);
154 indexInArray++;
155 }
156 }
157
158 } catch (IOException e) {
159 e.printStackTrace();
160 }
161 return Y;
162 }
163
164 private BigInteger generateRandom() {
165 Random r = new Random();
166 BigInteger result = new BigInteger(Main.Q.bitLength(), r);
167 return result;
168 }
169
170 private BigInteger generateSecretKey() {
171 Random r = new Random();
172 BigInteger result = new BigInteger(Main.Q.bitLength(), r);
173 return result;
174 }
175
176}