KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > maverick > crypto > publickey > Dsa


1 /*
2  * SSL-Explorer
3  *
4  * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */

19             
20 package com.maverick.crypto.publickey;
21
22 import com.maverick.crypto.digests.SHA1Digest;
23 import java.math.BigInteger JavaDoc;
24 import com.maverick.crypto.security.SecureRandom;
25
26 public final class Dsa {
27
28   public static byte[] sign(BigInteger JavaDoc x,
29                             BigInteger JavaDoc p, BigInteger JavaDoc q, BigInteger JavaDoc g,
30                             byte[] data) {
31       
32     BigInteger JavaDoc hM = new BigInteger JavaDoc(1, data);
33
34     hM = hM.mod(q);
35
36     BigInteger JavaDoc r = g.modPow(x, p).mod(q);
37     BigInteger JavaDoc s = x.modInverse(q).multiply(hM.add(x.multiply(r))).mod(q);
38
39     int dataSz = data.length;
40     byte[] signature = new byte[dataSz * 2];
41     byte[] tmp;
42
43     tmp = unsignedBigIntToBytes(r, dataSz);
44     System.arraycopy(tmp, 0, signature, 0, dataSz);
45
46     tmp = unsignedBigIntToBytes(s, dataSz);
47     System.arraycopy(tmp, 0, signature, dataSz, dataSz);
48
49     return signature;
50   }
51
52   public static boolean verify(BigInteger JavaDoc y,
53                                BigInteger JavaDoc p, BigInteger JavaDoc q, BigInteger JavaDoc g,
54                                byte[] signature, byte[] data) {
55     int dataSz = signature.length / 2;
56     byte[] ra = new byte[dataSz];
57     byte[] sa = new byte[dataSz];
58
59     System.arraycopy(signature, 0, ra, 0, dataSz);
60     System.arraycopy(signature, dataSz, sa, 0, dataSz);
61
62     BigInteger JavaDoc hM = new BigInteger JavaDoc(1, data);
63     BigInteger JavaDoc r = new BigInteger JavaDoc(1, ra);
64     BigInteger JavaDoc s = new BigInteger JavaDoc(1, sa);
65
66     hM = hM.mod(q);
67
68     BigInteger JavaDoc w = s.modInverse(q);
69     BigInteger JavaDoc u1 = hM.multiply(w).mod(q);
70     BigInteger JavaDoc u2 = r.multiply(w).mod(q);
71     BigInteger JavaDoc v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
72
73     return (v.compareTo(r) == 0);
74   }
75
76   private static byte[] unsignedBigIntToBytes(BigInteger JavaDoc bi, int size) {
77     byte[] tmp = bi.toByteArray();
78     byte[] tmp2 = null;
79     if (tmp.length > size) {
80       tmp2 = new byte[size];
81       System.arraycopy(tmp, tmp.length - size, tmp2, 0, size);
82     }
83     else if (tmp.length < size) {
84       tmp2 = new byte[size];
85       System.arraycopy(tmp, 0, tmp2, size - tmp.length, tmp.length);
86     }
87     else {
88       tmp2 = tmp;
89     }
90     return tmp2;
91   }
92
93   public static BigInteger JavaDoc generatePublicKey(BigInteger JavaDoc g, BigInteger JavaDoc p,
94                                              BigInteger JavaDoc x) {
95     return g.modPow(x, p);
96   }
97
98   public static DsaPrivateKey generateKey(int bits, SecureRandom rnd) {
99
100     BigInteger JavaDoc p, q, g, x, y;
101     BigInteger JavaDoc ZERO = BigInteger.valueOf(0);
102     DSAParametersGenerator dsaParams = new DSAParametersGenerator();
103     dsaParams.init(bits, 80, rnd);
104
105     DSAParameters dsa = dsaParams.generateParameters();
106
107     q = dsa.getQ();
108     p = dsa.getP();
109     g = dsa.getG();
110
111     do {
112       x = new BigInteger JavaDoc(160, rnd);
113     }
114     while (x.equals(ZERO) || x.compareTo(q) >= 0);
115
116     //
117
// calculate the public key.
118
//
119
y = g.modPow(x, p);
120
121     return new DsaPrivateKey(p, q, g, x);
122   }
123
124 }
125
126 /**
127  * generate suitable parameters for DSA, in line with FIPS 186-2.
128  */

129 class DSAParametersGenerator {
130   private int size;
131   private int certainty;
132   private SecureRandom random;
133
134   private static BigInteger JavaDoc ONE = BigInteger.valueOf(1);
135   private static BigInteger JavaDoc TWO = BigInteger.valueOf(2);
136
137   /**
138    * initialise the key generator.
139    *
140    * @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments)
141    * @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80).
142    * @param random random byte source.
143    */

144   public void init(
145       int size,
146       int certainty,
147       SecureRandom random) {
148     this.size = size;
149     this.certainty = certainty;
150     this.random = random;
151   }
152
153   /**
154    * add value to b, returning the result in a. The a value is treated
155    * as a BigInteger of length (a.length * 8) bits. The result is
156    * modulo 2^a.length in case of overflow.
157    */

158   private void add(
159       byte[] a,
160       byte[] b,
161       int value) {
162     int x = (b[b.length - 1] & 0xff) + value;
163
164     a[b.length - 1] = (byte) x;
165     x >>>= 8;
166
167     for (int i = b.length - 2; i >= 0; i--) {
168       x += (b[i] & 0xff);
169       a[i] = (byte) x;
170       x >>>= 8;
171     }
172   }
173
174   /**
175    * which generates the p and g values from the given parameters,
176    * returning the DSAParameters object.
177    * <p>
178    * Note: can take a while...
179    */

180   public DSAParameters generateParameters() {
181     byte[] seed = new byte[20];
182     byte[] part1 = new byte[20];
183     byte[] part2 = new byte[20];
184     byte[] u = new byte[20];
185     SHA1Digest sha1 = new SHA1Digest();
186     int n = (size - 1) / 160;
187     byte[] w = new byte[size / 8];
188
189     BigInteger JavaDoc q = null, p = null, g = null;
190     int counter = 0;
191     boolean primesFound = false;
192
193     while (!primesFound) {
194       do {
195         random.nextBytes(seed);
196
197         sha1.update(seed, 0, seed.length);
198
199         sha1.doFinal(part1, 0);
200
201         System.arraycopy(seed, 0, part2, 0, seed.length);
202
203         add(part2, seed, 1);
204
205         sha1.update(part2, 0, part2.length);
206
207         sha1.doFinal(part2, 0);
208
209         for (int i = 0; i != u.length; i++) {
210           u[i] = (byte) (part1[i] ^ part2[i]);
211         }
212
213         u[0] |= (byte) 0x80;
214         u[19] |= (byte) 0x01;
215
216         q = new BigInteger JavaDoc(1, u);
217       }
218       while (!q.isProbablePrime(certainty));
219
220       counter = 0;
221
222       int offset = 2;
223
224       while (counter < 4096) {
225         for (int k = 0; k < n; k++) {
226           add(part1, seed, offset + k);
227           sha1.update(part1, 0, part1.length);
228           sha1.doFinal(part1, 0);
229           System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length,
230                            part1.length);
231         }
232
233         add(part1, seed, offset + n);
234         sha1.update(part1, 0, part1.length);
235         sha1.doFinal(part1, 0);
236         System.arraycopy(part1, part1.length - ( (w.length - (n) * part1.length)),
237                          w, 0, w.length - n * part1.length);
238
239         w[0] |= (byte) 0x80;
240
241         BigInteger JavaDoc x = new BigInteger JavaDoc(1, w);
242
243         BigInteger JavaDoc c = x.mod(q.multiply(TWO));
244
245         p = x.subtract(c.subtract(ONE));
246
247         if (p.testBit(size - 1)) {
248           if (p.isProbablePrime(certainty)) {
249             primesFound = true;
250             break;
251           }
252         }
253
254         counter += 1;
255         offset += n + 1;
256       }
257     }
258
259     //
260
// calculate the generator g
261
//
262
BigInteger JavaDoc pMinusOneOverQ = p.subtract(ONE).divide(q);
263
264     for (; ; ) {
265       BigInteger JavaDoc h = new BigInteger JavaDoc(size, random);
266       if (h.compareTo(ONE) <= 0 || h.compareTo(p.subtract(ONE)) >= 0) {
267         continue;
268       }
269
270       g = h.modPow(pMinusOneOverQ, p);
271       if (g.compareTo(ONE) <= 0) {
272         continue;
273       }
274
275       break;
276     }
277
278     return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
279   }
280 }
281
282 class DSAParameters
283
284 {
285   private BigInteger JavaDoc g;
286   private BigInteger JavaDoc q;
287   private BigInteger JavaDoc p;
288   private DSAValidationParameters validation;
289
290   public DSAParameters(
291       BigInteger JavaDoc p,
292       BigInteger JavaDoc q,
293       BigInteger JavaDoc g) {
294     this.g = g;
295     this.p = p;
296     this.q = q;
297   }
298
299   public DSAParameters(
300       BigInteger JavaDoc p,
301       BigInteger JavaDoc q,
302       BigInteger JavaDoc g,
303       DSAValidationParameters params) {
304     this.g = g;
305     this.p = p;
306     this.q = q;
307     this.validation = params;
308   }
309
310   public BigInteger JavaDoc getP() {
311     return p;
312   }
313
314   public BigInteger JavaDoc getQ() {
315     return q;
316   }
317
318   public BigInteger JavaDoc getG() {
319     return g;
320   }
321
322   public DSAValidationParameters getValidationParameters() {
323     return validation;
324   }
325
326   public boolean equals(
327       Object JavaDoc obj) {
328     if (! (obj instanceof DSAParameters)) {
329       return false;
330     }
331
332     DSAParameters pm = (DSAParameters) obj;
333
334     return (pm.getP().equals(p) && pm.getQ().equals(q) && pm.getG().equals(g));
335   }
336 }
337
338 class DSAValidationParameters {
339   private byte[] seed;
340   private int counter;
341
342   public DSAValidationParameters(
343       byte[] seed,
344       int counter) {
345     this.seed = seed;
346     this.counter = counter;
347   }
348
349   public int getCounter() {
350     return counter;
351   }
352
353   public byte[] getSeed() {
354     return seed;
355   }
356
357   public boolean equals(
358       Object JavaDoc o) {
359     if (o == null || ! (o instanceof DSAValidationParameters)) {
360       return false;
361     }
362
363     DSAValidationParameters other = (DSAValidationParameters) o;
364
365     if (other.counter != this.counter) {
366       return false;
367     }
368
369     if (other.seed.length != this.seed.length) {
370       return false;
371     }
372
373     for (int i = 0; i != other.seed.length; i++) {
374       if (other.seed[i] != this.seed[i]) {
375         return false;
376       }
377     }
378
379     return true;
380   }
381 }
382
Popular Tags