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.

Attachment: pgp6yRy7E9jgR.pgp
Description: PGP signature

Reply via email to