View Javadoc
1   /*
2    * Copyright (c) 1996, 2013, 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.x509;
27  
28  import java.io.IOException;
29  import java.math.BigInteger;
30  import java.security.*;
31  import java.security.interfaces.DSAParams;
32  
33  import sun.security.util.*;
34  
35  
36  /**
37   * This class identifies DSS/DSA Algorithm variants, which are distinguished
38   * by using different algorithm parameters <em>P, Q, G</em>.  It uses the
39   * NIST/IETF standard DER encoding.  These are used to implement the Digital
40   * Signature Standard (DSS), FIPS 186.
41   *
42   * <P><em><b>NOTE:</b>  DSS/DSA Algorithm IDs may be created without these
43   * parameters.  Use of DSS/DSA in modes where parameters are
44   * either implicit (e.g. a default applicable to a site or a larger scope),
45   * or are derived from some Certificate Authority's DSS certificate, is
46   * not supported directly.  The application is responsible for creating a key
47   * containing the required parameters prior to using the key in cryptographic
48   * operations.  The follwoing is an example of how this may be done assuming
49   * that we have a certificate called <code>currentCert</code> which doesn't
50   * contain DSS/DSA parameters and we need to derive DSS/DSA parameters
51   * from a CA's certificate called <code>caCert</code>.
52   * <p>
53   * <code><pre>
54   * // key containing parameters to use
55   * DSAPublicKey cAKey = (DSAPublicKey)(caCert.getPublicKey());
56   * // key without parameters
57   * DSAPublicKey nullParamsKey = (DSAPublicKey)(currentCert.getPublicKey());
58   *
59   * DSAParams cAKeyParams = cAKey.getParams();
60   * KeyFactory kf = KeyFactory.getInstance("DSA");
61   * DSAPublicKeySpec ks = new DSAPublicKeySpec(nullParamsKey.getY(),
62   *                                            cAKeyParams.getP(),
63   *                                            cAKeyParams.getQ(),
64   *                                            cAKeyParams.getG());
65   * DSAPublicKey usableKey = kf.generatePublic(ks);
66   * </pre></code>
67   *
68   * @see java.security.interfaces.DSAParams
69   * @see java.security.interfaces.DSAPublicKey
70   * @see java.security.KeyFactory
71   * @see java.security.spec.DSAPublicKeySpec
72   *
73   * @author David Brownell
74   */
75  public final
76  class AlgIdDSA extends AlgorithmId implements DSAParams
77  {
78  
79      private static final long serialVersionUID = 3437177836797504046L;
80  
81      /*
82       * The three unsigned integer parameters.
83       */
84      private BigInteger  p , q, g;
85  
86      /** Returns the DSS/DSA parameter "P" */
87      public BigInteger   getP () { return p; }
88  
89      /** Returns the DSS/DSA parameter "Q" */
90      public BigInteger   getQ () { return q; }
91  
92      /** Returns the DSS/DSA parameter "G" */
93      public BigInteger   getG () { return g; }
94  
95      /**
96       * Default constructor.  The OID and parameters must be
97       * deserialized before this algorithm ID is used.
98       */
99      @Deprecated
100     public AlgIdDSA () {}
101 
102     AlgIdDSA (DerValue val) throws IOException
103         { super(val.getOID()); }
104 
105     /**
106      * Construct an AlgIdDSA from an X.509 encoded byte array.
107      */
108     public AlgIdDSA (byte[] encodedAlg) throws IOException
109         { super (new DerValue(encodedAlg).getOID()); }
110 
111     /**
112      * Constructs a DSS/DSA Algorithm ID from unsigned integers that
113      * define the algorithm parameters.  Those integers are encoded
114      * as big-endian byte arrays.
115      *
116      * @param p the DSS/DSA parameter "P"
117      * @param q the DSS/DSA parameter "Q"
118      * @param g the DSS/DSA parameter "G"
119      */
120     public AlgIdDSA (byte p [], byte q [], byte g [])
121     throws IOException
122     {
123         this (new BigInteger (1, p),
124             new BigInteger (1, q),
125             new BigInteger (1, g));
126     }
127 
128     /**
129      * Constructs a DSS/DSA Algorithm ID from numeric parameters.
130      * If all three are null, then the parameters portion of the algorithm id
131      * is set to null.  See note in header regarding use.
132      *
133      * @param p the DSS/DSA parameter "P"
134      * @param q the DSS/DSA parameter "Q"
135      * @param g the DSS/DSA parameter "G"
136      */
137     public AlgIdDSA (BigInteger p, BigInteger q, BigInteger g)
138     {
139         super (DSA_oid);
140 
141         if (p != null || q != null || g != null) {
142             if (p == null || q == null || g == null)
143                 throw new ProviderException("Invalid parameters for DSS/DSA" +
144                                             " Algorithm ID");
145             try {
146                 this.p = p;
147                 this.q = q;
148                 this.g = g;
149                 initializeParams ();
150 
151             } catch (IOException e) {
152                 /* this should not happen */
153                 throw new ProviderException ("Construct DSS/DSA Algorithm ID");
154             }
155         }
156     }
157 
158     /**
159      * Returns "DSA", indicating the Digital Signature Algorithm (DSA) as
160      * defined by the Digital Signature Standard (DSS), FIPS 186.
161      */
162     public String getName ()
163         { return "DSA"; }
164 
165 
166     /*
167      * For algorithm IDs which haven't been created from a DER encoded
168      * value, "params" must be created.
169      */
170     private void initializeParams ()
171     throws IOException
172     {
173         DerOutputStream out = new DerOutputStream ();
174 
175         out.putInteger(p);
176         out.putInteger(q);
177         out.putInteger(g);
178         params = new DerValue (DerValue.tag_Sequence,out.toByteArray ());
179     }
180 
181     /**
182      * Parses algorithm parameters P, Q, and G.  They're found
183      * in the "params" member, which never needs to be changed.
184      */
185     protected void decodeParams ()
186     throws IOException
187     {
188         if (params == null)
189             throw new IOException("DSA alg params are null");
190         if (params.tag != DerValue.tag_Sequence)
191             throw new  IOException("DSA alg parsing error");
192 
193         params.data.reset ();
194 
195         this.p = params.data.getBigInteger();
196         this.q = params.data.getBigInteger();
197         this.g = params.data.getBigInteger();
198 
199         if (params.data.available () != 0)
200             throw new IOException ("AlgIdDSA params, extra="+
201                                    params.data.available ());
202     }
203 
204 
205     /*
206      * Returns a formatted string describing the parameters.
207      */
208     public String toString ()
209         { return paramsToString (); }
210 
211     /*
212      * Returns a string describing the parameters.
213      */
214     protected String paramsToString ()
215     {
216         if (params == null)
217             return " null\n";
218         else
219             return
220                 "\n    p:\n" + Debug.toHexString(p) +
221                 "\n    q:\n" + Debug.toHexString(q) +
222                 "\n    g:\n" + Debug.toHexString(g) +
223                 "\n";
224     }
225 }