1
/* DSSSignature.java --
2
Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
4
This file is a part of GNU Classpath.
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or (at
9
your option) any later version.
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library. Thus, the terms and
23
conditions of the GNU General Public License cover the whole
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module. An independent module is a module which is not derived from
33
or based on this library. If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so. If you do not wish to do so, delete this
36
exception statement from your version. */
39
package gnu.java.security.sig.dss;
41
import gnu.java.security.Registry;
42
import gnu.java.security.hash.IMessageDigest;
43
import gnu.java.security.hash.Sha160;
44
import gnu.java.security.prng.IRandom;
45
import gnu.java.security.sig.BaseSignature;
46
import gnu.java.security.sig.ISignature;
48
import java.math.BigInteger;
49
import java.security.PrivateKey;
50
import java.security.PublicKey;
51
import java.security.interfaces.DSAPrivateKey;
52
import java.security.interfaces.DSAPublicKey;
53
import java.util.HashMap;
55
import java.util.Random;
58
* <p>The DSS (Digital Signature Standard) algorithm makes use of the following
62
* <li>p: A prime modulus, where <code>2<sup>L-1</sup> < p < 2<sup>L</sup>
63
* </code> for <code>512 <= L <= 1024</code> and <code>L</code> a
64
* multiple of <code>64</code>.</li>
65
* <li>q: A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup>
66
* < q < 2<sup>160</sup></code>.</li>
67
* <li>g: Where <code>g = h<sup>(p-1)</sup>/q mod p</code>, where
68
* <code>h</code> is any integer with <code>1 < h < p - 1</code> such
69
* that <code>h<sup> (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order
70
* <code>q mod p</code>).</li>
71
* <li>x: A randomly or pseudorandomly generated integer with <code>0 < x
73
* <li>y: <code>y = g<sup>x</sup> mod p</code>.</li>
74
* <li>k: A randomly or pseudorandomly generated integer with <code>0 < k
78
* <p>The integers <code>p</code>, <code>q</code>, and <code>g</code> can be
79
* public and can be common to a group of users. A user's private and public
80
* keys are <code>x</code> and <code>y</code>, respectively. They are normally
81
* fixed for a period of time. Parameters <code>x</code> and <code>k</code> are
82
* used for signature generation only, and must be kept secret. Parameter
83
* <code>k</code> must be regenerated for each signature.</p>
85
* <p>The signature of a message <code>M</code> is the pair of numbers <code>r</code>
86
* and <code>s</code> computed according to the equations below:</p>
89
* <li><code>r = (g<sup>k</sup> mod p) mod q</code> and</li>
90
* <li><code>s = (k<sup>-1</sup>(SHA(M) + xr)) mod q</code>.</li>
93
* <p>In the above, <code>k<sup>-1</sup></code> is the multiplicative inverse of
94
* <code>k</code>, <code>mod q</code>; i.e., <code>(k<sup>-1</sup> k) mod q = 1
95
* </code> and <code>0 < k-1 < q</code>. The value of <code>SHA(M)</code>
96
* is a 160-bit string output by the Secure Hash Algorithm specified in FIPS 180.
97
* For use in computing <code>s</code>, this string must be converted to an
100
* <p>As an option, one may wish to check if <code>r == 0</code> or <code>s == 0
101
* </code>. If either <code>r == 0</code> or <code>s == 0</code>, a new value
102
* of <code>k</code> should be generated and the signature should be
103
* recalculated (it is extremely unlikely that <code>r == 0</code> or <code>s ==
104
* 0</code> if signatures are generated properly).</p>
106
* <p>The signature is transmitted along with the message to the verifier.</p>
110
* <li><a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital
111
* Signature Standard (DSS)</a>, Federal Information Processing Standards
112
* Publication 186. National Institute of Standards and Technology.</li>
115
public class DSSSignature extends BaseSignature
118
// Constants and variables
119
// -------------------------------------------------------------------------
122
// -------------------------------------------------------------------------
124
/** Trivial 0-arguments constructor. */
125
public DSSSignature()
127
super(Registry.DSS_SIG, new Sha160());
130
/** Private constructor for cloning purposes. */
131
private DSSSignature(DSSSignature that)
135
this.publicKey = that.publicKey;
136
this.privateKey = that.privateKey;
137
this.md = (IMessageDigest) that.md.clone();
141
// -------------------------------------------------------------------------
143
public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h)
145
final DSSSignature sig = new DSSSignature();
146
final Map attributes = new HashMap();
147
attributes.put(ISignature.SIGNER_KEY, k);
148
sig.setupSign(attributes);
150
return sig.computeRS(h);
153
public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h,
156
final DSSSignature sig = new DSSSignature();
157
final Map attributes = new HashMap();
158
attributes.put(ISignature.SIGNER_KEY, k);
161
attributes.put(ISignature.SOURCE_OF_RANDOMNESS, rnd);
163
sig.setupSign(attributes);
165
return sig.computeRS(h);
168
public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h,
171
final DSSSignature sig = new DSSSignature();
172
final Map attributes = new HashMap();
173
attributes.put(ISignature.SIGNER_KEY, k);
176
attributes.put(ISignature.SOURCE_OF_RANDOMNESS, irnd);
178
sig.setupSign(attributes);
180
return sig.computeRS(h);
183
public static final boolean verify(final DSAPublicKey k, final byte[] h,
184
final BigInteger[] rs)
186
final DSSSignature sig = new DSSSignature();
187
final Map attributes = new HashMap();
188
attributes.put(ISignature.VERIFIER_KEY, k);
189
sig.setupVerify(attributes);
191
return sig.checkRS(rs, h);
194
// Implementation of abstract methods in superclass
195
// -------------------------------------------------------------------------
197
public Object clone()
199
return new DSSSignature(this);
202
protected void setupForVerification(PublicKey k)
203
throws IllegalArgumentException
205
if (!(k instanceof DSAPublicKey))
207
throw new IllegalArgumentException();
212
protected void setupForSigning(PrivateKey k) throws IllegalArgumentException
214
if (!(k instanceof DSAPrivateKey))
216
throw new IllegalArgumentException();
221
protected Object generateSignature() throws IllegalStateException
223
// BigInteger p = ((DSAPrivateKey) privateKey).getParams().getP();
224
// BigInteger q = ((DSAPrivateKey) privateKey).getParams().getQ();
225
// BigInteger g = ((DSAPrivateKey) privateKey).getParams().getG();
226
// BigInteger x = ((DSAPrivateKey) privateKey).getX();
227
// BigInteger m = new BigInteger(1, md.digest());
228
// BigInteger k, r, s;
230
// byte[] kb = new byte[20]; // we'll use 159 bits only
232
// this.nextRandomBytes(kb);
233
// k = new BigInteger(1, kb);
235
// r = g.modPow(k, p).mod(q);
236
// if (r.equals(BigInteger.ZERO)) {
239
// s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q);
240
// if (s.equals(BigInteger.ZERO)) {
245
final BigInteger[] rs = computeRS(md.digest());
247
// return encodeSignature(r, s);
248
return encodeSignature(rs[0], rs[1]);
251
protected boolean verifySignature(Object sig) throws IllegalStateException
253
final BigInteger[] rs = decodeSignature(sig);
254
// BigInteger r = rs[0];
255
// BigInteger s = rs[1];
257
// BigInteger g = ((DSAPublicKey) publicKey).getParams().getG();
258
// BigInteger p = ((DSAPublicKey) publicKey).getParams().getP();
259
// BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ();
260
// BigInteger y = ((DSAPublicKey) publicKey).getY();
261
// BigInteger w = s.modInverse(q);
263
// byte bytes[] = md.digest();
264
// BigInteger u1 = w.multiply(new BigInteger(1, bytes)).mod(q);
265
// BigInteger u2 = r.multiply(w).mod(q);
267
// BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
268
// return v.equals(r);
269
return checkRS(rs, md.digest());
272
// Other instance methods
273
// -------------------------------------------------------------------------
276
* Returns the output of a signature generation phase.<p>
278
* @return an object encapsulating the DSS signature pair <code>r</code> and
281
private Object encodeSignature(BigInteger r, BigInteger s)
283
return new BigInteger[] { r, s };
287
* Returns the output of a previously generated signature object as a pair
288
* of {@link java.math.BigInteger}.<p>
290
* @return the DSS signature pair <code>r</code> and <code>s</code>.
292
private BigInteger[] decodeSignature(Object signature)
294
return (BigInteger[]) signature;
297
private BigInteger[] computeRS(final byte[] digestBytes)
299
final BigInteger p = ((DSAPrivateKey) privateKey).getParams().getP();
300
final BigInteger q = ((DSAPrivateKey) privateKey).getParams().getQ();
301
final BigInteger g = ((DSAPrivateKey) privateKey).getParams().getG();
302
final BigInteger x = ((DSAPrivateKey) privateKey).getX();
303
final BigInteger m = new BigInteger(1, digestBytes);
306
final byte[] kb = new byte[20]; // we'll use 159 bits only
309
this.nextRandomBytes(kb);
310
k = new BigInteger(1, kb);
312
r = g.modPow(k, p).mod(q);
313
if (r.equals(BigInteger.ZERO))
317
s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q);
318
if (s.equals(BigInteger.ZERO))
325
return new BigInteger[] { r, s };
328
private boolean checkRS(final BigInteger[] rs, final byte[] digestBytes)
330
final BigInteger r = rs[0];
331
final BigInteger s = rs[1];
333
final BigInteger g = ((DSAPublicKey) publicKey).getParams().getG();
334
final BigInteger p = ((DSAPublicKey) publicKey).getParams().getP();
335
final BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ();
336
final BigInteger y = ((DSAPublicKey) publicKey).getY();
337
final BigInteger w = s.modInverse(q);
339
final BigInteger u1 = w.multiply(new BigInteger(1, digestBytes)).mod(q);
340
final BigInteger u2 = r.multiply(w).mod(q);
342
final BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);