Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / gnu / java / security / key / dss / DSSKeyPairPKCS8Codec.java
blob3a115b96378417505ee6b156e084e2fd10e1f68c
1 /* DSSKeyPairPKCS8Codec.java -- PKCS#8 Encoding/Decoding handler
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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, or (at your option)
9 any later version.
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.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
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.
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. */
39 package gnu.java.security.key.dss;
41 import gnu.java.security.OID;
42 import gnu.java.security.Registry;
43 import gnu.java.security.der.DER;
44 import gnu.java.security.der.DERReader;
45 import gnu.java.security.der.DERValue;
46 import gnu.java.security.der.DERWriter;
47 import gnu.java.security.key.IKeyPairCodec;
48 import gnu.java.security.util.DerUtil;
49 import gnu.java.security.util.Util;
51 import java.io.ByteArrayOutputStream;
52 import java.io.IOException;
53 import java.math.BigInteger;
54 import java.security.InvalidParameterException;
55 import java.security.PrivateKey;
56 import java.security.PublicKey;
57 import java.util.ArrayList;
58 import java.util.logging.Logger;
60 /**
61 * An implementation of an {@link IKeyPairCodec} that knows how to encode /
62 * decode PKCS#8 ASN.1 external representation of DSS private keys.
64 * @author Casey Marshall (rsdio@metastatic.org)
66 public class DSSKeyPairPKCS8Codec
67 implements IKeyPairCodec
69 private static final Logger log = Logger.getLogger(DSSKeyPairPKCS8Codec.class.getName());
70 private static final OID DSA_ALG_OID = new OID(Registry.DSA_OID_STRING);
72 // implicit 0-arguments constructor
74 public int getFormatID()
76 return PKCS8_FORMAT;
79 /**
80 * @throws InvalidParameterException ALWAYS.
82 public byte[] encodePublicKey(PublicKey key)
84 throw new InvalidParameterException("Wrong format for public keys");
87 /**
88 * Returns the PKCS#8 ASN.1 <i>PrivateKeyInfo</i> representation of a DSA
89 * private key. The ASN.1 specification is as follows:
91 * <pre>
92 * PrivateKeyInfo ::= SEQUENCE {
93 * version INTEGER, -- MUST be 0
94 * privateKeyAlgorithm AlgorithmIdentifier,
95 * privateKey OCTET STRING
96 * }
98 * AlgorithmIdentifier ::= SEQUENCE {
99 * algorithm OBJECT IDENTIFIER,
100 * parameters ANY DEFINED BY algorithm OPTIONAL
103 * DssParams ::= SEQUENCE {
104 * p INTEGER,
105 * q INTEGER,
106 * g INTEGER
108 * </pre>
110 * @return the DER encoded form of the ASN.1 representation of the
111 * <i>PrivateKeyInfo</i> field in an X.509 certificate.
112 * @throw InvalidParameterException if an error occurs during the marshalling
113 * process.
115 public byte[] encodePrivateKey(PrivateKey key)
117 if (! (key instanceof DSSPrivateKey))
118 throw new InvalidParameterException("Wrong key type");
120 DERValue derVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
122 DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DSA_ALG_OID);
124 DSSPrivateKey pk = (DSSPrivateKey) key;
125 BigInteger p = pk.getParams().getP();
126 BigInteger q = pk.getParams().getQ();
127 BigInteger g = pk.getParams().getG();
128 BigInteger x = pk.getX();
130 ArrayList params = new ArrayList(3);
131 params.add(new DERValue(DER.INTEGER, p));
132 params.add(new DERValue(DER.INTEGER, q));
133 params.add(new DERValue(DER.INTEGER, g));
134 DERValue derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
136 ArrayList algorithmID = new ArrayList(2);
137 algorithmID.add(derOID);
138 algorithmID.add(derParams);
139 DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
140 algorithmID);
142 // The OCTET STRING is the DER encoding of an INTEGER.
143 DERValue derX = new DERValue(DER.INTEGER, x);
144 DERValue derPrivateKey = new DERValue(DER.OCTET_STRING, derX.getEncoded());
146 ArrayList pki = new ArrayList(3);
147 pki.add(derVersion);
148 pki.add(derAlgorithmID);
149 pki.add(derPrivateKey);
150 DERValue derPKI = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, pki);
152 byte[] result;
153 ByteArrayOutputStream baos = new ByteArrayOutputStream();
156 DERWriter.write(baos, derPKI);
157 result = baos.toByteArray();
159 catch (IOException e)
161 InvalidParameterException y = new InvalidParameterException();
162 y.initCause(e);
163 throw y;
166 return result;
170 * @throws InvalidParameterException ALWAYS.
172 public PublicKey decodePublicKey(byte[] input)
174 throw new InvalidParameterException("Wrong format for public keys");
178 * @param input the byte array to unmarshall into a valid DSS
179 * {@link PrivateKey} instance. MUST NOT be null.
180 * @return a new instance of a {@link DSSPrivateKey} decoded from the
181 * <i>PrivateKeyInfo</i> material fed as <code>input</code>.
182 * @throw InvalidParameterException if an exception occurs during the
183 * unmarshalling process.
185 public PrivateKey decodePrivateKey(byte[] input)
187 log.entering("DSSKeyPairPKCS8Codec", "decodePrivateKey");
189 if (input == null)
190 throw new InvalidParameterException("Input bytes MUST NOT be null");
192 BigInteger version, p, q, g, x;
193 DERReader der = new DERReader(input);
196 DERValue derPKI = der.read();
197 DerUtil.checkIsConstructed(derPKI, "Wrong PrivateKeyInfo field");
199 DERValue derVersion = der.read();
200 if (! (derVersion.getValue() instanceof BigInteger))
201 throw new InvalidParameterException("Wrong Version field");
203 version = (BigInteger) derVersion.getValue();
204 if (version.compareTo(BigInteger.ZERO) != 0)
205 throw new InvalidParameterException("Unexpected Version: " + version);
207 DERValue derAlgoritmID = der.read();
208 DerUtil.checkIsConstructed(derAlgoritmID, "Wrong AlgorithmIdentifier field");
210 DERValue derOID = der.read();
211 OID algOID = (OID) derOID.getValue();
212 if (! algOID.equals(DSA_ALG_OID))
213 throw new InvalidParameterException("Unexpected OID: " + algOID);
215 DERValue derParams = der.read();
216 DerUtil.checkIsConstructed(derParams, "Wrong DSS Parameters field");
218 DERValue val = der.read();
219 DerUtil.checkIsBigInteger(val, "Wrong P field");
220 p = (BigInteger) val.getValue();
221 val = der.read();
222 DerUtil.checkIsBigInteger(val, "Wrong Q field");
223 q = (BigInteger) val.getValue();
224 val = der.read();
225 DerUtil.checkIsBigInteger(val, "Wrong G field");
226 g = (BigInteger) val.getValue();
228 val = der.read();
229 log.finest("val = " + val);
230 byte[] xBytes = (byte[]) val.getValue();
231 log.finest(Util.dumpString(xBytes, "xBytes: "));
232 DERReader der2 = new DERReader(xBytes);
233 val = der2.read();
234 DerUtil.checkIsBigInteger(val, "Wrong X field");
235 x = (BigInteger) val.getValue();
237 catch (IOException e)
239 InvalidParameterException y = new InvalidParameterException();
240 y.initCause(e);
241 throw y;
244 log.exiting("DSSKeyPairPKCS8Codec", "decodePrivateKey");
245 return new DSSPrivateKey(Registry.PKCS8_ENCODING_ID, p, q, g, x);