Frames | No Frames |
1: /* DSSSignature.java -- 2: Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc. 3: 4: This file is a part of GNU Classpath. 5: 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. 10: 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. 15: 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 19: USA 20: 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 24: combination. 25: 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. */ 37: 38: 39: package gnu.java.security.sig.dss; 40: 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; 47: 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; 54: import java.util.Map; 55: import java.util.Random; 56: 57: /** 58: * The DSS (Digital Signature Standard) algorithm makes use of the following 59: * parameters: 60: * <ol> 61: * <li>p: A prime modulus, where 62: * <code>2<sup>L-1</sup> < p < 2<sup>L</sup> </code> for <code>512 <= L 63: * <= 1024</code> and <code>L</code> a multiple of <code>64</code>.</li> 64: * <li>q: A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup> 65: * < q < 2<sup>160</sup></code>.</li> 66: * <li>g: Where <code>g = h<sup>(p-1)</sup>/q mod p</code>, where 67: * <code>h</code> is any integer with <code>1 < h < p - 1</code> such 68: * that <code>h<sup> (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order 69: * <code>q mod p</code>).</li> 70: * <li>x: A randomly or pseudorandomly generated integer with <code>0 < x 71: * < q</code>.</li> 72: * <li>y: <code>y = g<sup>x</sup> mod p</code>.</li> 73: * <li>k: A randomly or pseudorandomly generated integer with <code>0 < k 74: * < q</code>.</li> 75: * </ol> 76: * <p> 77: * The integers <code>p</code>, <code>q</code>, and <code>g</code> can be 78: * public and can be common to a group of users. A user's private and public 79: * keys are <code>x</code> and <code>y</code>, respectively. They are 80: * normally fixed for a period of time. Parameters <code>x</code> and 81: * <code>k</code> are used for signature generation only, and must be kept 82: * secret. Parameter <code>k</code> must be regenerated for each signature. 83: * <p> 84: * The signature of a message <code>M</code> is the pair of numbers 85: * <code>r</code> and <code>s</code> computed according to the equations below: 86: * <ul> 87: * <li><code>r = (g<sup>k</sup> mod p) mod q</code> and</li> 88: * <li><code>s = (k<sup>-1</sup>(SHA(M) + xr)) mod q</code>.</li> 89: * </ul> 90: * <p> 91: * In the above, <code>k<sup>-1</sup></code> is the multiplicative inverse of 92: * <code>k</code>, <code>mod q</code>; i.e., <code>(k<sup>-1</sup> k) mod q = 93: * 1</code> and <code>0 < k-1 < q</code>. The value of <code>SHA(M)</code> 94: * is a 160-bit string output by the Secure Hash Algorithm specified in FIPS 95: * 180. For use in computing <code>s</code>, this string must be converted to 96: * an integer. 97: * <p> 98: * As an option, one may wish to check if <code>r == 0</code> or <code>s == 0 99: * </code>. 100: * If either <code>r == 0</code> or <code>s == 0</code>, a new value of 101: * <code>k</code> should be generated and the signature should be recalculated 102: * (it is extremely unlikely that <code>r == 0</code> or <code>s == 0</code> if 103: * signatures are generated properly). 104: * <p> 105: * The signature is transmitted along with the message to the verifier. 106: * <p> 107: * References: 108: * <ol> 109: * <li><a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital Signature 110: * Standard (DSS)</a>, Federal Information Processing Standards Publication 111: * 186. National Institute of Standards and Technology.</li> 112: * </ol> 113: */ 114: public class DSSSignature 115: extends BaseSignature 116: { 117: /** Trivial 0-arguments constructor. */ 118: public DSSSignature() 119: { 120: super(Registry.DSS_SIG, new Sha160()); 121: } 122: 123: /** Private constructor for cloning purposes. */ 124: private DSSSignature(DSSSignature that) 125: { 126: this(); 127: 128: this.publicKey = that.publicKey; 129: this.privateKey = that.privateKey; 130: this.md = (IMessageDigest) that.md.clone(); 131: } 132: 133: public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h) 134: { 135: final DSSSignature sig = new DSSSignature(); 136: final Map attributes = new HashMap(); 137: attributes.put(ISignature.SIGNER_KEY, k); 138: sig.setupSign(attributes); 139: return sig.computeRS(h); 140: } 141: 142: public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h, 143: Random rnd) 144: { 145: final DSSSignature sig = new DSSSignature(); 146: final Map attributes = new HashMap(); 147: attributes.put(ISignature.SIGNER_KEY, k); 148: if (rnd != null) 149: attributes.put(ISignature.SOURCE_OF_RANDOMNESS, rnd); 150: 151: sig.setupSign(attributes); 152: return sig.computeRS(h); 153: } 154: 155: public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h, 156: IRandom irnd) 157: { 158: final DSSSignature sig = new DSSSignature(); 159: final Map attributes = new HashMap(); 160: attributes.put(ISignature.SIGNER_KEY, k); 161: if (irnd != null) 162: attributes.put(ISignature.SOURCE_OF_RANDOMNESS, irnd); 163: 164: sig.setupSign(attributes); 165: return sig.computeRS(h); 166: } 167: 168: public static final boolean verify(final DSAPublicKey k, final byte[] h, 169: final BigInteger[] rs) 170: { 171: final DSSSignature sig = new DSSSignature(); 172: final Map attributes = new HashMap(); 173: attributes.put(ISignature.VERIFIER_KEY, k); 174: sig.setupVerify(attributes); 175: return sig.checkRS(rs, h); 176: } 177: 178: public Object clone() 179: { 180: return new DSSSignature(this); 181: } 182: 183: protected void setupForVerification(PublicKey k) 184: throws IllegalArgumentException 185: { 186: if (! (k instanceof DSAPublicKey)) 187: throw new IllegalArgumentException(); 188: 189: this.publicKey = k; 190: } 191: 192: protected void setupForSigning(PrivateKey k) throws IllegalArgumentException 193: { 194: if (! (k instanceof DSAPrivateKey)) 195: throw new IllegalArgumentException(); 196: 197: this.privateKey = k; 198: } 199: 200: protected Object generateSignature() throws IllegalStateException 201: { 202: final BigInteger[] rs = computeRS(md.digest()); 203: return encodeSignature(rs[0], rs[1]); 204: } 205: 206: protected boolean verifySignature(Object sig) throws IllegalStateException 207: { 208: final BigInteger[] rs = decodeSignature(sig); 209: return checkRS(rs, md.digest()); 210: } 211: 212: /** 213: * Returns the output of a signature generation phase. 214: * 215: * @return an object encapsulating the DSS signature pair <code>r</code> and 216: * <code>s</code>. 217: */ 218: private Object encodeSignature(BigInteger r, BigInteger s) 219: { 220: return new BigInteger[] { r, s }; 221: } 222: 223: /** 224: * Returns the output of a previously generated signature object as a pair of 225: * {@link java.math.BigInteger}. 226: * 227: * @return the DSS signature pair <code>r</code> and <code>s</code>. 228: */ 229: private BigInteger[] decodeSignature(Object signature) 230: { 231: return (BigInteger[]) signature; 232: } 233: 234: private BigInteger[] computeRS(final byte[] digestBytes) 235: { 236: final BigInteger p = ((DSAPrivateKey) privateKey).getParams().getP(); 237: final BigInteger q = ((DSAPrivateKey) privateKey).getParams().getQ(); 238: final BigInteger g = ((DSAPrivateKey) privateKey).getParams().getG(); 239: final BigInteger x = ((DSAPrivateKey) privateKey).getX(); 240: final BigInteger m = new BigInteger(1, digestBytes); 241: BigInteger k, r, s; 242: final byte[] kb = new byte[20]; // we'll use 159 bits only 243: while (true) 244: { 245: this.nextRandomBytes(kb); 246: k = new BigInteger(1, kb); 247: k.clearBit(159); 248: r = g.modPow(k, p).mod(q); 249: if (r.equals(BigInteger.ZERO)) 250: continue; 251: 252: s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q); 253: if (s.equals(BigInteger.ZERO)) 254: continue; 255: 256: break; 257: } 258: return new BigInteger[] { r, s }; 259: } 260: 261: private boolean checkRS(final BigInteger[] rs, final byte[] digestBytes) 262: { 263: final BigInteger r = rs[0]; 264: final BigInteger s = rs[1]; 265: final BigInteger g = ((DSAPublicKey) publicKey).getParams().getG(); 266: final BigInteger p = ((DSAPublicKey) publicKey).getParams().getP(); 267: final BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ(); 268: final BigInteger y = ((DSAPublicKey) publicKey).getY(); 269: final BigInteger w = s.modInverse(q); 270: final BigInteger u1 = w.multiply(new BigInteger(1, digestBytes)).mod(q); 271: final BigInteger u2 = r.multiply(w).mod(q); 272: final BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q); 273: return v.equals(r); 274: } 275: }