001: /*
002: * @(#)AlgIdDSA.java 1.42 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.security.x509;
029:
030: import java.io.IOException;
031: import java.math.BigInteger;
032: import java.security.*;
033: import java.security.interfaces.DSAParams;
034:
035: import sun.security.util.*;
036:
037: /**
038: * This class identifies DSS/DSA Algorithm variants, which are distinguished
039: * by using different algorithm parameters <em>P, Q, G</em>. It uses the
040: * NIST/IETF standard DER encoding. These are used to implement the Digital
041: * Signature Standard (DSS), FIPS 186.
042: *
043: * <P><em><b>NOTE:</b> DSS/DSA Algorithm IDs may be created without these
044: * parameters. Use of DSS/DSA in modes where parameters are
045: * either implicit (e.g. a default applicable to a site or a larger scope),
046: * or are derived from some Certificate Authority's DSS certificate, is
047: * not supported directly. The application is responsible for creating a key
048: * containing the required parameters prior to using the key in cryptographic
049: * operations. The follwoing is an example of how this may be done assuming
050: * that we have a certificate called <code>currentCert</code> which doesn't
051: * contain DSS/DSA parameters and we need to derive DSS/DSA parameters
052: * from a CA's certificate called <code>caCert</code>.
053: * <p>
054: * <code><pre>
055: * // key containing parameters to use
056: * DSAPublicKey cAKey = (DSAPublicKey)(caCert.getPublicKey());
057: * // key without parameters
058: * DSAPublicKey nullParamsKey = (DSAPublicKey)(currentCert.getPublicKey());
059: *
060: * DSAParams cAKeyParams = cAKey.getParams();
061: * KeyFactory kf = KeyFactory.getInstance("DSA");
062: * DSAPublicKeySpec ks = new DSAPublicKeySpec(nullParamsKey.getY(),
063: * cAKeyParams.getP(),
064: * cAKeyParams.getQ(),
065: * cAKeyParams.getG());
066: * DSAPublicKey usableKey = kf.generatePublic(ks);
067: * </pre></code>
068: *
069: * @see java.security.interfaces.DSAParams
070: * @see java.security.interfaces.DSAPublicKey
071: * @see java.security.KeyFactory
072: * @see java.security.spec.DSAPublicKeySpec
073: *
074: * @version 1.42, 10/10/06
075: * @author David Brownell
076: */
077: public final class AlgIdDSA extends AlgorithmId implements DSAParams {
078: /*
079: * The three unsigned integer parameters.
080: */
081: private BigInteger p, q, g;
082:
083: /** Returns the DSS/DSA parameter "P" */
084: public BigInteger getP() {
085: return p;
086: }
087:
088: /** Returns the DSS/DSA parameter "Q" */
089: public BigInteger getQ() {
090: return q;
091: }
092:
093: /** Returns the DSS/DSA parameter "G" */
094: public BigInteger getG() {
095: return g;
096: }
097:
098: /**
099: * Default constructor. The OID and parameters must be
100: * deserialized before this algorithm ID is used.
101: */
102: // NOTE: deprecated for general use
103: public AlgIdDSA() {
104: }
105:
106: AlgIdDSA(DerValue val) throws IOException {
107: super (val.getOID());
108: }
109:
110: /**
111: * Construct an AlgIdDSA from an X.509 encoded byte array.
112: */
113: public AlgIdDSA(byte[] encodedAlg) throws IOException {
114: super (new DerValue(encodedAlg).getOID());
115: }
116:
117: /**
118: * Constructs a DSS/DSA Algorithm ID from unsigned integers that
119: * define the algorithm parameters. Those integers are encoded
120: * as big-endian byte arrays.
121: *
122: * @param p the DSS/DSA paramter "P"
123: * @param q the DSS/DSA paramter "Q"
124: * @param g the DSS/DSA paramter "G"
125: */
126: public AlgIdDSA(byte p[], byte q[], byte g[]) throws IOException {
127: this (new BigInteger(1, p), new BigInteger(1, q),
128: new BigInteger(1, g));
129: }
130:
131: /**
132: * Constructs a DSS/DSA Algorithm ID from numeric parameters.
133: * If all three are null, then the parameters portion of the algorithm id
134: * is set to null. See note in header regarding use.
135: *
136: * @param p the DSS/DSA paramter "P"
137: * @param q the DSS/DSA paramter "Q"
138: * @param g the DSS/DSA paramter "G"
139: */
140: public AlgIdDSA(BigInteger p, BigInteger q, BigInteger g) {
141: super (DSA_oid);
142:
143: if (p != null || q != null || g != null) {
144: if (p == null || q == null || g == null)
145: throw new ProviderException(
146: "Invalid parameters for DSS/DSA"
147: + " Algorithm ID");
148: try {
149: this .p = p;
150: this .q = q;
151: this .g = g;
152: initializeParams();
153:
154: } catch (IOException e) {
155: /* this should not happen */
156: throw new ProviderException(
157: "Construct DSS/DSA Algorithm ID");
158: }
159: }
160: }
161:
162: /**
163: * Returns "DSA", indicating the Digital Signature Algorithm (DSA) as
164: * defined by the Digital Signature Standard (DSS), FIPS 186.
165: */
166: public String getName() {
167: return "DSA";
168: }
169:
170: /*
171: * For algorithm IDs which haven't been created from a DER encoded
172: * value, "params" must be created.
173: */
174: private void initializeParams() throws IOException {
175: DerOutputStream out = new DerOutputStream();
176:
177: out.putInteger(p);
178: out.putInteger(q);
179: out.putInteger(g);
180: params = new DerValue(DerValue.tag_Sequence, out.toByteArray());
181: }
182:
183: /**
184: * Parses algorithm parameters P, Q, and G. They're found
185: * in the "params" member, which never needs to be changed.
186: */
187: protected void decodeParams() throws IOException {
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: * Returns a formatted string describing the parameters.
206: */
207: public String toString() {
208: return paramsToString();
209: }
210:
211: /*
212: * Returns a string describing the parameters.
213: */
214: protected String paramsToString() {
215: if (params == null)
216: return " null\n";
217: else
218: return "\n p:\n" + Debug.toHexString(p) + "\n q:\n"
219: + Debug.toHexString(q) + "\n g:\n"
220: + Debug.toHexString(g) + "\n";
221: }
222: }
|