History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/provider/DSA.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/provider/DSA.java+678−0
@@ -0,0 +1,678 @@
1+/*
2+ * Copyright (c) 1996, 2004, 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+
26+package sun.security.provider;
27+
28+import java.io.*;
29+import java.util.*;
30+import java.math.BigInteger;
31+import java.nio.ByteBuffer;
32+
33+import java.security.*;
34+import java.security.SecureRandom;
35+import java.security.interfaces.*;
36+import java.security.spec.DSAParameterSpec;
37+import java.security.spec.InvalidParameterSpecException;
38+
39+import sun.security.util.Debug;
40+import sun.security.util.DerValue;
41+import sun.security.util.DerInputStream;
42+import sun.security.util.DerOutputStream;
43+import sun.security.x509.AlgIdDSA;
44+import sun.security.jca.JCAUtil;
45+
46+/**
47+ * The Digital Signature Standard (using the Digital Signature
48+ * Algorithm), as described in fips186 of the National Instute of
49+ * Standards and Technology (NIST), using fips180-1 (SHA-1).
50+ *
51+ * This file contains both the signature implementation for the
52+ * commonly used SHA1withDSA (DSS) as well as RawDSA, used by TLS
53+ * among others. RawDSA expects the 20 byte SHA-1 digest as input
54+ * via update rather than the original data like other signature
55+ * implementations.
56+ *
57+ * @author Benjamin Renaud
58+ *
59+ * @since 1.1
60+ *
61+ * @see DSAPublicKey
62+ * @see DSAPrivateKey
63+ */
64+abstract class DSA extends SignatureSpi {
65+
66+ /* Are we debugging? */
67+ private static final boolean debug = false;
68+
69+ /* The parameter object */
70+ private DSAParams params;
71+
72+ /* algorithm parameters */
73+ private BigInteger presetP, presetQ, presetG;
74+
75+ /* The public key, if any */
76+ private BigInteger presetY;
77+
78+ /* The private key, if any */
79+ private BigInteger presetX;
80+
81+ /* The random seed used to generate k */
82+ private int[] Kseed;
83+
84+ /* The random seed used to generate k (specified by application) */
85+ private byte[] KseedAsByteArray;
86+
87+ /*
88+ * The random seed used to generate k
89+ * (prevent the same Kseed from being used twice in a row
90+ */
91+ private int[] previousKseed;
92+
93+ /* The RNG used to output a seed for generating k */
94+ private SecureRandom signingRandom;
95+
96+ /**
97+ * Construct a blank DSA object. It must be
98+ * initialized before being usable for signing or verifying.
99+ */
100+ DSA() {
101+ super();
102+ }
103+
104+ /**
105+ * Return the 20 byte hash value and reset the digest.
106+ */
107+ abstract byte[] getDigest() throws SignatureException;
108+
109+ /**
110+ * Reset the digest.
111+ */
112+ abstract void resetDigest();
113+
114+ /**
115+ * Standard SHA1withDSA implementation.
116+ */
117+ public static final class SHA1withDSA extends DSA {
118+
119+ /* The SHA hash for the data */
120+ private final MessageDigest dataSHA;
121+
122+ public SHA1withDSA() throws NoSuchAlgorithmException {
123+ dataSHA = MessageDigest.getInstance("SHA-1");
124+ }
125+
126+ /**
127+ * Update a byte to be signed or verified.
128+ */
129+ protected void engineUpdate(byte b) {
130+ dataSHA.update(b);
131+ }
132+
133+ /**
134+ * Update an array of bytes to be signed or verified.
135+ */
136+ protected void engineUpdate(byte[] data, int off, int len) {
137+ dataSHA.update(data, off, len);
138+ }
139+
140+ protected void engineUpdate(ByteBuffer b) {
141+ dataSHA.update(b);
142+ }
143+
144+ byte[] getDigest() {
145+ return dataSHA.digest();
146+ }
147+
148+ void resetDigest() {
149+ dataSHA.reset();
150+ }
151+ }
152+
153+ /**
154+ * RawDSA implementation.
155+ *
156+ * RawDSA requires the data to be exactly 20 bytes long. If it is
157+ * not, a SignatureException is thrown when sign()/verify() is called
158+ * per JCA spec.
159+ */
160+ public static final class RawDSA extends DSA {
161+
162+ // length of the SHA-1 digest (20 bytes)
163+ private final static int SHA1_LEN = 20;
164+
165+ // 20 byte digest buffer
166+ private final byte[] digestBuffer;
167+
168+ // offset into the buffer
169+ private int ofs;
170+
171+ public RawDSA() {
172+ digestBuffer = new byte[SHA1_LEN];
173+ }
174+
175+ protected void engineUpdate(byte b) {
176+ if (ofs == SHA1_LEN) {
177+ ofs = SHA1_LEN + 1;
178+ return;
179+ }
180+ digestBuffer[ofs++] = b;
181+ }
182+
183+ protected void engineUpdate(byte[] data, int off, int len) {
184+ if (ofs + len > SHA1_LEN) {
185+ ofs = SHA1_LEN + 1;
186+ return;
187+ }
188+ System.arraycopy(data, off, digestBuffer, ofs, len);
189+ ofs += len;
190+ }
191+
192+ byte[] getDigest() throws SignatureException {
193+ if (ofs != SHA1_LEN) {
194+ throw new SignatureException
195+ ("Data for RawDSA must be exactly 20 bytes long");
196+ }
197+ ofs = 0;
198+ return digestBuffer;
199+ }
200+
201+ void resetDigest() {
202+ ofs = 0;
203+ }
204+ }
205+
206+ /**
207+ * Initialize the DSA object with a DSA private key.
208+ *
209+ * @param privateKey the DSA private key
210+ *
211+ * @exception InvalidKeyException if the key is not a valid DSA private
212+ * key.
213+ */
214+ protected void engineInitSign(PrivateKey privateKey)
215+ throws InvalidKeyException {
216+ if (!(privateKey instanceof java.security.interfaces.DSAPrivateKey)) {
217+ throw new InvalidKeyException("not a DSA private key: " +
218+ privateKey);
219+ }
220+ java.security.interfaces.DSAPrivateKey priv =
221+ (java.security.interfaces.DSAPrivateKey)privateKey;
222+ this.presetX = priv.getX();
223+ this.presetY = null;
224+ initialize(priv.getParams());
225+ }
226+
227+ /**
228+ * Initialize the DSA object with a DSA public key.
229+ *
230+ * @param publicKey the DSA public key.
231+ *
232+ * @exception InvalidKeyException if the key is not a valid DSA public
233+ * key.
234+ */
235+ protected void engineInitVerify(PublicKey publicKey)
236+ throws InvalidKeyException {
237+ if (!(publicKey instanceof java.security.interfaces.DSAPublicKey)) {
238+ throw new InvalidKeyException("not a DSA public key: " +
239+ publicKey);
240+ }
241+ java.security.interfaces.DSAPublicKey pub =
242+ (java.security.interfaces.DSAPublicKey)publicKey;
243+ this.presetY = pub.getY();
244+ this.presetX = null;
245+ initialize(pub.getParams());
246+ }
247+
248+ private void initialize(DSAParams params) throws InvalidKeyException {
249+ resetDigest();
250+ setParams(params);
251+ }
252+
253+ /**
254+ * Sign all the data thus far updated. The signature is formatted
255+ * according to the Canonical Encoding Rules, returned as a DER
256+ * sequence of Integer, r and s.
257+ *
258+ * @return a signature block formatted according to the Canonical
259+ * Encoding Rules.
260+ *
261+ * @exception SignatureException if the signature object was not
262+ * properly initialized, or if another exception occurs.
263+ *
264+ * @see sun.security.DSA#engineUpdate
265+ * @see sun.security.DSA#engineVerify
266+ */
267+ protected byte[] engineSign() throws SignatureException {
268+ BigInteger k = generateK(presetQ);
269+ BigInteger r = generateR(presetP, presetQ, presetG, k);
270+ BigInteger s = generateS(presetX, presetQ, r, k);
271+
272+ try {
273+ DerOutputStream outseq = new DerOutputStream(100);
274+ outseq.putInteger(r);
275+ outseq.putInteger(s);
276+ DerValue result = new DerValue(DerValue.tag_Sequence,
277+ outseq.toByteArray());
278+
279+ return result.toByteArray();
280+
281+ } catch (IOException e) {
282+ throw new SignatureException("error encoding signature");
283+ }
284+ }
285+
286+ /**
287+ * Verify all the data thus far updated.
288+ *
289+ * @param signature the alledged signature, encoded using the
290+ * Canonical Encoding Rules, as a sequence of integers, r and s.
291+ *
292+ * @exception SignatureException if the signature object was not
293+ * properly initialized, or if another exception occurs.
294+ *
295+ * @see sun.security.DSA#engineUpdate
296+ * @see sun.security.DSA#engineSign
297+ */
298+ protected boolean engineVerify(byte[] signature)
299+ throws SignatureException {
300+ return engineVerify(signature, 0, signature.length);
301+ }
302+
303+ /**
304+ * Verify all the data thus far updated.
305+ *
306+ * @param signature the alledged signature, encoded using the
307+ * Canonical Encoding Rules, as a sequence of integers, r and s.
308+ *
309+ * @param offset the offset to start from in the array of bytes.
310+ *
311+ * @param length the number of bytes to use, starting at offset.
312+ *
313+ * @exception SignatureException if the signature object was not
314+ * properly initialized, or if another exception occurs.
315+ *
316+ * @see sun.security.DSA#engineUpdate
317+ * @see sun.security.DSA#engineSign
318+ */
319+ protected boolean engineVerify(byte[] signature, int offset, int length)
320+ throws SignatureException {
321+
322+ BigInteger r = null;
323+ BigInteger s = null;
324+ // first decode the signature.
325+ try {
326+ DerInputStream in = new DerInputStream(signature, offset, length);
327+ DerValue[] values = in.getSequence(2);
328+
329+ r = values[0].getBigInteger();
330+ s = values[1].getBigInteger();
331+
332+ } catch (IOException e) {
333+ throw new SignatureException("invalid encoding for signature");
334+ }
335+
336+ // some implementations do not correctly encode values in the ASN.1
337+ // 2's complement format. force r and s to be positive in order to
338+ // to validate those signatures
339+ if (r.signum() < 0) {
340+ r = new BigInteger(1, r.toByteArray());
341+ }
342+ if (s.signum() < 0) {
343+ s = new BigInteger(1, s.toByteArray());
344+ }
345+
346+ if ((r.compareTo(presetQ) == -1) && (s.compareTo(presetQ) == -1)) {
347+ BigInteger w = generateW(presetP, presetQ, presetG, s);
348+ BigInteger v = generateV(presetY, presetP, presetQ, presetG, w, r);
349+ return v.equals(r);
350+ } else {
351+ throw new SignatureException("invalid signature: out of range values");
352+ }
353+ }
354+
355+ private BigInteger generateR(BigInteger p, BigInteger q, BigInteger g,
356+ BigInteger k) {
357+ BigInteger temp = g.modPow(k, p);
358+ return temp.remainder(q);
359+ }
360+
361+ private BigInteger generateS(BigInteger x, BigInteger q,
362+ BigInteger r, BigInteger k) throws SignatureException {
363+
364+ byte[] s2 = getDigest();
365+ BigInteger temp = new BigInteger(1, s2);
366+ BigInteger k1 = k.modInverse(q);
367+
368+ BigInteger s = x.multiply(r);
369+ s = temp.add(s);
370+ s = k1.multiply(s);
371+ return s.remainder(q);
372+ }
373+
374+ private BigInteger generateW(BigInteger p, BigInteger q,
375+ BigInteger g, BigInteger s) {
376+ return s.modInverse(q);
377+ }
378+
379+ private BigInteger generateV(BigInteger y, BigInteger p,
380+ BigInteger q, BigInteger g, BigInteger w, BigInteger r)
381+ throws SignatureException {
382+
383+ byte[] s2 = getDigest();
384+ BigInteger temp = new BigInteger(1, s2);
385+
386+ temp = temp.multiply(w);
387+ BigInteger u1 = temp.remainder(q);
388+
389+ BigInteger u2 = (r.multiply(w)).remainder(q);
390+
391+ BigInteger t1 = g.modPow(u1,p);
392+ BigInteger t2 = y.modPow(u2,p);
393+ BigInteger t3 = t1.multiply(t2);
394+ BigInteger t5 = t3.remainder(p);
395+ return t5.remainder(q);
396+ }
397+
398+ /*
399+ * Please read bug report 4044247 for an alternative, faster,
400+ * NON-FIPS approved method to generate K
401+ */
402+ private BigInteger generateK(BigInteger q) {
403+
404+ BigInteger k = null;
405+
406+ // The application specified a Kseed for us to use.
407+ // Note that we do not allow usage of the same Kseed twice in a row
408+ if (Kseed != null && !Arrays.equals(Kseed, previousKseed)) {
409+ k = generateK(Kseed, q);
410+ if (k.signum() > 0 && k.compareTo(q) < 0) {
411+ previousKseed = new int [Kseed.length];
412+ System.arraycopy(Kseed, 0, previousKseed, 0, Kseed.length);
413+ return k;
414+ }
415+ }
416+
417+ // The application did not specify a Kseed for us to use.
418+ // We'll generate a new Kseed by getting random bytes from
419+ // a SecureRandom object.
420+ SecureRandom random = getSigningRandom();
421+
422+ while (true) {
423+ int[] seed = new int[5];
424+
425+ for (int i = 0; i < 5; i++)
426+ seed[i] = random.nextInt();
427+ k = generateK(seed, q);
428+ if (k.signum() > 0 && k.compareTo(q) < 0) {
429+ previousKseed = new int [seed.length];
430+ System.arraycopy(seed, 0, previousKseed, 0, seed.length);
431+ return k;
432+ }
433+ }
434+ }
435+
436+ // Use the application-specified SecureRandom Object if provided.
437+ // Otherwise, use our default SecureRandom Object.
438+ private SecureRandom getSigningRandom() {
439+ if (signingRandom == null) {
440+ if (appRandom != null) {
441+ signingRandom = appRandom;
442+ } else {
443+ signingRandom = JCAUtil.getSecureRandom();
444+ }
445+ }
446+ return signingRandom;
447+ }
448+
449+ /**
450+ * Compute k for a DSA signature.
451+ *
452+ * @param seed the seed for generating k. This seed should be
453+ * secure. This is what is refered to as the KSEED in the DSA
454+ * specification.
455+ *
456+ * @param g the g parameter from the DSA key pair.
457+ */
458+ private BigInteger generateK(int[] seed, BigInteger q) {
459+
460+ // check out t in the spec.
461+ int[] t = { 0xEFCDAB89, 0x98BADCFE, 0x10325476,
462+ 0xC3D2E1F0, 0x67452301 };
463+ //
464+ int[] tmp = DSA.SHA_7(seed, t);
465+ byte[] tmpBytes = new byte[tmp.length * 4];
466+ for (int i = 0; i < tmp.length; i++) {
467+ int k = tmp[i];
468+ for (int j = 0; j < 4; j++) {
469+ tmpBytes[(i * 4) + j] = (byte) (k >>> (24 - (j * 8)));
470+ }
471+ }
472+ BigInteger k = new BigInteger(1, tmpBytes).mod(q);
473+ return k;
474+ }
475+
476+ // Constants for each round
477+ private static final int round1_kt = 0x5a827999;
478+ private static final int round2_kt = 0x6ed9eba1;
479+ private static final int round3_kt = 0x8f1bbcdc;
480+ private static final int round4_kt = 0xca62c1d6;
481+
482+ /**
483+ * Computes set 1 thru 7 of SHA-1 on m1. */
484+ static int[] SHA_7(int[] m1, int[] h) {
485+
486+ int[] W = new int[80];
487+ System.arraycopy(m1,0,W,0,m1.length);
488+ int temp = 0;
489+
490+ for (int t = 16; t <= 79; t++){
491+ temp = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
492+ W[t] = ((temp << 1) | (temp >>>(32 - 1)));
493+ }
494+
495+ int a = h[0],b = h[1],c = h[2], d = h[3], e = h[4];
496+ for (int i = 0; i < 20; i++) {
497+ temp = ((a<<5) | (a>>>(32-5))) +
498+ ((b&c)|((~b)&d))+ e + W[i] + round1_kt;
499+ e = d;
500+ d = c;
501+ c = ((b<<30) | (b>>>(32-30)));
502+ b = a;
503+ a = temp;
504+ }
505+
506+ // Round 2
507+ for (int i = 20; i < 40; i++) {
508+ temp = ((a<<5) | (a>>>(32-5))) +
509+ (b ^ c ^ d) + e + W[i] + round2_kt;
510+ e = d;
511+ d = c;
512+ c = ((b<<30) | (b>>>(32-30)));
513+ b = a;
514+ a = temp;
515+ }
516+
517+ // Round 3
518+ for (int i = 40; i < 60; i++) {
519+ temp = ((a<<5) | (a>>>(32-5))) +
520+ ((b&c)|(b&d)|(c&d)) + e + W[i] + round3_kt;
521+ e = d;
522+ d = c;
523+ c = ((b<<30) | (b>>>(32-30)));
524+ b = a;
525+ a = temp;
526+ }
527+
528+ // Round 4
529+ for (int i = 60; i < 80; i++) {
530+ temp = ((a<<5) | (a>>>(32-5))) +
531+ (b ^ c ^ d) + e + W[i] + round4_kt;
532+ e = d;
533+ d = c;
534+ c = ((b<<30) | (b>>>(32-30)));
535+ b = a;
536+ a = temp;
537+ }
538+ int[] md = new int[5];
539+ md[0] = h[0] + a;
540+ md[1] = h[1] + b;
541+ md[2] = h[2] + c;
542+ md[3] = h[3] + d;
543+ md[4] = h[4] + e;
544+ return md;
545+ }
546+
547+
548+ /**
549+ * This implementation recognizes the following parameter:<dl>
550+ *
551+ * <dt><tt>Kseed</tt>
552+ *
553+ * <dd>a byte array.
554+ *
555+ * </dl>
556+ *
557+ * @deprecated
558+ */
559+ @Deprecated
560+ protected void engineSetParameter(String key, Object param) {
561+ if (key.equals("KSEED")) {
562+ if (param instanceof byte[]) {
563+ Kseed = byteArray2IntArray((byte[])param);
564+ KseedAsByteArray = (byte[])param;
565+ } else {
566+ debug("unrecognized param: " + key);
567+ throw new InvalidParameterException("Kseed not a byte array");
568+ }
569+ } else {
570+ throw new InvalidParameterException("invalid parameter");
571+ }
572+ }
573+
574+ /**
575+ * Return the value of the requested parameter. Recognized
576+ * parameters are:
577+ *
578+ * <dl>
579+ *
580+ * <dt><tt>Kseed</tt>
581+ *
582+ * <dd>a byte array.
583+ *
584+ * </dl>
585+ *
586+ * @return the value of the requested parameter.
587+ *
588+ * @see java.security.SignatureEngine
589+ *
590+ * @deprecated
591+ */
592+ @Deprecated
593+ protected Object engineGetParameter(String key) {
594+ if (key.equals("KSEED")) {
595+ return KseedAsByteArray;
596+ } else {
597+ return null;
598+ }
599+ }
600+
601+ /**
602+ * Set the algorithm object.
603+ */
604+ private void setParams(DSAParams params) throws InvalidKeyException {
605+ if (params == null) {
606+ throw new InvalidKeyException("DSA public key lacks parameters");
607+ }
608+ this.params = params;
609+ this.presetP = params.getP();
610+ this.presetQ = params.getQ();
611+ this.presetG = params.getG();
612+ }
613+
614+ /**
615+ * Return a human readable rendition of the engine.
616+ */
617+ public String toString() {
618+ String printable = "DSA Signature";
619+ if (presetP != null && presetQ != null && presetG != null) {
620+ printable += "\n\tp: " + Debug.toHexString(presetP);
621+ printable += "\n\tq: " + Debug.toHexString(presetQ);
622+ printable += "\n\tg: " + Debug.toHexString(presetG);
623+ } else {
624+ printable += "\n\t P, Q or G not initialized.";
625+ }
626+ if (presetY != null) {
627+ printable += "\n\ty: " + Debug.toHexString(presetY);
628+ }
629+ if (presetY == null && presetX == null) {
630+ printable += "\n\tUNINIIALIZED";
631+ }
632+ return printable;
633+ }
634+
635+ /*
636+ * Utility routine for converting a byte array into an int array
637+ */
638+ private int[] byteArray2IntArray(byte[] byteArray) {
639+
640+ int j = 0;
641+ byte[] newBA;
642+ int mod = byteArray.length % 4;
643+
644+ // guarantee that the incoming byteArray is a multiple of 4
645+ // (pad with 0's)
646+ switch (mod) {
647+ case 3: newBA = new byte[byteArray.length + 1]; break;
648+ case 2: newBA = new byte[byteArray.length + 2]; break;
649+ case 1: newBA = new byte[byteArray.length + 3]; break;
650+ default: newBA = new byte[byteArray.length + 0]; break;
651+ }
652+ System.arraycopy(byteArray, 0, newBA, 0, byteArray.length);
653+
654+ // copy each set of 4 bytes in the byte array into an integer
655+ int[] newSeed = new int[newBA.length / 4];
656+ for (int i = 0; i < newBA.length; i += 4) {
657+ newSeed[j] = newBA[i + 3] & 0xFF;
658+ newSeed[j] |= (newBA[i + 2] << 8) & 0xFF00;
659+ newSeed[j] |= (newBA[i + 1] << 16) & 0xFF0000;
660+ newSeed[j] |= (newBA[i + 0] << 24) & 0xFF000000;
661+ j++;
662+ }
663+
664+ return newSeed;
665+ }
666+
667+ private static void debug(Exception e) {
668+ if (debug) {
669+ e.printStackTrace();
670+ }
671+ }
672+
673+ private static void debug(String s) {
674+ if (debug) {
675+ System.err.println(s);
676+ }
677+ }
678+}