hello there, the attached patch fixes a bug in the gnu.java.security.der.DERWriter class and adds support for encoding/decoding ASN.1 forms of the DSS keys.
the ChangeLog is:
2006-02-07 Raif S. Naffah <[EMAIL PROTECTED]>
* gnu/java/security/key/KeyPairCodecFactory.java (getEncodingName): New
method.
(getEncodingShortName): Likewise.
* gnu/java/security/key/IKeyPairCodec.java (X509_FORMAT): New constant.
(PKCS8_FORMAT): Likewise.
(ASN1_FORMAT): Likewise.
* gnu/java/security/key/dss/DSSPublicKey.java (DSSPublicKey(4)): Call
constructor with 5 arguments.
(DSSPublicKey(5)): New constructor.
(valueOf): Handle ASN.1 encoding.
(getEncoded): Likewise.
* gnu/java/security/key/dss/DSSPrivateKey.java (DSSPrivateKey(4)): Call
constructor with 5 arguments.
(DSSPrivateKey(5)): New constructor.
(valueOf): Handle ASN.1 encoding.
(getEncoded): Likewise.
* gnu/java/security/key/dss/DSSKeyPairX509Codec.java: New file.
* gnu/java/security/key/dss/DSSKeyPairPKCS8Codec.java: Likewise.
* gnu/java/security/key/dss/DSSKeyPairGenerator.java
(PREFERRED_ENCODING_FORMAT): New constant.
(DEFAULT_ENCODING_FORMAT): Likewise.
(preferredFormat): New field.
(setup): Handle preferred format ID.
(generate): Use new ctors with 5 arguments.
* gnu/java/security/key/dss/DSSKey.java (DSSKey): Now accepts a format
ID as an additional argument.
(defaultFormat): new field.
(getFormat): Returns the preferred format as a short string.
* gnu/java/security/jce/sig/DSSKeyFactory.java: New file.
* gnu/java/security/jce/sig/EncodedKeyFactory.java (engineGetKeySpec):
Likewise
* gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java
(initialize(AlgorithmParameterSpec)): Set ASN.1 as the preferred
encoding format.
(initialize(int,boolean,SecureRandom)): Likewise.
* gnu/java/security/der/DERWriter.java (writeBitString): Use
writeLength() instead of write().
return buf.length + 1 instead of buf.length.
a new Mauve testlet (gnu.testlet.gnu.java.security.jce.TestOfFormat) has
been added and an existing one
(gnu.testlet.gnu.java.security.key.dss.TestOfDSSCodec) was changed to
test this new encoding format.
committed.
cheers;
rsn
Index: DERWriter.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/security/der/DERWriter.java,v
retrieving revision 1.6
diff -u -r1.6 DERWriter.java
--- DERWriter.java 2 Feb 2006 07:06:35 -0000 1.6
+++ DERWriter.java 7 Feb 2006 11:25:32 -0000
@@ -222,10 +222,10 @@
throws IOException
{
byte[] buf = bs.getShiftedByteArray();
- out.write(buf.length + 1);
+ writeLength(out, buf.length + 1);
out.write(bs.getIgnoredBits());
out.write(buf);
- return buf.length;
+ return buf.length + 1;
}
private static int writeString(OutputStream out, int tag, String str)
Index: DSSKeyPairGeneratorSpi.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java,v
retrieving revision 1.2
diff -u -r1.2 DSSKeyPairGeneratorSpi.java
--- DSSKeyPairGeneratorSpi.java 4 Feb 2006 01:13:16 -0000 1.2
+++ DSSKeyPairGeneratorSpi.java 7 Feb 2006 11:29:45 -0000
@@ -105,6 +105,8 @@
attributes.put(DSSKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
}
+ attributes.put(DSSKeyPairGenerator.PREFERRED_ENCODING_FORMAT,
+ new Integer(Registry.ASN1_ENCODING_ID));
try
{
adaptee.setup(attributes);
@@ -151,6 +153,8 @@
attributes.put(DSSKeyPairGenerator.USE_DEFAULTS,
Boolean.valueOf(!genParams));
attributes.put(DSSKeyPairGenerator.STRICT_DEFAULTS, Boolean.TRUE);
+ attributes.put(DSSKeyPairGenerator.PREFERRED_ENCODING_FORMAT,
+ new Integer(Registry.ASN1_ENCODING_ID));
try
{
adaptee.setup(attributes);
Index: DSSKeyFactory.java
===================================================================
RCS file: DSSKeyFactory.java
diff -N DSSKeyFactory.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DSSKeyFactory.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,128 @@
+/* DSSKeyFactory.java -- JCE DSA key factory Adapter
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.key.dss.DSSPrivateKey;
+import gnu.java.security.key.dss.DSSPublicKey;
+
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactorySpi;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAPrivateKeySpec;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+
+/**
+ * DSA key factory.
+ *
+ * @author Casey Marshall ([EMAIL PROTECTED])
+ */
+public class DSSKeyFactory extends KeyFactorySpi
+{
+ // implicit 0-arguments constructor
+
+ protected PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (!(keySpec instanceof DSAPublicKeySpec))
+ throw new InvalidKeySpecException();
+
+ return new DSSPublicKey(((DSAPublicKeySpec) keySpec).getY(),
+ ((DSAPublicKeySpec) keySpec).getP(),
+ ((DSAPublicKeySpec) keySpec).getQ(),
+ ((DSAPublicKeySpec) keySpec).getG());
+ }
+
+ protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (!(keySpec instanceof DSAPrivateKeySpec))
+ throw new InvalidKeySpecException();
+
+ return new DSSPrivateKey(((DSAPrivateKeySpec) keySpec).getX(),
+ ((DSAPrivateKeySpec) keySpec).getP(),
+ ((DSAPrivateKeySpec) keySpec).getQ(),
+ ((DSAPrivateKeySpec) keySpec).getG());
+ }
+
+ protected KeySpec engineGetKeySpec(Key key, Class keySpec)
+ throws InvalidKeySpecException
+ {
+ if ((key instanceof DSAPublicKey)
+ && keySpec.isAssignableFrom(DSAPublicKeySpec.class))
+ return new DSAPublicKeySpec(((DSAPublicKey) key).getY(),
+ ((DSAPublicKey) key).getParams().getP(),
+ ((DSAPublicKey) key).getParams().getQ(),
+ ((DSAPublicKey) key).getParams().getG());
+
+ if ((key instanceof DSAPrivateKey)
+ && keySpec.isAssignableFrom(DSAPrivateKeySpec.class))
+ return new DSAPrivateKeySpec(((DSAPrivateKey) key).getX(),
+ ((DSAPrivateKey) key).getParams().getP(),
+ ((DSAPrivateKey) key).getParams().getQ(),
+ ((DSAPrivateKey) key).getParams().getG());
+
+ throw new InvalidKeySpecException();
+ }
+
+ protected Key engineTranslateKey(Key key) throws InvalidKeyException
+ {
+ if ((key instanceof DSSPublicKey) || (key instanceof DSSPrivateKey))
+ return key;
+
+ if (key instanceof DSAPublicKey)
+ return new DSSPublicKey(((DSAPublicKey) key).getY(),
+ ((DSAPublicKey) key).getParams().getP(),
+ ((DSAPublicKey) key).getParams().getQ(),
+ ((DSAPublicKey) key).getParams().getG());
+
+ if (key instanceof DSAPrivateKey)
+ return new DSSPrivateKey(((DSAPrivateKey) key).getX(),
+ ((DSAPrivateKey) key).getParams().getP(),
+ ((DSAPrivateKey) key).getParams().getQ(),
+ ((DSAPrivateKey) key).getParams().getG());
+
+ throw new InvalidKeyException();
+ }
+}
Index: EncodedKeyFactory.java
===================================================================
RCS file: EncodedKeyFactory.java
diff -N EncodedKeyFactory.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ EncodedKeyFactory.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,133 @@
+/* EncodedKeyFactory.java -- JCE Encoded key factory Adapter
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.dss.DSSPrivateKey;
+import gnu.java.security.key.dss.DSSPublicKey;
+
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.Key;
+import java.security.KeyFactorySpi;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+/**
+ * A factory for keys encoded in either the X.509 format (for public keys) or
+ * the PKCS#8 format (for private keys).
+ */
+public class EncodedKeyFactory
+ extends KeyFactorySpi
+{
+ // implicit 0-arguments constructor
+
+ protected PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (! (keySpec instanceof X509EncodedKeySpec))
+ throw new InvalidKeySpecException("only supports X.509 key specs");
+
+ byte[] input = ((X509EncodedKeySpec) keySpec).getEncoded();
+
+ // try DSS
+ try
+ {
+ return DSSPublicKey.valueOf(input);
+ }
+ catch (InvalidParameterException ignored)
+ {
+ }
+
+ // FIXME: try RSA
+
+ // FIXME: try DH
+
+ throw new InvalidKeySpecException();
+ }
+
+ protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (! (keySpec instanceof PKCS8EncodedKeySpec))
+ throw new InvalidKeySpecException("only supports PKCS8 key specs");
+
+ byte[] input = ((PKCS8EncodedKeySpec) keySpec).getEncoded();
+
+ // try DSS
+ try
+ {
+ return DSSPrivateKey.valueOf(input);
+ }
+ catch (InvalidParameterException ignored)
+ {
+ }
+
+ // FIXME: try RSA
+
+ // FIXME: try DH
+
+ throw new InvalidKeySpecException();
+ }
+
+ protected KeySpec engineGetKeySpec(Key key, Class keySpec)
+ throws InvalidKeySpecException
+ {
+ if (key instanceof PublicKey
+ && Registry.X509_ENCODING_SORT_NAME.equalsIgnoreCase(key.getFormat())
+ && keySpec.isAssignableFrom(X509EncodedKeySpec.class))
+ return new X509EncodedKeySpec(key.getEncoded());
+
+ if (key instanceof PrivateKey
+ && Registry.PKCS8_ENCODING_SHORT_NAME.equalsIgnoreCase(key.getFormat())
+ && keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class))
+ return new PKCS8EncodedKeySpec(key.getEncoded());
+
+ throw new InvalidKeySpecException("Unsupported format or invalid key spec class");
+ }
+
+ protected Key engineTranslateKey(Key key) throws InvalidKeyException
+ {
+ throw new InvalidKeyException("Key translation not supported");
+ }
+}
Index: DSSKey.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/security/key/dss/DSSKey.java,v
retrieving revision 1.1
diff -u -r1.1 DSSKey.java
--- DSSKey.java 26 Jan 2006 02:25:10 -0000 1.1
+++ DSSKey.java 7 Feb 2006 11:39:52 -0000
@@ -40,6 +40,7 @@
import gnu.java.security.Registry;
import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.key.KeyPairCodecFactory;
import java.math.BigInteger;
import java.security.Key;
@@ -65,7 +66,6 @@
*/
public abstract class DSSKey implements Key, DSAKey
{
-
// Constants and variables
// -------------------------------------------------------------------------
@@ -90,20 +90,30 @@
*/
protected final BigInteger g;
+ /**
+ * Identifier of the default encoding format to use when externalizing the
+ * key material.
+ */
+ protected final int defaultFormat;
+
// Constructor(s)
// -------------------------------------------------------------------------
/**
- * <p>Trivial protected constructor.</p>
- *
+ * Trivial protected constructor.
+ *
+ * @param defaultFormat the identifier of the encoding format to use by
+ * default when externalizing the key.
* @param p the DSS parameter <code>p</code>.
* @param q the DSS parameter <code>q</code>.
* @param g the DSS parameter <code>g</code>.
*/
- protected DSSKey(BigInteger p, BigInteger q, BigInteger g)
+ protected DSSKey(int defaultFormat, BigInteger p, BigInteger q, BigInteger g)
{
super();
+ this.defaultFormat = defaultFormat <= 0 ? Registry.RAW_ENCODING_ID
+ : defaultFormat;
this.p = p;
this.q = q;
this.g = g;
@@ -137,7 +147,7 @@
public String getFormat()
{
- return null;
+ return KeyPairCodecFactory.getEncodingShortName(defaultFormat);
}
// Other instance methods --------------------------------------------------
Index: DSSKeyPairGenerator.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/security/key/dss/DSSKeyPairGenerator.java,v
retrieving revision 1.2
diff -u -r1.2 DSSKeyPairGenerator.java
--- DSSKeyPairGenerator.java 3 Feb 2006 19:29:01 -0000 1.2
+++ DSSKeyPairGenerator.java 7 Feb 2006 11:43:10 -0000
@@ -151,9 +151,19 @@
*/
public static final String DSS_PARAMETERS = "gnu.crypto.dss.params";
+ /**
+ * Property name of the preferred encoding format to use when externalizing
+ * generated instance of key-pairs from this generator. The property is taken
+ * to be an [EMAIL PROTECTED] Integer} that encapsulates an encoding format identifier.
+ */
+ public static final String PREFERRED_ENCODING_FORMAT = "gnu.crypto.dss.encoding";
+
/** Default value for the modulus length. */
private static final int DEFAULT_MODULUS_LENGTH = 1024;
+ /** Default encoding format to use when none was specified. */
+ private static final int DEFAULT_ENCODING_FORMAT = Registry.RAW_ENCODING_ID;
+
/** Initial SHS context. */
private static final int[] T_SHS = new int[] { 0x67452301, 0xEFCDAB89,
0x98BADCFE, 0x10325476,
@@ -230,6 +240,9 @@
/** Our default source of randomness. */
private PRNG prng = null;
+ /** Preferred encoding format of generated keys. */
+ private int preferredFormat;
+
// Constructor(s)
// -------------------------------------------------------------------------
@@ -325,6 +338,12 @@
// do we have a SecureRandom, or should we use our own?
rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+ // what is the preferred encoding format
+ Integer formatID = (Integer) attributes.get(PREFERRED_ENCODING_FORMAT);
+ preferredFormat = formatID == null
+ ? DEFAULT_ENCODING_FORMAT
+ : formatID.intValue();
+
// set the seed-key
byte[] kb = new byte[20]; // we need 160 bits of randomness
nextRandomBytes(kb);
@@ -356,8 +375,8 @@
BigInteger x = nextX();
BigInteger y = g.modPow(x, p);
- PublicKey pubK = new DSSPublicKey(p, q, g, y);
- PrivateKey secK = new DSSPrivateKey(p, q, g, x);
+ PublicKey pubK = new DSSPublicKey(preferredFormat, p, q, g, y);
+ PrivateKey secK = new DSSPrivateKey(preferredFormat, p, q, g, x);
return new KeyPair(pubK, secK);
}
Index: DSSKeyPairPKCS8Codec.java
===================================================================
RCS file: DSSKeyPairPKCS8Codec.java
diff -N DSSKeyPairPKCS8Codec.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DSSKeyPairPKCS8Codec.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,236 @@
+/* DSSKeyPairPKCS8Codec.java -- PKCS#8 Encoding/Decoding handler
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.OID;
+import gnu.java.security.Registry;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.der.DERWriter;
+import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.util.Util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidParameterException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+
+/**
+ * An implementation of an [EMAIL PROTECTED] IKeyPairCodec} that knows how to encode /
+ * decode PKCS#8 ASN.1 external representation of DSS private keys.
+ *
+ * @author Casey Marshall ([EMAIL PROTECTED])
+ */
+public class DSSKeyPairPKCS8Codec
+ implements IKeyPairCodec
+{
+ private static final OID DSA_ALG_OID = new OID(Registry.DSA_OID_STRING);
+
+ // implicit 0-arguments constructor
+
+ private static void checkIsConstructed(DERValue v, String msg)
+ {
+ if (! v.isConstructed())
+ throw new InvalidParameterException(msg);
+ }
+
+ private static void checkIsBigInteger(DERValue v, String msg)
+ {
+ if (! (v.getValue() instanceof BigInteger))
+ throw new InvalidParameterException(msg);
+ }
+
+ public int getFormatID()
+ {
+ return PKCS8_FORMAT;
+ }
+
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ throw new IllegalArgumentException("Wrong format for public keys");
+ }
+
+ /**
+ * Returns the PKCS#8 ASN.1 <i>PrivateKeyInfo</i> representation of a DSA
+ * private key. The ASN.1 specification is as follows:
+ *
+ * <pre>
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version INTEGER, -- MUST be 0
+ * privateKeyAlgorithm AlgorithmIdentifier,
+ * privateKey OCTET STRING
+ * }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DssParams ::= SEQUENCE {
+ * p INTEGER,
+ * q INTEGER,
+ * g INTEGER
+ * }
+ * </pre>
+ *
+ * @return the DER encoded form of the ASN.1 representation of the
+ * <i>PrivateKeyInfo</i> field in an X.509 certificate.
+ * @throw InvalidParameterException if an error occurs during the marshalling
+ * process.
+ */
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ if (! (key instanceof DSSPrivateKey))
+ throw new IllegalArgumentException("Wrong key type");
+
+ DERValue derVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
+
+ DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DSA_ALG_OID);
+
+ DSSPrivateKey pk = (DSSPrivateKey) key;
+ BigInteger p = pk.getParams().getP();
+ BigInteger q = pk.getParams().getQ();
+ BigInteger g = pk.getParams().getG();
+ BigInteger x = pk.getX();
+
+ ArrayList params = new ArrayList(3);
+ params.add(new DERValue(DER.INTEGER, p));
+ params.add(new DERValue(DER.INTEGER, q));
+ params.add(new DERValue(DER.INTEGER, g));
+ DERValue derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
+
+ ArrayList algorithmID = new ArrayList(2);
+ algorithmID.add(derOID);
+ algorithmID.add(derParams);
+ DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ algorithmID);
+
+ DERValue derPrivateKey = new DERValue(DER.OCTET_STRING, Util.trim(x));
+
+ ArrayList pki = new ArrayList(3);
+ pki.add(derVersion);
+ pki.add(derAlgorithmID);
+ pki.add(derPrivateKey);
+ DERValue derPKI = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, pki);
+
+ byte[] result;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try
+ {
+ DERWriter.write(baos, derPKI);
+ result = baos.toByteArray();
+ }
+ catch (IOException e)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(e);
+ throw y;
+ }
+
+ return result;
+ }
+
+ public PublicKey decodePublicKey(byte[] input)
+ {
+ throw new IllegalArgumentException("Wrong format for public keys");
+ }
+
+ /**
+ * @param input the byte array to unmarshall into a valid DSS
+ * [EMAIL PROTECTED] PublicKey} instance. MUST NOT be null.
+ * @return a new instance of a [EMAIL PROTECTED] DSSPrivateKey} decoded from the
+ * <i>PrivateKeyInfo</i> material fed as <code>input</code>.
+ * @throw InvalidParameterException if an exception occurs during the
+ * unmarshalling process.
+ */
+ public PrivateKey decodePrivateKey(byte[] input)
+ {
+ if (input == null)
+ throw new InvalidParameterException("Input bytes MUST NOT be null");
+
+ BigInteger p, q, g, x;
+ DERReader der = new DERReader(input);
+ try
+ {
+ DERValue derPKI = der.read();
+ checkIsConstructed(derPKI, "Wrong PrivateKeyInfo field");
+
+ DERValue derVersion = der.read();
+ if (! (derVersion.getValue() instanceof BigInteger))
+ throw new InvalidParameterException("Wrong Version field");
+
+ DERValue derAlgoritmID = der.read();
+ checkIsConstructed(derAlgoritmID, "Wrong AlgorithmIdentifier field");
+
+ DERValue derOID = der.read();
+ OID algOID = (OID) derOID.getValue();
+ if (! algOID.equals(DSA_ALG_OID))
+ throw new InvalidParameterException("Unexpected OID: " + algOID);
+
+ DERValue derParams = der.read();
+ checkIsConstructed(derParams, "Wrong DSS Parameters field");
+
+ DERValue val = der.read();
+ checkIsBigInteger(val, "Wrong P field");
+ p = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong Q field");
+ q = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong G field");
+ g = (BigInteger) val.getValue();
+
+ val = der.read();
+ byte[] xBytes = (byte[]) val.getValue();
+ x = new BigInteger(1, xBytes);
+ }
+ catch (IOException e)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(e);
+ throw y;
+ }
+
+ return new DSSPrivateKey(Registry.PKCS8_ENCODING_ID, p, q, g, x);
+ }
+}
Index: DSSKeyPairX509Codec.java
===================================================================
RCS file: DSSKeyPairX509Codec.java
diff -N DSSKeyPairX509Codec.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DSSKeyPairX509Codec.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,253 @@
+/* DSSKeyPairX509Codec.java -- X.509 Encoding/Decoding handler
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.OID;
+import gnu.java.security.Registry;
+import gnu.java.security.der.BitString;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.der.DERWriter;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidParameterException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+
+/**
+ * An implementation of an [EMAIL PROTECTED] IKeyPairCodec} that knows how to encode /
+ * decode X.509 ASN.1 external representation of DSS public keys.
+ */
+public class DSSKeyPairX509Codec
+ implements IKeyPairCodec
+{
+ private static final OID DSA_ALG_OID = new OID(Registry.DSA_OID_STRING);
+
+ // implicit 0-arguments constructor
+
+ private static void checkIsConstructed(DERValue v, String msg)
+ {
+ if (! v.isConstructed())
+ throw new InvalidParameterException(msg);
+ }
+
+ private static void checkIsBigInteger(DERValue v, String msg)
+ {
+ if (! (v.getValue() instanceof BigInteger))
+ throw new InvalidParameterException(msg);
+ }
+
+ public int getFormatID()
+ {
+ return X509_FORMAT;
+ }
+
+ /**
+ * Returns the X.509 ASN.1 <i>SubjectPublicKeyInfo</i> representation of a
+ * DSA public key. The ASN.1 specification, as defined in RFC-3280, and
+ * RFC-2459, is as follows:
+ *
+ * <pre>
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DssParams ::= SEQUENCE {
+ * p INTEGER,
+ * q INTEGER,
+ * g INTEGER
+ * }
+ * </pre>
+ *
+ * <p>The <i>subjectPublicKey</i> field, which is a BIT STRING, contains the
+ * DER-encoded form of the DSA public key as an INTEGER.</p>
+ *
+ * <pre>
+ * DSAPublicKey ::= INTEGER -- public key, Y
+ * </pre>
+ *
+ * @param key the [EMAIL PROTECTED] PublicKey} instance to encode. MUST be an instance of
+ * [EMAIL PROTECTED] DSSPublicKey}.
+ * @return the ASN.1 representation of the <i>SubjectPublicKeyInfo</i> in an
+ * X.509 certificate.
+ * @throw InvalidParameterException if <code>key</code> is not an instance
+ * of [EMAIL PROTECTED] DSSPublicKey} or if an exception occurs during the
+ * marshalling process.
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ if (! (key instanceof DSSPublicKey))
+ throw new InvalidParameterException("key");
+
+ DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DSA_ALG_OID);
+
+ DSSPublicKey dssKey = (DSSPublicKey) key;
+ BigInteger p = dssKey.getParams().getP();
+ BigInteger q = dssKey.getParams().getQ();
+ BigInteger g = dssKey.getParams().getG();
+ BigInteger y = dssKey.getY();
+
+ DERValue derP = new DERValue(DER.INTEGER, p);
+ DERValue derQ = new DERValue(DER.INTEGER, q);
+ DERValue derG = new DERValue(DER.INTEGER, g);
+
+ ArrayList params = new ArrayList(3);
+ params.add(derP);
+ params.add(derQ);
+ params.add(derG);
+ DERValue derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
+
+ ArrayList algorithmID = new ArrayList(2);
+ algorithmID.add(derOID);
+ algorithmID.add(derParams);
+ DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ algorithmID);
+
+ DERValue derDSAPublicKey = new DERValue(DER.INTEGER, y);
+ byte[] yBytes = derDSAPublicKey.getEncoded();
+ DERValue derSPK = new DERValue(DER.BIT_STRING, new BitString(yBytes));
+
+ ArrayList spki = new ArrayList(2);
+ spki.add(derAlgorithmID);
+ spki.add(derSPK);
+ DERValue derSPKI = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, spki);
+
+ byte[] result;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try
+ {
+ DERWriter.write(baos, derSPKI);
+ result = baos.toByteArray();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException e = new InvalidParameterException();
+ e.initCause(x);
+ throw e;
+ }
+
+ return result;
+ }
+
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ throw new IllegalArgumentException("Wrong format for private keys");
+ }
+
+ /**
+ * @param input the byte array to unmarshall into a valid DSS
+ * [EMAIL PROTECTED] PublicKey} instance. MUST NOT be null.
+ * @return a new instance of a [EMAIL PROTECTED] DSSPublicKey} decoded from the
+ * <i>SubjectPublicKeyInfo</i> material in an X.509 certificate.
+ * @throw InvalidParameterException if an exception occurs during the
+ * unmarshalling process.
+ */
+ public PublicKey decodePublicKey(byte[] input)
+ {
+ if (input == null)
+ throw new InvalidParameterException("Input bytes MUST NOT be null");
+
+ BigInteger p, g, q, y;
+ DERReader der = new DERReader(input);
+ try
+ {
+ DERValue derSPKI = der.read();
+ checkIsConstructed(derSPKI, "Wrong SubjectPublicKeyInfo field");
+
+ DERValue derAlgorithmID = der.read();
+ checkIsConstructed(derAlgorithmID, "Wrong AlgorithmIdentifier field");
+
+ DERValue derOID = der.read();
+ if (! (derOID.getValue() instanceof OID))
+ throw new InvalidParameterException("Wrong Algorithm field");
+
+ OID algOID = (OID) derOID.getValue();
+ if (! algOID.equals(DSA_ALG_OID))
+ throw new IllegalArgumentException("Unexpected OID: " + algOID);
+
+ DERValue derParams = der.read();
+ checkIsConstructed(derParams, "Wrong DSS Parameters field");
+
+ DERValue val = der.read();
+ checkIsBigInteger(val, "Wrong P field");
+ p = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong Q field");
+ q = (BigInteger) val.getValue();
+ val = der.read();
+ checkIsBigInteger(val, "Wrong G field");
+ g = (BigInteger) val.getValue();
+
+ val = der.read();
+ if (! (val.getValue() instanceof BitString))
+ throw new InvalidParameterException("Wrong SubjectPublicKey field");
+
+ byte[] yBytes = ((BitString) val.getValue()).toByteArray();
+
+ DERReader dsaPub = new DERReader(yBytes);
+ val = dsaPub.read();
+ checkIsBigInteger(val, "Wrong Y field");
+ y = (BigInteger) val.getValue();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException e = new InvalidParameterException();
+ e.initCause(x);
+ throw e;
+ }
+
+ return new DSSPublicKey(Registry.X509_ENCODING_ID, p, q, g, y);
+ }
+
+ public PrivateKey decodePrivateKey(byte[] input)
+ {
+ throw new IllegalArgumentException("Wrong format for private keys");
+ }
+}
Index: DSSPrivateKey.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/security/key/dss/DSSPrivateKey.java,v
retrieving revision 1.1
diff -u -r1.1 DSSPrivateKey.java
--- DSSPrivateKey.java 26 Jan 2006 02:25:10 -0000 1.1
+++ DSSPrivateKey.java 7 Feb 2006 11:49:08 -0000
@@ -67,17 +67,39 @@
// -------------------------------------------------------------------------
/**
- * <p>Trivial constructor.</p>
- *
+ * Convenience constructor. Calls the constructor with 5 arguments passing
+ * [EMAIL PROTECTED] Registry#RAW_ENCODING_ID} as the identifier of the preferred
+ * encoding format.
+ *
* @param p the public modulus.
* @param q the public prime divisor of <code>p-1</code>.
* @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
- * <sub>p</sub></code>.
+ * <sub>p</sub></code>.
* @param x the private key part.
*/
public DSSPrivateKey(BigInteger p, BigInteger q, BigInteger g, BigInteger x)
{
- super(p, q, g);
+ this(Registry.RAW_ENCODING_ID, p, q, g, x);
+ }
+
+ /**
+ * Constructs a new instance of a <code>DSSPrivateKey</code> given the
+ * designated arguments.
+ *
+ * @param preferredFormat the indetifier of the preferred encoding format to
+ * use when externalizing this key.
+ * @param p the public modulus.
+ * @param q the public prime divisor of <code>p-1</code>.
+ * @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
+ * <sub>p</sub></code>.
+ * @param x the private key part.
+ */
+ public DSSPrivateKey(int preferredFormat, BigInteger p, BigInteger q,
+ BigInteger g, BigInteger x)
+ {
+ super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.PKCS8_ENCODING_ID
+ : preferredFormat,
+ p, q, g);
this.x = x;
}
@@ -86,36 +108,32 @@
// -------------------------------------------------------------------------
/**
- * <p>A class method that takes the output of the <code>encodePrivateKey()</code>
+ * A class method that takes the output of the <code>encodePrivateKey()</code>
* method of a DSS keypair codec object (an instance implementing
- * [EMAIL PROTECTED] gnu.crypto.key.IKeyPairCodec} for DSS keys, and re-constructs an
- * instance of this object.</p>
- *
+ * [EMAIL PROTECTED] gnu.java.security.key.IKeyPairCodec} for DSS keys, and re-constructs
+ * an instance of this object.
+ *
* @param k the contents of a previously encoded instance of this object.
- * @exception ArrayIndexOutOfBoundsException if there is not enough bytes,
- * in <code>k</code>, to represent a valid encoding of an instance of
- * this object.
- * @exception IllegalArgumentException if the byte sequence does not
- * represent a valid encoding of an instance of this object.
+ * @exception ArrayIndexOutOfBoundsException if there is not enough bytes, in
+ * <code>k</code>, to represent a valid encoding of an
+ * instance of this object.
+ * @exception IllegalArgumentException if the byte sequence does not represent
+ * a valid encoding of an instance of this object.
*/
public static DSSPrivateKey valueOf(byte[] k)
{
- // check magic...
- // we should parse here enough bytes to know which codec to use, and
- // direct the byte array to the appropriate codec. since we only have one
- // codec, we could have immediately tried it; nevertheless since testing
- // one byte is cheaper than instatiating a codec that will fail we test
- // the first byte before we carry on.
+ // try RAW codec
if (k[0] == Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0])
- {
- // it's likely to be in raw format. get a raw codec and hand it over
- IKeyPairCodec codec = new DSSKeyPairRawCodec();
- return (DSSPrivateKey) codec.decodePrivateKey(k);
- }
- else
- {
- throw new IllegalArgumentException("magic");
- }
+ try
+ {
+ return (DSSPrivateKey) new DSSKeyPairRawCodec().decodePrivateKey(k);
+ }
+ catch (IllegalArgumentException ignored)
+ {
+ }
+
+ // try PKCS#8 codec
+ return (DSSPrivateKey) new DSSKeyPairPKCS8Codec().decodePrivateKey(k);
}
// Instance methods
@@ -148,8 +166,12 @@
case IKeyPairCodec.RAW_FORMAT:
result = new DSSKeyPairRawCodec().encodePrivateKey(this);
break;
+ case IKeyPairCodec.PKCS8_FORMAT:
+ result = new DSSKeyPairPKCS8Codec().encodePrivateKey(this);
+ break;
default:
- throw new IllegalArgumentException("format");
+ throw new IllegalArgumentException("Unsupported encoding format: "
+ + format);
}
return result;
}
Index: IKeyPairCodec.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/security/key/IKeyPairCodec.java,v
retrieving revision 1.1
diff -u -r1.1 IKeyPairCodec.java
--- IKeyPairCodec.java 26 Jan 2006 02:25:10 -0000 1.1
+++ IKeyPairCodec.java 7 Feb 2006 11:54:38 -0000
@@ -53,13 +53,24 @@
*/
public interface IKeyPairCodec
{
-
// Constants
// -------------------------------------------------------------------------
/** Constant identifying the <i>Raw</i> encoding format. */
int RAW_FORMAT = Registry.RAW_ENCODING_ID;
+ /** Constant identifying the <i>X.509</i> encoding format. */
+ int X509_FORMAT = Registry.X509_ENCODING_ID;
+
+ /** Constant identifying the <i>PKCS#8</i> encoding format. */
+ int PKCS8_FORMAT = Registry.PKCS8_ENCODING_ID;
+
+ /**
+ * Constant identifying the <i>ASN.1</i> encoding format: a combined encoding
+ * of <i>X.509</i> for public keys, and <i>PKCS#8</i> for private ones.
+ */
+ int ASN1_FORMAT = Registry.ASN1_ENCODING_ID;
+
// Method(s)
// -------------------------------------------------------------------------
Index: KeyPairCodecFactory.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/security/key/KeyPairCodecFactory.java,v
retrieving revision 1.1
diff -u -r1.1 KeyPairCodecFactory.java
--- KeyPairCodecFactory.java 26 Jan 2006 02:25:10 -0000 1.1
+++ KeyPairCodecFactory.java 7 Feb 2006 11:56:20 -0000
@@ -229,6 +229,65 @@
return KeyPairGeneratorFactory.getNames();
}
+ /**
+ * Returns the fully qualified name of the designated encoding ID.
+ *
+ * @param formatID the unique identifier of the encoding format.
+ * @return the fully qualified name of the designated format. Returns
+ * <code>null</code> if no such encoding format is known.
+ */
+ public static final String getEncodingName(int formatID)
+ {
+ String result = null;
+ switch (formatID)
+ {
+ case Registry.RAW_ENCODING_ID:
+ result = Registry.RAW_ENCODING;
+ break;
+ case Registry.X509_ENCODING_ID:
+ result = Registry.X509_ENCODING;
+ break;
+ case Registry.PKCS8_ENCODING_ID:
+ result = Registry.PKCS8_ENCODING;
+ break;
+ case Registry.ASN1_ENCODING_ID:
+ result = Registry.ASN1_ENCODING;
+ break;
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the short name of the designated encoding ID. This is used by the
+ * JCE Adapters.
+ *
+ * @param formatID the unique identifier of the encoding format.
+ * @return the short name of the designated format. Returns <code>null</code>
+ * if no such encoding format is known.
+ */
+ public static final String getEncodingShortName(int formatID)
+ {
+ String result = null;
+ switch (formatID)
+ {
+ case Registry.RAW_ENCODING_ID:
+ result = Registry.RAW_ENCODING_SHORT_NAME;
+ break;
+ case Registry.X509_ENCODING_ID:
+ result = Registry.X509_ENCODING_SORT_NAME;
+ break;
+ case Registry.PKCS8_ENCODING_ID:
+ result = Registry.PKCS8_ENCODING_SHORT_NAME;
+ break;
+ case Registry.ASN1_ENCODING_ID:
+ result = Registry.ASN1_ENCODING_SHORT_NAME;
+ break;
+ }
+
+ return result;
+ }
+
private static IKeyPairCodec makeInstance (String clazz)
{
try
Index: DSSPublicKey.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/security/key/dss/DSSPublicKey.java,v
retrieving revision 1.1
diff -u -r1.1 DSSPublicKey.java
--- DSSPublicKey.java 26 Jan 2006 02:25:10 -0000 1.1
+++ DSSPublicKey.java 7 Feb 2006 12:00:08 -0000
@@ -47,7 +47,7 @@
/**
* <p>An object that embodies a DSS (Digital Signature Standard) public key.</p>
- *
+ *
* @version $Revision: 1.1 $
* @see #getEncoded
*/
@@ -67,17 +67,39 @@
// -------------------------------------------------------------------------
/**
- * <p>Trivial constructor.</p>
- *
+ * Conveience constructor. Calls the constructor with 5 arguments passing
+ * [EMAIL PROTECTED] Registry#RAW_ENCODING_ID} as the identifier of the preferred
+ * encoding format.
+ *
* @param p the public modulus.
* @param q the public prime divisor of <code>p-1</code>.
* @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
- * <sub>p</sub></code>.
+ * <sub>p</sub></code>.
* @param y the public key part.
*/
public DSSPublicKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y)
{
- super(p, q, g);
+ this(Registry.RAW_ENCODING_ID, p, q, g, y);
+ }
+
+ /**
+ * Constructs a new instance of <code>DSSPublicKey</code> given the designated
+ * arguments.
+ *
+ * @param preferredFormat the identifier of the preferred encoding format to
+ * use when externalizing this key.
+ * @param p the public modulus.
+ * @param q the public prime divisor of <code>p-1</code>.
+ * @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
+ * <sub>p</sub></code>.
+ * @param y the public key part.
+ */
+ public DSSPublicKey(int preferredFormat, BigInteger p, BigInteger q,
+ BigInteger g, BigInteger y)
+ {
+ super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.X509_ENCODING_ID
+ : preferredFormat,
+ p, q, g);
this.y = y;
}
@@ -86,36 +108,32 @@
// -------------------------------------------------------------------------
/**
- * <p>A class method that takes the output of the <code>encodePublicKey()</code>
+ * A class method that takes the output of the <code>encodePublicKey()</code>
* method of a DSS keypair codec object (an instance implementing
- * [EMAIL PROTECTED] gnu.crypto.key.IKeyPairCodec} for DSS keys, and re-constructs an
- * instance of this object.</p>
- *
+ * [EMAIL PROTECTED] gnu.java.security.key.IKeyPairCodec} for DSS keys, and re-constructs
+ * an instance of this object.
+ *
* @param k the contents of a previously encoded instance of this object.
- * @exception ArrayIndexOutOfBoundsException if there is not enough bytes,
- * in <code>k</code>, to represent a valid encoding of an instance of
- * this object.
- * @exception IllegalArgumentException if the byte sequence does not
- * represent a valid encoding of an instance of this object.
+ * @exception ArrayIndexOutOfBoundsException if there is not enough bytes, in
+ * <code>k</code>, to represent a valid encoding of an
+ * instance of this object.
+ * @exception IllegalArgumentException if the byte sequence does not represent
+ * a valid encoding of an instance of this object.
*/
public static DSSPublicKey valueOf(byte[] k)
{
- // check magic...
- // we should parse here enough bytes to know which codec to use, and
- // direct the byte array to the appropriate codec. since we only have one
- // codec, we could have immediately tried it; nevertheless since testing
- // one byte is cheaper than instatiating a codec that will fail we test
- // the first byte before we carry on.
+ // try RAW codec
if (k[0] == Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0])
- {
- // it's likely to be in raw format. get a raw codec and hand it over
- IKeyPairCodec codec = new DSSKeyPairRawCodec();
- return (DSSPublicKey) codec.decodePublicKey(k);
- }
- else
- {
- throw new IllegalArgumentException("magic");
- }
+ try
+ {
+ return (DSSPublicKey) new DSSKeyPairRawCodec().decodePublicKey(k);
+ }
+ catch (IllegalArgumentException ignored)
+ {
+ }
+
+ // try X.509 codec
+ return (DSSPublicKey) new DSSKeyPairX509Codec().decodePublicKey(k);
}
// Instance methods
@@ -133,7 +151,7 @@
/**
* <p>Returns the encoded form of this public key according to the designated
* format.</p>
- *
+ *
* @param format the desired format identifier of the resulting encoding.
* @return the byte sequence encoding this key according to the designated
* format.
@@ -148,8 +166,12 @@
case IKeyPairCodec.RAW_FORMAT:
result = new DSSKeyPairRawCodec().encodePublicKey(this);
break;
+ case IKeyPairCodec.X509_FORMAT:
+ result = new DSSKeyPairX509Codec().encodePublicKey(this);
+ break;
default:
- throw new IllegalArgumentException("format");
+ throw new IllegalArgumentException("Unsupported encoding format: "
+ + format);
}
return result;
}
@@ -158,7 +180,7 @@
* <p>Returns <code>true</code> if the designated object is an instance of
* [EMAIL PROTECTED] DSAPublicKey} and has the same DSS (Digital Signature Standard)
* parameter values as this one.</p>
- *
+ *
* @param obj the other non-null DSS key to compare to.
* @return <code>true</code> if the designated object is of the same type and
* value as this one.
pgp6yRy7E9jgR.pgp
Description: PGP signature
