Source for gnu.java.security.sig.dss.DSSSignature

   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> &lt; p &lt; 2<sup>L</sup> </code> for <code>512 &lt;= L
  63:  * &lt;= 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:  *    &lt; q &lt; 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 &lt; h &lt; 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 &lt; x
  71:  *    &lt; 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 &lt; k
  74:  *    &lt; 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 &lt; k-1 &lt; 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: }