DSA.java revision 15134:714224061029
1/*
2 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.security.provider;
27
28import java.io.*;
29import java.util.*;
30import java.math.BigInteger;
31import java.nio.ByteBuffer;
32
33import java.security.*;
34import java.security.SecureRandom;
35import java.security.interfaces.*;
36
37import sun.security.util.Debug;
38import sun.security.util.DerValue;
39import sun.security.util.DerInputStream;
40import sun.security.util.DerOutputStream;
41import sun.security.jca.JCAUtil;
42
43/**
44 * The Digital Signature Standard (using the Digital Signature
45 * Algorithm), as described in fips186-3 of the National Instute of
46 * Standards and Technology (NIST), using SHA digest algorithms
47 * from FIPS180-3.
48 *
49 * This file contains both the signature implementation for the
50 * commonly used SHA1withDSA (DSS), SHA224withDSA, SHA256withDSA,
51 * as well as RawDSA, used by TLS among others. RawDSA expects
52 * the 20 byte SHA-1 digest as input via update rather than the
53 * original data like other signature implementations.
54 *
55 * @author Benjamin Renaud
56 *
57 * @since   1.1
58 *
59 * @see DSAPublicKey
60 * @see DSAPrivateKey
61 */
62abstract class DSA extends SignatureSpi {
63
64    /* Are we debugging? */
65    private static final boolean debug = false;
66
67    /* The parameter object */
68    private DSAParams params;
69
70    /* algorithm parameters */
71    private BigInteger presetP, presetQ, presetG;
72
73    /* The public key, if any */
74    private BigInteger presetY;
75
76    /* The private key, if any */
77    private BigInteger presetX;
78
79    /* The RNG used to output a seed for generating k */
80    private SecureRandom signingRandom;
81
82    /* The message digest object used */
83    private final MessageDigest md;
84
85    /* The format. true for the IEEE P1363 format. false (default) for ASN.1 */
86    private final boolean p1363Format;
87
88    /**
89     * Construct a blank DSA object. It must be
90     * initialized before being usable for signing or verifying.
91     */
92    DSA(MessageDigest md) {
93        this(md, false);
94    }
95
96    /**
97     * Construct a blank DSA object that will use the specified
98     * signature format. {@code p1363Format} should be {@code true} to
99     * use the IEEE P1363 format. If {@code p1363Format} is {@code false},
100     * the DER-encoded ASN.1 format will used. The DSA object must be
101     * initialized before being usable for signing or verifying.
102     */
103    DSA(MessageDigest md, boolean p1363Format) {
104        super();
105        this.md = md;
106        this.p1363Format = p1363Format;
107    }
108
109    private static void checkKey(DSAParams params, int digestLen, String mdAlgo)
110        throws InvalidKeyException {
111        // FIPS186-3 states in sec4.2 that a hash function which provides
112        // a lower security strength than the (L, N) pair ordinarily should
113        // not be used.
114        int valueN = params.getQ().bitLength();
115        if (valueN > digestLen) {
116            throw new InvalidKeyException("The security strength of " +
117                mdAlgo + " digest algorithm is not sufficient for this key size");
118        }
119    }
120
121    /**
122     * Initialize the DSA object with a DSA private key.
123     *
124     * @param privateKey the DSA private key
125     *
126     * @exception InvalidKeyException if the key is not a valid DSA private
127     * key.
128     */
129    protected void engineInitSign(PrivateKey privateKey)
130            throws InvalidKeyException {
131        if (!(privateKey instanceof java.security.interfaces.DSAPrivateKey)) {
132            throw new InvalidKeyException("not a DSA private key: " +
133                                          privateKey);
134        }
135
136        java.security.interfaces.DSAPrivateKey priv =
137            (java.security.interfaces.DSAPrivateKey)privateKey;
138
139        // check for algorithm specific constraints before doing initialization
140        DSAParams params = priv.getParams();
141        if (params == null) {
142            throw new InvalidKeyException("DSA private key lacks parameters");
143        }
144
145        // check key size against hash output size for signing
146        // skip this check for verification to minimize impact on existing apps
147        if (md.getAlgorithm() != "NullDigest20") {
148            checkKey(params, md.getDigestLength()*8, md.getAlgorithm());
149        }
150
151        this.params = params;
152        this.presetX = priv.getX();
153        this.presetY = null;
154        this.presetP = params.getP();
155        this.presetQ = params.getQ();
156        this.presetG = params.getG();
157        this.md.reset();
158    }
159    /**
160     * Initialize the DSA object with a DSA public key.
161     *
162     * @param publicKey the DSA public key.
163     *
164     * @exception InvalidKeyException if the key is not a valid DSA public
165     * key.
166     */
167    protected void engineInitVerify(PublicKey publicKey)
168            throws InvalidKeyException {
169        if (!(publicKey instanceof java.security.interfaces.DSAPublicKey)) {
170            throw new InvalidKeyException("not a DSA public key: " +
171                                          publicKey);
172        }
173        java.security.interfaces.DSAPublicKey pub =
174            (java.security.interfaces.DSAPublicKey)publicKey;
175
176        // check for algorithm specific constraints before doing initialization
177        DSAParams params = pub.getParams();
178        if (params == null) {
179            throw new InvalidKeyException("DSA public key lacks parameters");
180        }
181        this.params = params;
182        this.presetY = pub.getY();
183        this.presetX = null;
184        this.presetP = params.getP();
185        this.presetQ = params.getQ();
186        this.presetG = params.getG();
187        this.md.reset();
188    }
189
190    /**
191     * Update a byte to be signed or verified.
192     */
193    protected void engineUpdate(byte b) {
194        md.update(b);
195    }
196
197    /**
198     * Update an array of bytes to be signed or verified.
199     */
200    protected void engineUpdate(byte[] data, int off, int len) {
201        md.update(data, off, len);
202    }
203
204    protected void engineUpdate(ByteBuffer b) {
205        md.update(b);
206    }
207
208
209    /**
210     * Sign all the data thus far updated. The signature format is
211     * determined by {@code p1363Format}. If {@code p1363Format} is
212     * {@code false} (the default), then the signature is formatted
213     * according to the Canonical Encoding Rules, returned as a DER
214     * sequence of Integers, r and s. If {@code p1363Format} is
215     * {@code false}, the signature is returned in the IEEE P1363
216     * format, which is the concatenation or r and s.
217     *
218     * @return a signature block formatted according to the format
219     * indicated by {@code p1363Format}
220     *
221     * @exception SignatureException if the signature object was not
222     * properly initialized, or if another exception occurs.
223     *
224     * @see sun.security.DSA#engineUpdate
225     * @see sun.security.DSA#engineVerify
226     */
227    protected byte[] engineSign() throws SignatureException {
228        BigInteger k = generateK(presetQ);
229        BigInteger r = generateR(presetP, presetQ, presetG, k);
230        BigInteger s = generateS(presetX, presetQ, r, k);
231
232        if (p1363Format) {
233            // Return the concatenation of r and s
234            byte[] rBytes = r.toByteArray();
235            byte[] sBytes = s.toByteArray();
236
237            int size = presetQ.bitLength() / 8;
238            byte[] outseq = new byte[size * 2];
239
240            int rLength = rBytes.length;
241            int sLength = sBytes.length;
242            int i;
243            for (i = rLength; i > 0 && rBytes[rLength - i] == 0; i--);
244
245            int j;
246            for (j = sLength;
247                    j > 0 && sBytes[sLength - j] == 0; j--);
248
249            System.arraycopy(rBytes, rLength - i, outseq, size - i, i);
250            System.arraycopy(sBytes, sLength - j, outseq, size * 2 - j, j);
251
252            return outseq;
253        } else {
254            // Return the DER-encoded ASN.1 form
255            try {
256                DerOutputStream outseq = new DerOutputStream(100);
257                outseq.putInteger(r);
258                outseq.putInteger(s);
259                DerValue result = new DerValue(DerValue.tag_Sequence,
260                        outseq.toByteArray());
261
262                return result.toByteArray();
263
264            } catch (IOException e) {
265                throw new SignatureException("error encoding signature");
266            }
267        }
268    }
269
270    /**
271     * Verify all the data thus far updated.
272     *
273     * @param signature the alleged signature, encoded using the
274     * Canonical Encoding Rules, as a sequence of integers, r and s.
275     *
276     * @exception SignatureException if the signature object was not
277     * properly initialized, or if another exception occurs.
278     *
279     * @see sun.security.DSA#engineUpdate
280     * @see sun.security.DSA#engineSign
281     */
282    protected boolean engineVerify(byte[] signature)
283            throws SignatureException {
284        return engineVerify(signature, 0, signature.length);
285    }
286
287    /**
288     * Verify all the data thus far updated.
289     *
290     * @param signature the alleged signature, encoded using the
291     * format indicated by {@code p1363Format}. If {@code p1363Format}
292     * is {@code false} (the default), then the signature is formatted
293     * according to the Canonical Encoding Rules, as a DER sequence of
294     * Integers, r and s. If {@code p1363Format} is {@code false},
295     * the signature is in the IEEE P1363 format, which is the
296     * concatenation or r and s.
297     *
298     * @param offset the offset to start from in the array of bytes.
299     *
300     * @param length the number of bytes to use, starting at offset.
301     *
302     * @exception SignatureException if the signature object was not
303     * properly initialized, or if another exception occurs.
304     *
305     * @see sun.security.DSA#engineUpdate
306     * @see sun.security.DSA#engineSign
307     */
308    protected boolean engineVerify(byte[] signature, int offset, int length)
309            throws SignatureException {
310
311        BigInteger r = null;
312        BigInteger s = null;
313
314        if (p1363Format) {
315            if ((length & 1) == 1) {
316                // length of signature byte array should be even
317                throw new SignatureException("invalid signature format");
318            }
319            int mid = length/2;
320            r = new BigInteger(Arrays.copyOfRange(signature, 0, mid));
321            s = new BigInteger(Arrays.copyOfRange(signature, mid, length));
322        } else {
323            // first decode the signature.
324            try {
325                DerInputStream in = new DerInputStream(signature, offset,
326                                                       length);
327                DerValue[] values = in.getSequence(2);
328
329                r = values[0].getBigInteger();
330                s = values[1].getBigInteger();
331
332                // Check for trailing signature data
333                if (in.available() != 0) {
334                    throw new IOException("Incorrect signature length");
335                }
336            } catch (IOException e) {
337                throw new SignatureException("invalid encoding for signature");
338            }
339        }
340
341        // some implementations do not correctly encode values in the ASN.1
342        // 2's complement format. force r and s to be positive in order to
343        // to validate those signatures
344        if (r.signum() < 0) {
345            r = new BigInteger(1, r.toByteArray());
346        }
347        if (s.signum() < 0) {
348            s = new BigInteger(1, s.toByteArray());
349        }
350
351        if ((r.compareTo(presetQ) == -1) && (s.compareTo(presetQ) == -1)) {
352            BigInteger w = generateW(presetP, presetQ, presetG, s);
353            BigInteger v = generateV(presetY, presetP, presetQ, presetG, w, r);
354            return v.equals(r);
355        } else {
356            throw new SignatureException("invalid signature: out of range values");
357        }
358    }
359
360    @Deprecated
361    protected void engineSetParameter(String key, Object param) {
362        throw new InvalidParameterException("No parameter accepted");
363    }
364
365    @Deprecated
366    protected Object engineGetParameter(String key) {
367        return null;
368    }
369
370    private BigInteger generateR(BigInteger p, BigInteger q, BigInteger g,
371                         BigInteger k) {
372        BigInteger temp = g.modPow(k, p);
373        return temp.mod(q);
374    }
375
376    private BigInteger generateS(BigInteger x, BigInteger q,
377            BigInteger r, BigInteger k) throws SignatureException {
378
379        byte[] s2;
380        try {
381            s2 = md.digest();
382        } catch (RuntimeException re) {
383            // Only for RawDSA due to its 20-byte length restriction
384            throw new SignatureException(re.getMessage());
385        }
386        // get the leftmost min(N, outLen) bits of the digest value
387        int nBytes = q.bitLength()/8;
388        if (nBytes < s2.length) {
389            s2 = Arrays.copyOfRange(s2, 0, nBytes);
390        }
391        BigInteger z = new BigInteger(1, s2);
392        BigInteger k1 = k.modInverse(q);
393
394        return x.multiply(r).add(z).multiply(k1).mod(q);
395    }
396
397    private BigInteger generateW(BigInteger p, BigInteger q,
398                         BigInteger g, BigInteger s) {
399        return s.modInverse(q);
400    }
401
402    private BigInteger generateV(BigInteger y, BigInteger p,
403             BigInteger q, BigInteger g, BigInteger w, BigInteger r)
404             throws SignatureException {
405
406        byte[] s2;
407        try {
408            s2 = md.digest();
409        } catch (RuntimeException re) {
410            // Only for RawDSA due to its 20-byte length restriction
411            throw new SignatureException(re.getMessage());
412        }
413        // get the leftmost min(N, outLen) bits of the digest value
414        int nBytes = q.bitLength()/8;
415        if (nBytes < s2.length) {
416            s2 = Arrays.copyOfRange(s2, 0, nBytes);
417        }
418        BigInteger z = new BigInteger(1, s2);
419
420        BigInteger u1 = z.multiply(w).mod(q);
421        BigInteger u2 = (r.multiply(w)).mod(q);
422
423        BigInteger t1 = g.modPow(u1,p);
424        BigInteger t2 = y.modPow(u2,p);
425        BigInteger t3 = t1.multiply(t2);
426        BigInteger t5 = t3.mod(p);
427        return t5.mod(q);
428    }
429
430    // NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1.
431    protected BigInteger generateK(BigInteger q) {
432        SecureRandom random = getSigningRandom();
433        byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];
434
435        random.nextBytes(kValue);
436        return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
437    }
438
439    // Use the application-specified SecureRandom Object if provided.
440    // Otherwise, use our default SecureRandom Object.
441    protected SecureRandom getSigningRandom() {
442        if (signingRandom == null) {
443            if (appRandom != null) {
444                signingRandom = appRandom;
445            } else {
446                signingRandom = JCAUtil.getSecureRandom();
447            }
448        }
449        return signingRandom;
450    }
451
452    /**
453     * Return a human readable rendition of the engine.
454     */
455    public String toString() {
456        String printable = "DSA Signature";
457        if (presetP != null && presetQ != null && presetG != null) {
458            printable += "\n\tp: " + Debug.toHexString(presetP);
459            printable += "\n\tq: " + Debug.toHexString(presetQ);
460            printable += "\n\tg: " + Debug.toHexString(presetG);
461        } else {
462            printable += "\n\t P, Q or G not initialized.";
463        }
464        if (presetY != null) {
465            printable += "\n\ty: " + Debug.toHexString(presetY);
466        }
467        if (presetY == null && presetX == null) {
468            printable += "\n\tUNINIIALIZED";
469        }
470        return printable;
471    }
472
473    private static void debug(Exception e) {
474        if (debug) {
475            e.printStackTrace();
476        }
477    }
478
479    private static void debug(String s) {
480        if (debug) {
481            System.err.println(s);
482        }
483    }
484
485    /**
486     * Standard SHA224withDSA implementation as defined in FIPS186-3.
487     */
488    public static final class SHA224withDSA extends DSA {
489        public SHA224withDSA() throws NoSuchAlgorithmException {
490            super(MessageDigest.getInstance("SHA-224"));
491        }
492    }
493
494    /**
495     * SHA224withDSA implementation that uses the IEEE P1363 format.
496     */
497    public static final class SHA224withDSAinP1363Format extends DSA {
498        public SHA224withDSAinP1363Format() throws NoSuchAlgorithmException {
499            super(MessageDigest.getInstance("SHA-224"), true);
500        }
501    }
502
503    /**
504     * Standard SHA256withDSA implementation as defined in FIPS186-3.
505     */
506    public static final class SHA256withDSA extends DSA {
507        public SHA256withDSA() throws NoSuchAlgorithmException {
508            super(MessageDigest.getInstance("SHA-256"));
509        }
510    }
511
512    /**
513     * SHA256withDSA implementation that uses the IEEE P1363 format.
514     */
515    public static final class SHA256withDSAinP1363Format extends DSA {
516        public SHA256withDSAinP1363Format() throws NoSuchAlgorithmException {
517            super(MessageDigest.getInstance("SHA-256"), true);
518        }
519    }
520
521    /**
522     * Standard SHA1withDSA implementation.
523     */
524    public static final class SHA1withDSA extends DSA {
525        public SHA1withDSA() throws NoSuchAlgorithmException {
526            super(MessageDigest.getInstance("SHA-1"));
527        }
528    }
529
530    /**
531     * SHA1withDSA implementation that uses the IEEE P1363 format.
532     */
533    public static final class SHA1withDSAinP1363Format extends DSA {
534        public SHA1withDSAinP1363Format() throws NoSuchAlgorithmException {
535            super(MessageDigest.getInstance("SHA-1"), true);
536        }
537    }
538
539    /**
540     * Raw DSA.
541     *
542     * Raw DSA requires the data to be exactly 20 bytes long. If it is
543     * not, a SignatureException is thrown when sign()/verify() is called
544     * per JCA spec.
545     */
546    static class Raw extends DSA {
547        // Internal special-purpose MessageDigest impl for RawDSA
548        // Only override whatever methods used
549        // NOTE: no clone support
550        public static final class NullDigest20 extends MessageDigest {
551            // 20 byte digest buffer
552            private final byte[] digestBuffer = new byte[20];
553
554            // offset into the buffer; use Integer.MAX_VALUE to indicate
555            // out-of-bound condition
556            private int ofs = 0;
557
558            protected NullDigest20() {
559                super("NullDigest20");
560            }
561            protected void engineUpdate(byte input) {
562                if (ofs == digestBuffer.length) {
563                    ofs = Integer.MAX_VALUE;
564                } else {
565                    digestBuffer[ofs++] = input;
566                }
567            }
568            protected void engineUpdate(byte[] input, int offset, int len) {
569                if (ofs + len > digestBuffer.length) {
570                    ofs = Integer.MAX_VALUE;
571                } else {
572                    System.arraycopy(input, offset, digestBuffer, ofs, len);
573                    ofs += len;
574                }
575            }
576            protected final void engineUpdate(ByteBuffer input) {
577                int inputLen = input.remaining();
578                if (ofs + inputLen > digestBuffer.length) {
579                    ofs = Integer.MAX_VALUE;
580                } else {
581                    input.get(digestBuffer, ofs, inputLen);
582                    ofs += inputLen;
583                }
584            }
585            protected byte[] engineDigest() throws RuntimeException {
586                if (ofs != digestBuffer.length) {
587                    throw new RuntimeException
588                        ("Data for RawDSA must be exactly 20 bytes long");
589                }
590                reset();
591                return digestBuffer;
592            }
593            protected int engineDigest(byte[] buf, int offset, int len)
594                throws DigestException {
595                if (ofs != digestBuffer.length) {
596                    throw new DigestException
597                        ("Data for RawDSA must be exactly 20 bytes long");
598                }
599                if (len < digestBuffer.length) {
600                    throw new DigestException
601                        ("Output buffer too small; must be at least 20 bytes");
602                }
603                System.arraycopy(digestBuffer, 0, buf, offset, digestBuffer.length);
604                reset();
605                return digestBuffer.length;
606            }
607
608            protected void engineReset() {
609                ofs = 0;
610            }
611            protected final int engineGetDigestLength() {
612                return digestBuffer.length;
613            }
614        }
615
616        private Raw(boolean p1363Format) throws NoSuchAlgorithmException {
617            super(new NullDigest20(), p1363Format);
618        }
619
620    }
621
622    /**
623     * Standard Raw DSA implementation.
624     */
625    public static final class RawDSA extends Raw {
626        public RawDSA() throws NoSuchAlgorithmException {
627            super(false);
628        }
629    }
630
631    /**
632     * Raw DSA implementation that uses the IEEE P1363 format.
633     */
634    public static final class RawDSAinP1363Format extends Raw {
635        public RawDSAinP1363Format() throws NoSuchAlgorithmException {
636            super(true);
637        }
638    }
639}
640