summaryrefslogtreecommitdiffstats
path: root/libjava/classpath/gnu/javax/crypto/keyring
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/gnu/javax/crypto/keyring')
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/AuthenticatedEntry.java222
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/BaseKeyring.java198
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/BinaryDataEntry.java128
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/CertPathEntry.java133
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/CertificateEntry.java150
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/CompressedEntry.java113
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/EncryptedEntry.java235
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/Entry.java178
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/EnvelopeEntry.java398
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/GnuPrivateKeyring.java328
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/GnuPublicKeyring.java146
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/IKeyring.java164
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/IPrivateKeyring.java142
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/IPublicKeyring.java81
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/MalformedKeyringException.java58
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java148
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/MeteredInputStream.java137
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java285
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PasswordEncryptedEntry.java301
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PasswordProtectedEntry.java66
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PrimitiveEntry.java129
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PrivateKeyEntry.java221
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/Properties.java227
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PublicKeyEntry.java192
24 files changed, 4380 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/AuthenticatedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/AuthenticatedEntry.java
new file mode 100644
index 00000000000..22b42b3ea0b
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/AuthenticatedEntry.java
@@ -0,0 +1,222 @@
+/* AuthenticatedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.InvalidKeyException;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.List;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mac.MacFactory;
+import gnu.javax.crypto.mac.MacInputStream;
+import gnu.javax.crypto.mac.MacOutputStream;
+
+public final class AuthenticatedEntry extends MaskableEnvelopeEntry implements
+ Registry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 2;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public AuthenticatedEntry(String mac, int macLen, Properties properties)
+ {
+ super(TYPE, properties);
+
+ if (macLen <= 0)
+ {
+ throw new IllegalArgumentException("invalid mac length");
+ }
+ this.properties.put("mac", mac);
+ this.properties.put("maclen", String.valueOf(macLen));
+ setMasked(false);
+ }
+
+ private AuthenticatedEntry()
+ {
+ super(TYPE);
+ setMasked(true);
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ public static AuthenticatedEntry decode(DataInputStream in)
+ throws IOException
+ {
+ AuthenticatedEntry entry = new AuthenticatedEntry();
+ entry.properties.decode(in);
+ if (!entry.properties.containsKey("mac"))
+ {
+ throw new MalformedKeyringException("no mac specified");
+ }
+ if (!entry.properties.containsKey("maclen"))
+ {
+ throw new MalformedKeyringException("no mac length specified");
+ }
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Computes the mac over this envelope's data. This method <b>must</b> be
+ * called before this entry in encoded.
+ *
+ * @param key The key to authenticate with.
+ * @throws IOException If encoding fails.
+ * @throws InvalidKeyException If the supplied key is bad.
+ */
+ public void authenticate(byte[] key) throws IOException, InvalidKeyException
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("entry is masked");
+ }
+ IMac m = getMac(key);
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ MacOutputStream macout = new MacOutputStream(bout, m);
+ DataOutputStream out2 = new DataOutputStream(macout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry entry = (Entry) it.next();
+ entry.encode(out2);
+ }
+ bout.write(m.digest());
+ payload = bout.toByteArray();
+ }
+
+ /**
+ * Verifies this entry's payload. This method will unmask this entry,
+ * thus it must be called before accessing its contents.
+ *
+ * @param key The key to use to authenticate.
+ * @throws InvalidKeyException If the given key is improper.
+ */
+ public void verify(byte[] key) throws InvalidKeyException
+ {
+ if (!isMasked() || payload == null)
+ {
+ return;
+ }
+ IMac m = getMac(key);
+
+ m.update(payload, 0, payload.length - m.macSize());
+ byte[] macValue = new byte[m.macSize()];
+ System.arraycopy(payload, payload.length - macValue.length, macValue, 0,
+ macValue.length);
+ if (!Arrays.equals(macValue, m.digest()))
+ {
+ throw new IllegalArgumentException("MAC verification failed");
+ }
+ try
+ {
+ DataInputStream in = new DataInputStream(
+ new ByteArrayInputStream(
+ payload,
+ 0,
+ payload.length
+ - m.macSize()));
+ decodeEnvelope(in);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException("malformed keyring fragment");
+ }
+ setMasked(false);
+ payload = null;
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ if (payload == null)
+ {
+ throw new IllegalStateException("not authenticated");
+ }
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private IMac getMac(byte[] key) throws InvalidKeyException
+ {
+ IMac mac = MacFactory.getInstance(properties.get("mac"));
+ if (mac == null)
+ {
+ throw new IllegalArgumentException("no such mac: "
+ + properties.get("mac"));
+ }
+ int maclen = 0;
+ if (!properties.containsKey("maclen"))
+ {
+ throw new IllegalArgumentException("no MAC length");
+ }
+ try
+ {
+ maclen = Integer.parseInt(properties.get("maclen"));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new IllegalArgumentException("bad MAC length");
+ }
+
+ HashMap macAttr = new HashMap();
+ macAttr.put(IMac.MAC_KEY_MATERIAL, key);
+ macAttr.put(IMac.TRUNCATED_SIZE, new Integer(maclen));
+ mac.init(macAttr);
+ return mac;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/BaseKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/BaseKeyring.java
new file mode 100644
index 00000000000..5fe7dbf4deb
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/BaseKeyring.java
@@ -0,0 +1,198 @@
+/* BaseKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import gnu.java.security.Registry;
+
+public abstract class BaseKeyring implements IKeyring
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /**
+ * The top-level keyring data.
+ */
+ protected PasswordAuthenticatedEntry keyring;
+
+ protected CompressedEntry keyring2;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ public BaseKeyring()
+ {
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public void load(Map attributes) throws IOException
+ {
+ InputStream in = (InputStream) attributes.get(KEYRING_DATA_IN);
+ if (in == null)
+ {
+ throw new IllegalArgumentException("no input stream");
+ }
+ char[] password = (char[]) attributes.get(KEYRING_PASSWORD);
+ if (password == null)
+ {
+ password = new char[0];
+ }
+
+ if (in.read() != Registry.GKR_MAGIC[0]
+ || in.read() != Registry.GKR_MAGIC[1]
+ || in.read() != Registry.GKR_MAGIC[2]
+ || in.read() != Registry.GKR_MAGIC[3])
+ {
+ throw new MalformedKeyringException("magic");
+ }
+
+ load(in, password);
+
+ List l = keyring.getEntries();
+ if (l.size() == 1 && (l.get(0) instanceof CompressedEntry))
+ {
+ keyring2 = (CompressedEntry) l.get(0);
+ }
+ }
+
+ public void store(Map attributes) throws IOException
+ {
+ OutputStream out = (OutputStream) attributes.get(KEYRING_DATA_OUT);
+ if (out == null)
+ {
+ throw new IllegalArgumentException("no output stream");
+ }
+ char[] password = (char[]) attributes.get(KEYRING_PASSWORD);
+ if (password == null)
+ {
+ password = new char[0];
+ }
+ if (keyring == null)
+ {
+ throw new IllegalStateException("empty keyring");
+ }
+
+ out.write(Registry.GKR_MAGIC);
+ store(out, password);
+ }
+
+ public void reset()
+ {
+ keyring = null;
+ }
+
+ public int size()
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException ("keyring not loaded");
+ }
+ return ((StringTokenizer) aliases()).countTokens();
+ }
+
+ public Enumeration aliases()
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException ("keyring not loaded");
+ }
+ return new StringTokenizer(keyring.getAliasList(), ";");
+ }
+
+ public boolean containsAlias(String alias)
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException("keyring not loaded");
+ }
+ return keyring.containsAlias(alias);
+ }
+
+ public List get(String alias)
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException("keyring not loaded");
+ }
+ return keyring.get(alias);
+ }
+
+ public void add(Entry entry)
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException("keyring not loaded");
+ }
+ if (keyring2 != null)
+ keyring2.add(entry);
+ else
+ keyring.add(entry);
+ }
+
+ public void remove(String alias)
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException("keyring not loaded");
+ }
+ keyring.remove(alias);
+ }
+
+ protected String fixAlias(String alias)
+ {
+ return alias.replace(';', '_');
+ }
+
+ protected abstract void load(InputStream in, char[] password)
+ throws IOException;
+
+ protected abstract void store(OutputStream out, char[] password)
+ throws IOException;
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/BinaryDataEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/BinaryDataEntry.java
new file mode 100644
index 00000000000..2dcd5454fb6
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/BinaryDataEntry.java
@@ -0,0 +1,128 @@
+/* BinaryDataEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import java.util.Date;
+
+/**
+ * A binary data entry is a primitive entry that simply contains some amount
+ * of arbitrary binary data and an optional content type.
+ */
+public class BinaryDataEntry extends PrimitiveEntry
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 9;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new binary data entry.
+ *
+ * @param contentType The content type of this entry. This parameter can
+ * be <code>null</code> if no content type is needed.
+ * @param data The data.
+ * @param creationDate The creation date.
+ * @param properties This entry's properties.
+ */
+ public BinaryDataEntry(String contentType, byte[] data, Date creationDate,
+ Properties properties)
+ {
+ super(TYPE, creationDate, properties);
+ if (data == null)
+ {
+ throw new IllegalArgumentException("no data");
+ }
+ payload = (byte[]) data.clone();
+ if (contentType != null)
+ {
+ this.properties.put("content-type", contentType);
+ }
+ }
+
+ private BinaryDataEntry()
+ {
+ super(TYPE);
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ public static BinaryDataEntry decode(DataInputStream in) throws IOException
+ {
+ BinaryDataEntry entry = new BinaryDataEntry();
+ entry.defaultDecode(in);
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the content type of this entry, or <code>null</code> if this
+ * property is not set.
+ *
+ * @return The content type.
+ */
+ public String getContentType()
+ {
+ return properties.get("content-type");
+ }
+
+ /**
+ * Returns this object's data field.
+ *
+ * @return The data.
+ */
+ public byte[] getData()
+ {
+ return getPayload();
+ }
+
+ protected void encodePayload()
+ {
+ // Empty.
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/CertPathEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/CertPathEntry.java
new file mode 100644
index 00000000000..ef62347ec9d
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/CertPathEntry.java
@@ -0,0 +1,133 @@
+/* CertPathEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+
+import java.util.Date;
+
+/**
+ * A primitive entry that contains a path of X.509 certificates.
+ */
+public final class CertPathEntry extends PrimitiveEntry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 8;
+
+ private Certificate[] path;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public CertPathEntry(Certificate[] path, Date creationDate,
+ Properties properties)
+ {
+ super(TYPE, creationDate, properties);
+ if (path == null || path.length == 0)
+ {
+ throw new IllegalArgumentException("no certificate path");
+ }
+ this.path = (Certificate[]) path.clone();
+ }
+
+ private CertPathEntry()
+ {
+ super(TYPE);
+ }
+
+ // Class method.
+ // ------------------------------------------------------------------------
+
+ public static CertPathEntry decode(DataInputStream in) throws IOException
+ {
+ CertPathEntry entry = new CertPathEntry();
+ entry.properties.decode(in);
+ entry.makeCreationDate();
+ int len = in.readInt();
+ MeteredInputStream in2 = new MeteredInputStream(in, len);
+ try
+ {
+ CertificateFactory fact = CertificateFactory.getInstance("X.509");
+ entry.path = (Certificate[]) fact.generateCertificates(in2).toArray(
+ new Certificate[0]);
+ }
+ catch (CertificateException ce)
+ {
+ throw new MalformedKeyringException(ce.toString());
+ }
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public Certificate[] getCertPath()
+ {
+ return path;
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ byte[] enc = null;
+ try
+ {
+ for (int i = 0; i < path.length; i++)
+ {
+ bout.write(path[i].getEncoded());
+ }
+ }
+ catch (CertificateEncodingException cee)
+ {
+ throw new IOException(cee.toString());
+ }
+ payload = bout.toByteArray();
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/CertificateEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/CertificateEntry.java
new file mode 100644
index 00000000000..95a708ac53f
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/CertificateEntry.java
@@ -0,0 +1,150 @@
+/* CertificateEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+/**
+ * <p>An immutable class representing a trusted certificate entry.</p>
+ */
+public final class CertificateEntry extends PrimitiveEntry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int TYPE = 5;
+
+ /** The certificate. */
+ private Certificate certificate;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Creates a new certificate entry.
+ *
+ * @param certificate The certificate.
+ * @param creationDate The creation date.
+ * @param properties The alias.
+ * @throws IllegalArgumentException If any argument is null, or if the alias
+ * is empty.
+ */
+ public CertificateEntry(Certificate certificate, Date creationDate,
+ Properties properties)
+ {
+ super(TYPE, creationDate, properties);
+
+ if (certificate == null)
+ {
+ throw new IllegalArgumentException("no certificate");
+ }
+ this.certificate = certificate;
+ this.properties.put("type", certificate.getType());
+ }
+
+ private CertificateEntry()
+ {
+ super(TYPE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static CertificateEntry decode(DataInputStream in) throws IOException
+ {
+ CertificateEntry entry = new CertificateEntry();
+ entry.properties.decode(in);
+ entry.makeCreationDate();
+ String type = entry.properties.get("type");
+ if (type == null)
+ {
+ throw new MalformedKeyringException("no certificate type");
+ }
+ int len = in.readInt();
+ MeteredInputStream in2 = new MeteredInputStream(in, len);
+ try
+ {
+ CertificateFactory fact = CertificateFactory.getInstance(type);
+ entry.certificate = fact.generateCertificate(in2);
+ }
+ catch (CertificateException ce)
+ {
+ throw new MalformedKeyringException(ce.toString());
+ }
+ if (!in2.limitReached())
+ {
+ throw new MalformedKeyringException("extra data at end of payload");
+ }
+ return entry;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns this entry's certificate.
+ *
+ * @return The certificate.
+ */
+ public Certificate getCertificate()
+ {
+ return certificate;
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ try
+ {
+ payload = certificate.getEncoded();
+ }
+ catch (CertificateEncodingException cee)
+ {
+ throw new IOException(cee.toString());
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/CompressedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/CompressedEntry.java
new file mode 100644
index 00000000000..cce930d739d
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/CompressedEntry.java
@@ -0,0 +1,113 @@
+/* CompressedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.util.Iterator;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.InflaterInputStream;
+
+public class CompressedEntry extends EnvelopeEntry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 4;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public CompressedEntry(Properties properties)
+ {
+ super(TYPE, properties);
+ this.properties.put("algorithm", "DEFLATE");
+ }
+
+ private CompressedEntry()
+ {
+ this(new Properties());
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ public static CompressedEntry decode(DataInputStream in) throws IOException
+ {
+ CompressedEntry entry = new CompressedEntry();
+ entry.properties.decode(in);
+ String alg = entry.properties.get("algorithm");
+ if (alg == null)
+ {
+ throw new MalformedKeyringException("no compression algorithm");
+ }
+ if (!alg.equalsIgnoreCase("DEFLATE"))
+ {
+ throw new MalformedKeyringException(
+ "unsupported compression algorithm: "
+ + alg);
+ }
+ int len = in.readInt();
+ MeteredInputStream min = new MeteredInputStream(in, len);
+ InflaterInputStream infin = new InflaterInputStream(min);
+ DataInputStream in2 = new DataInputStream(infin);
+ entry.decodeEnvelope(in2);
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ protected void encodePayload() throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream(1024);
+ DeflaterOutputStream dout = new DeflaterOutputStream(buf);
+ DataOutputStream out2 = new DataOutputStream(dout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ ((Entry) it.next()).encode(out2);
+ }
+ dout.finish();
+ payload = buf.toByteArray();
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/EncryptedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/EncryptedEntry.java
new file mode 100644
index 00000000000..fad5f54b236
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/EncryptedEntry.java
@@ -0,0 +1,235 @@
+/* EncryptedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.InvalidKeyException;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.List;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.mode.ModeFactory;
+import gnu.javax.crypto.pad.IPad;
+import gnu.javax.crypto.pad.PadFactory;
+import gnu.javax.crypto.pad.WrongPaddingException;
+
+public class EncryptedEntry extends MaskableEnvelopeEntry implements Registry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 0;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public EncryptedEntry(String cipher, String mode, Properties properties)
+ {
+ super(TYPE, properties);
+ if (cipher == null || mode == null)
+ {
+ throw new IllegalArgumentException(
+ "neither cipher nor mode can be null");
+ }
+ properties.put("cipher", cipher);
+ properties.put("mode", mode);
+ setMasked(false);
+ }
+
+ private EncryptedEntry()
+ {
+ super(TYPE, new Properties());
+ setMasked(true);
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ public static EncryptedEntry decode(DataInputStream in) throws IOException
+ {
+ EncryptedEntry entry = new EncryptedEntry();
+ entry.defaultDecode(in);
+ if (!entry.properties.containsKey("cipher"))
+ {
+ throw new MalformedKeyringException("no cipher");
+ }
+ if (!entry.properties.containsKey("cipher"))
+ {
+ throw new MalformedKeyringException("no cipher");
+ }
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public void decrypt(byte[] key, byte[] iv) throws IllegalArgumentException,
+ WrongPaddingException
+ {
+ if (!isMasked() || payload == null)
+ {
+ return;
+ }
+ IMode mode = getMode(key, iv, IMode.DECRYPTION);
+ IPad padding = null;
+ padding = PadFactory.getInstance("PKCS7");
+ padding.init(mode.currentBlockSize());
+ byte[] buf = new byte[payload.length];
+ int count = 0;
+ for (int i = 0; i < payload.length; i++)
+ {
+ mode.update(payload, count, buf, count);
+ count += mode.currentBlockSize();
+ }
+ int padlen = padding.unpad(buf, 0, buf.length);
+ DataInputStream in = new DataInputStream(
+ new ByteArrayInputStream(
+ buf,
+ 0,
+ buf.length
+ - padlen));
+ try
+ {
+ decodeEnvelope(in);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException("decryption failed");
+ }
+ setMasked(false);
+ payload = null;
+ }
+
+ public void encrypt(byte[] key, byte[] iv) throws IOException
+ {
+ IMode mode = getMode(key, iv, IMode.ENCRYPTION);
+ IPad pad = PadFactory.getInstance("PKCS7");
+ pad.init(mode.currentBlockSize());
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ DataOutputStream out2 = new DataOutputStream(bout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry entry = (Entry) it.next();
+ entry.encode(out2);
+ }
+ byte[] plaintext = bout.toByteArray();
+ byte[] padding = pad.pad(plaintext, 0, plaintext.length);
+ payload = new byte[plaintext.length + padding.length];
+ byte[] lastBlock = new byte[mode.currentBlockSize()];
+ int l = mode.currentBlockSize() - padding.length;
+ System.arraycopy(plaintext, plaintext.length - l, lastBlock, 0, l);
+ System.arraycopy(padding, 0, lastBlock, l, padding.length);
+ int count = 0;
+ while (count + mode.currentBlockSize() < plaintext.length)
+ {
+ mode.update(plaintext, count, payload, count);
+ count += mode.currentBlockSize();
+ }
+ mode.update(lastBlock, 0, payload, count);
+ }
+
+ public void encodePayload() throws IOException
+ {
+ if (payload == null)
+ {
+ throw new IOException("not encrypted");
+ }
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private IMode getMode(byte[] key, byte[] iv, int state)
+ {
+ IBlockCipher cipher = CipherFactory.getInstance(properties.get("cipher"));
+ if (cipher == null)
+ {
+ throw new IllegalArgumentException("no such cipher: "
+ + properties.get("cipher"));
+ }
+ int blockSize = cipher.defaultBlockSize();
+ if (properties.containsKey("block-size"))
+ {
+ try
+ {
+ blockSize = Integer.parseInt(properties.get("block-size"));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new IllegalArgumentException("bad block size: "
+ + nfe.getMessage());
+ }
+ }
+ IMode mode = ModeFactory.getInstance(properties.get("mode"), cipher,
+ blockSize);
+ if (mode == null)
+ {
+ throw new IllegalArgumentException("no such mode: "
+ + properties.get("mode"));
+ }
+
+ HashMap modeAttr = new HashMap();
+ modeAttr.put(IMode.KEY_MATERIAL, key);
+ modeAttr.put(IMode.STATE, new Integer(state));
+ modeAttr.put(IMode.IV, iv);
+ try
+ {
+ mode.init(modeAttr);
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new IllegalArgumentException(ike.toString());
+ }
+ return mode;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/Entry.java b/libjava/classpath/gnu/javax/crypto/keyring/Entry.java
new file mode 100644
index 00000000000..fa7f496798b
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/Entry.java
@@ -0,0 +1,178 @@
+/* Entry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * An immutable class representing a single entry in a keyring.
+ */
+public abstract class Entry
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** This entry's type identifier. */
+ protected int type;
+
+ /** This entry's property set. */
+ protected Properties properties;
+
+ /** This entry's payload. */
+ protected byte[] payload;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new Entry.
+ *
+ * @param type This entry's type.
+ * @param properties This entry's properties.
+ * @throws IllegalArgumentException If the properties argument is null,
+ * or if the type is out of range.
+ */
+ protected Entry(int type, Properties properties)
+ {
+ if (type < 0 || type > 255)
+ {
+ throw new IllegalArgumentException("invalid packet type");
+ }
+ if (properties == null)
+ {
+ throw new IllegalArgumentException("no properties");
+ }
+ this.type = type;
+ this.properties = (Properties) properties.clone();
+ }
+
+ /**
+ * Constructor for use by subclasses.
+ */
+ protected Entry(final int type)
+ {
+ if (type < 0 || type > 255)
+ {
+ throw new IllegalArgumentException("invalid packet type");
+ }
+ this.type = type;
+ properties = new Properties();
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns this entry's properties object. The properties are cloned before
+ * being returned.
+ *
+ * @return The properties.
+ */
+ public Properties getProperties()
+ {
+ return (Properties) properties.clone();
+ }
+
+ /**
+ * Returns this entry's payload data, or null if
+ */
+ public byte[] getPayload()
+ {
+ if (payload == null)
+ return null;
+ return (byte[]) payload.clone();
+ }
+
+ /**
+ * This method is called when this entry needs to be written to an
+ * output stream.
+ *
+ * @param out The stream to write to.
+ * @throws IOException If an I/O exception occurs.
+ */
+ public void encode(DataOutputStream out) throws IOException
+ {
+ if (payload == null)
+ {
+ encodePayload();
+ }
+ if (out == null)
+ {
+ return;
+ }
+ out.write(type);
+ properties.encode(out);
+ out.writeInt(payload.length);
+ out.write(payload);
+ }
+
+ /**
+ * Generic decoding method, which simply decodes the properties field
+ * and reads the payload field.
+ *
+ * @param in The input data stream.
+ * @throws IOException If an I/O error occurs.
+ */
+ protected void defaultDecode(DataInputStream in) throws IOException
+ {
+ properties = new Properties();
+ properties.decode(in);
+ int len = in.readInt();
+ if (len < 0)
+ {
+ throw new IOException("corrupt length");
+ }
+ payload = new byte[len];
+ in.readFully(payload);
+ }
+
+ // Abstract methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * This method is called of subclasses when the payload data needs to be
+ * created.
+ *
+ * @throws IOException If an encoding error occurs.
+ */
+ protected abstract void encodePayload() throws IOException;
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/EnvelopeEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/EnvelopeEntry.java
new file mode 100644
index 00000000000..25b1dc2a04d
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/EnvelopeEntry.java
@@ -0,0 +1,398 @@
+/* EnvelopeEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * An envelope entry is a generic container for some number of primitive
+ * and other envelope entries.
+ */
+public abstract class EnvelopeEntry extends Entry
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The envelope that contains this one (if any). */
+ protected EnvelopeEntry containingEnvelope;
+
+ /** The contained entries. */
+ protected List entries;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public EnvelopeEntry(int type, Properties properties)
+ {
+ super(type, properties);
+ entries = new LinkedList();
+ if (this.properties.get("alias-list") != null)
+ {
+ this.properties.remove("alias-list");
+ }
+ }
+
+ protected EnvelopeEntry(int type)
+ {
+ super(type);
+ entries = new LinkedList();
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Adds an entry to this envelope.
+ *
+ * @param entry The entry to add.
+ */
+ public void add(Entry entry)
+ {
+ if (!containsEntry(entry))
+ {
+ if (entry instanceof EnvelopeEntry)
+ {
+ ((EnvelopeEntry) entry).setContainingEnvelope(this);
+ }
+ entries.add(entry);
+ payload = null;
+ makeAliasList();
+ }
+ }
+
+ /**
+ * Tests if this envelope contains a primitive entry with the
+ * given alias.
+ *
+ * @param alias The alias to test.
+ * @return True if this envelope (or one of the contained envelopes)
+ * contains a primitive entry with the given alias.
+ */
+ public boolean containsAlias(String alias)
+ {
+ String aliases = getAliasList();
+ if (aliases == null)
+ {
+ return false;
+ }
+ StringTokenizer tok = new StringTokenizer(aliases, ";");
+ while (tok.hasMoreTokens())
+ {
+ if (tok.nextToken().equals(alias))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests if this envelope contains the given entry.
+ *
+ * @param entry The entry to test.
+ * @return True if this envelope contains the given entry.
+ */
+ public boolean containsEntry(Entry entry)
+ {
+ if (entry instanceof EnvelopeEntry)
+ {
+ return entries.contains(entry);
+ }
+ else if (entry instanceof PrimitiveEntry)
+ {
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e.equals(entry))
+ return true;
+ if ((e instanceof EnvelopeEntry)
+ && ((EnvelopeEntry) e).containsEntry(entry))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a copy of all entries this envelope contains.
+ *
+ * @return All contained entries.
+ */
+ public List getEntries()
+ {
+ return new ArrayList(entries);
+ }
+
+ /**
+ * Gets all primitive entries that have the given alias. If there
+ * are any masked entries that contain the given alias, they will
+ * be returned as well.
+ *
+ * @param alias The alias of the entries to get.
+ * @return A list of all primitive entries that have the given alias.
+ */
+ public List get(String alias)
+ {
+ List result = new LinkedList();
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof EnvelopeEntry)
+ {
+ if (!((EnvelopeEntry) e).containsAlias(alias))
+ {
+ continue;
+ }
+ if (e instanceof MaskableEnvelopeEntry)
+ {
+ if (((MaskableEnvelopeEntry) e).isMasked())
+ {
+ result.add(e);
+ continue;
+ }
+ }
+ result.addAll(((EnvelopeEntry) e).get(alias));
+ }
+ else if (e instanceof PrimitiveEntry)
+ {
+ if (((PrimitiveEntry) e).getAlias().equals(alias))
+ {
+ result.add(e);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the list of all aliases contained by this envelope,
+ * separated by a semicolon (';').
+ *
+ * @return The list of aliases.
+ */
+ public String getAliasList()
+ {
+ String list = properties.get("alias-list");
+ if (list == null)
+ {
+ return "";
+ }
+ else
+ {
+ return list;
+ }
+ }
+
+ /**
+ * Removes the specified entry.
+ *
+ * @param entry The entry.
+ * @return True if an entry was removed.
+ */
+ public boolean remove(Entry entry)
+ {
+ boolean ret = false;
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof EnvelopeEntry)
+ {
+ if (e == entry)
+ {
+ it.remove();
+ ret = true;
+ break;
+ }
+ if (((EnvelopeEntry) e).remove(entry))
+ {
+ ret = true;
+ break;
+ }
+ }
+ else if (e instanceof PrimitiveEntry)
+ {
+ if (((PrimitiveEntry) e).equals(entry))
+ {
+ it.remove();
+ ret = true;
+ break;
+ }
+ }
+ }
+ if (ret)
+ {
+ payload = null;
+ makeAliasList();
+ }
+ return ret;
+ }
+
+ /**
+ * Removes all primitive entries that have the specified alias.
+ *
+ * @param alias The alias of the entries to remove.
+ */
+ public void remove(String alias)
+ {
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof EnvelopeEntry)
+ {
+ ((EnvelopeEntry) e).remove(alias);
+ }
+ else if (e instanceof PrimitiveEntry)
+ {
+ if (((PrimitiveEntry) e).getAlias().equals(alias))
+ {
+ it.remove();
+ }
+ }
+ }
+ payload = null;
+ makeAliasList();
+ }
+
+ // Protected methods.
+ // ------------------------------------------------------------------------
+
+ protected void encodePayload() throws IOException
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ DataOutputStream out = new DataOutputStream(bout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ ((Entry) it.next()).encode(out);
+ }
+ }
+
+ protected void setContainingEnvelope(EnvelopeEntry e)
+ {
+ if (containingEnvelope != null)
+ {
+ throw new IllegalArgumentException("envelopes may not be shared");
+ }
+ containingEnvelope = e;
+ }
+
+ protected void decodeEnvelope(DataInputStream in) throws IOException
+ {
+ while (true)
+ {
+ int type = in.read();
+ switch (type)
+ {
+ case EncryptedEntry.TYPE:
+ add(EncryptedEntry.decode(in));
+ break;
+ case PasswordEncryptedEntry.TYPE:
+ add(PasswordEncryptedEntry.decode(in));
+ break;
+ case PasswordAuthenticatedEntry.TYPE:
+ add(PasswordAuthenticatedEntry.decode(in));
+ break;
+ case AuthenticatedEntry.TYPE:
+ add(AuthenticatedEntry.decode(in));
+ break;
+ case CompressedEntry.TYPE:
+ add(CompressedEntry.decode(in));
+ break;
+ case CertificateEntry.TYPE:
+ add(CertificateEntry.decode(in));
+ break;
+ case PublicKeyEntry.TYPE:
+ add(PublicKeyEntry.decode(in));
+ break;
+ case PrivateKeyEntry.TYPE:
+ add(PrivateKeyEntry.decode(in));
+ break;
+ case CertPathEntry.TYPE:
+ add(CertPathEntry.decode(in));
+ break;
+ case BinaryDataEntry.TYPE:
+ add(BinaryDataEntry.decode(in));
+ break;
+ case -1:
+ return;
+ default:
+ throw new MalformedKeyringException("unknown type " + type);
+ }
+ }
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private void makeAliasList()
+ {
+ if (entries.isEmpty())
+ return;
+ StringBuffer buf = new StringBuffer();
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry entry = (Entry) it.next();
+ if (entry instanceof EnvelopeEntry)
+ {
+ buf.append(((EnvelopeEntry) entry).getAliasList());
+ }
+ else if (entry instanceof PrimitiveEntry)
+ {
+ buf.append(((PrimitiveEntry) entry).getAlias());
+ }
+ if (it.hasNext())
+ buf.append(';');
+ }
+ properties.put("alias-list", buf.toString());
+ if (containingEnvelope != null)
+ {
+ containingEnvelope.makeAliasList();
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/GnuPrivateKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/GnuPrivateKeyring.java
new file mode 100644
index 00000000000..d49bd09636d
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/GnuPrivateKeyring.java
@@ -0,0 +1,328 @@
+/* GnuPrivateKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import gnu.java.security.Registry;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.Key;
+import java.security.PublicKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * <p>.</p>
+ */
+public class GnuPrivateKeyring extends BaseKeyring implements IPrivateKeyring
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int USAGE = Registry.GKR_PRIVATE_KEYS
+ | Registry.GKR_PUBLIC_CREDENTIALS;
+
+ protected String mac;
+
+ protected int maclen;
+
+ protected String cipher;
+
+ protected String mode;
+
+ protected int keylen;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public GnuPrivateKeyring(String mac, int maclen, String cipher, String mode,
+ int keylen)
+ {
+ keyring = new PasswordAuthenticatedEntry(mac, maclen, new Properties());
+ keyring2 = new CompressedEntry(new Properties());
+ keyring.add(keyring2);
+ this.mac = mac;
+ this.maclen = maclen;
+ this.cipher = cipher;
+ this.mode = mode;
+ this.keylen = keylen;
+ }
+
+ public GnuPrivateKeyring()
+ {
+ this("HMAC-SHA-1", 20, "AES", "OFB", 16);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public boolean containsPrivateKey(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return false;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ if (it.next() instanceof PasswordAuthenticatedEntry)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Key getPrivateKey(String alias, char[] password)
+ throws UnrecoverableKeyException
+ {
+ if (!containsAlias(alias))
+ {
+ return null;
+ }
+ List l = get(alias);
+ PasswordAuthenticatedEntry e1 = null;
+ PasswordEncryptedEntry e2 = null;
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof PasswordAuthenticatedEntry)
+ {
+ e1 = (PasswordAuthenticatedEntry) e;
+ break;
+ }
+ }
+ if (e1 == null)
+ {
+ return null;
+ }
+ try
+ {
+ e1.verify(password);
+ }
+ catch (Exception e)
+ {
+ throw new UnrecoverableKeyException("authentication failed");
+ }
+ for (Iterator it = e1.getEntries().iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof PasswordEncryptedEntry)
+ {
+ e2 = (PasswordEncryptedEntry) e;
+ break;
+ }
+ }
+ if (e2 == null)
+ {
+ return null;
+ }
+ try
+ {
+ e2.decrypt(password);
+ }
+ catch (Exception e)
+ {
+ throw new UnrecoverableKeyException("decryption failed");
+ }
+ for (Iterator it = e2.get(alias).iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof PrivateKeyEntry)
+ {
+ return ((PrivateKeyEntry) e).getKey();
+ }
+ }
+ return null;
+ }
+
+ public void putPrivateKey(String alias, Key key, char[] password)
+ {
+ if (containsPrivateKey(alias))
+ {
+ return;
+ }
+ alias = fixAlias(alias);
+ Properties p = new Properties();
+ p.put("alias", alias);
+ PrivateKeyEntry pke = new PrivateKeyEntry(key, new Date(), p);
+ PasswordEncryptedEntry enc = new PasswordEncryptedEntry(cipher, mode,
+ keylen,
+ new Properties());
+ PasswordAuthenticatedEntry auth = new PasswordAuthenticatedEntry(
+ mac,
+ maclen,
+ new Properties());
+ enc.add(pke);
+ auth.add(enc);
+ try
+ {
+ enc.encode(null, password);
+ auth.encode(null, password);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException(ioe.toString());
+ }
+ keyring.add(auth);
+ }
+
+ public boolean containsPublicKey(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return false;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ if (it.next() instanceof PublicKeyEntry)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public PublicKey getPublicKey(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return null;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof PublicKeyEntry)
+ {
+ return ((PublicKeyEntry) e).getKey();
+ }
+ }
+ return null;
+ }
+
+ public void putPublicKey(String alias, PublicKey key)
+ {
+ if (containsPublicKey(alias))
+ {
+ return;
+ }
+ Properties p = new Properties();
+ p.put("alias", fixAlias(alias));
+ add(new PublicKeyEntry(key, new Date(), p));
+ }
+
+ public boolean containsCertPath(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return false;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ if (it.next() instanceof CertPathEntry)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Certificate[] getCertPath(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return null;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof CertPathEntry)
+ {
+ return ((CertPathEntry) e).getCertPath();
+ }
+ }
+ return null;
+ }
+
+ public void putCertPath(String alias, Certificate[] path)
+ {
+ if (containsCertPath(alias))
+ {
+ return;
+ }
+ Properties p = new Properties();
+ p.put("alias", fixAlias(alias));
+ add(new CertPathEntry(path, new Date(), p));
+ }
+
+ protected void load(InputStream in, char[] password) throws IOException
+ {
+ if (in.read() != USAGE)
+ {
+ throw new MalformedKeyringException("incompatible keyring usage");
+ }
+ if (in.read() != PasswordAuthenticatedEntry.TYPE)
+ {
+ throw new MalformedKeyringException(
+ "expecting password-authenticated entry tag");
+ }
+ keyring = PasswordAuthenticatedEntry.decode(new DataInputStream(in),
+ password);
+ }
+
+ protected void store(OutputStream out, char[] password) throws IOException
+ {
+ out.write(USAGE);
+ keyring.encode(new DataOutputStream(out), password);
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/GnuPublicKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/GnuPublicKeyring.java
new file mode 100644
index 00000000000..318eb036fc8
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/GnuPublicKeyring.java
@@ -0,0 +1,146 @@
+/* GnuPublicKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+import java.security.cert.Certificate;
+
+import gnu.java.security.Registry;
+
+public class GnuPublicKeyring extends BaseKeyring implements IPublicKeyring
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ public static final int USAGE = Registry.GKR_CERTIFICATES;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ public GnuPublicKeyring(String mac, int macLen)
+ {
+ keyring = new PasswordAuthenticatedEntry(mac, macLen, new Properties());
+ keyring2 = new CompressedEntry(new Properties());
+ keyring.add(keyring2);
+ }
+
+ public GnuPublicKeyring()
+ {
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public boolean containsCertificate(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return false;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ if (it.next() instanceof CertificateEntry)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Certificate getCertificate(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return null;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof CertificateEntry)
+ {
+ return ((CertificateEntry) e).getCertificate();
+ }
+ }
+ return null;
+ }
+
+ public void putCertificate(String alias, Certificate cert)
+ {
+ if (containsCertificate(alias))
+ {
+ return;
+ }
+ Properties p = new Properties();
+ p.put("alias", fixAlias(alias));
+ add(new CertificateEntry(cert, new Date(), p));
+ }
+
+ protected void load(InputStream in, char[] password) throws IOException
+ {
+ if (in.read() != USAGE)
+ {
+ throw new MalformedKeyringException("incompatible keyring usage");
+ }
+ if (in.read() != PasswordAuthenticatedEntry.TYPE)
+ {
+ throw new MalformedKeyringException(
+ "expecting password-authenticated entry tag");
+ }
+ keyring = PasswordAuthenticatedEntry.decode(new DataInputStream(in),
+ password);
+ }
+
+ protected void store(OutputStream out, char[] password) throws IOException
+ {
+ out.write(USAGE);
+ keyring.encode(new DataOutputStream(out), password);
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/IKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/IKeyring.java
new file mode 100644
index 00000000000..56f467df26e
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/IKeyring.java
@@ -0,0 +1,164 @@
+/* IKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>The top-level interface to a <i>keyring:</i> a file that is used to
+ * store and protect public and private cryptographic keys.</p>
+ *
+ * <p>A <i>keyring</i> is modelled as a mapping of one <i>alias</i> to one or
+ * more <i>entries</i> (optionally of different types).</p>
+ *
+ * <p>See also the sub-interfaces {@link IPublicKeyring} and
+ * {@link IPrivateKeyring} for special types of <i>keyrings</i> --the difference
+ * being in the type of entries they contain.</p>
+ */
+public interface IKeyring
+{
+
+ /**
+ * <p>Property name for the source of data to load the keyring from. The
+ * value mapped must be a {@link java.io.InputStream}.</p>
+ */
+ public static final String KEYRING_DATA_IN = "gnu.crypto.keyring.data.in";
+
+ /**
+ * <p>Property name for the data sink to store the keyring to. The value
+ * mapped must be a {@link java.io.OutputStream}.</p>
+ */
+ public static final String KEYRING_DATA_OUT = "gun.crypto.keyring.data.out";
+
+ /**
+ * <p>Property name for the keyring's top-level password, used to
+ * authenticate and/or transform the store itself. The mapped value must be a
+ * char array.</p>
+ */
+ public static final String KEYRING_PASSWORD = "gnu.crypto.keyring.password";
+
+ /**
+ * <p>Loads a keyring into memory.</p>
+ *
+ * <p>What happens to the current contents of this keyring? are the new ones
+ * merged with the current ones or do they simply replace them?</p>
+ *
+ * @param attributes The attributes that designate the source where the store
+ * is to be loaded from. What happens
+ * @throws IllegalArgumentException If the attributes are inappropriate.
+ * @throws IOException If the keyring file cannot be read.
+ * @throws SecurityException If the given password is incorrect, or if the
+ * top-level authentication or decryption fails.
+ */
+ void load(Map attributes) throws IOException;
+
+ /**
+ * <p>Stores the contents of this keyring to persistent storage as specified
+ * by the designated <code>attributes</code>.</p>
+ *
+ * @param attributes the attributes that define where the contents of this
+ * keyring will be stored.
+ * @throws IOException if an exception occurs during the process.
+ */
+ void store(Map attributes) throws IOException;
+
+ /**
+ * <p>Resets this keyring, clearing all sensitive data. This method always
+ * suceeds.</p>
+ */
+ void reset();
+
+ /**
+ * <p>Returns the number of entries in this keyring.</p>
+ *
+ * @return The number of current entries in this keyring.
+ */
+ int size();
+
+ /**
+ * <p>Returns an {@link Enumeration} of all aliases (instances of
+ * {@link String}) in this keyring.</p>
+ *
+ * @return The enumeration of {@link String}s each representing an
+ * <i>alias</i> found in this keyring.
+ */
+ Enumeration aliases();
+
+ /**
+ * Tests whether or not this keyring contains the given alias.
+ *
+ * @param alias The alias to check.
+ * @return true if this keyring contains the alias.
+ */
+ boolean containsAlias(String alias);
+
+ /**
+ * <p>Returns a {@link List} of entries (instances of {@link Entry}) for the
+ * given <code>alias</code>, or <code>null</code> if there no such entry
+ * exists.</p>
+ *
+ * @param alias The alias of the entry(ies) to return.
+ * @return A list of all entries (instances of {@link Entry} that have the
+ * given <code>alias</code>, or <code>null</code> if no one {@link Entry} can
+ * be found with the designated <code>alias</code>.
+ */
+ List get(String alias);
+
+ /**
+ * <p>Adds a designated {@link Entry} to this keyring.</p>
+ *
+ * <p>What happens if there is already an entry with the same alias?</p>
+ *
+ * @param entry The entry to put in this keyring.
+ */
+ void add(Entry entry);
+
+ /**
+ * <p>Removes an entry with the designated <code>alias</code> from this
+ * keyring. Does nothing if there was no such entry.</p>
+ *
+ * <p>What happens if there are more than one?</p>
+ *
+ * @param alias The alias of the entry to remove.
+ */
+ void remove(String alias);
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/IPrivateKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/IPrivateKeyring.java
new file mode 100644
index 00000000000..66bbd84f568
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/IPrivateKeyring.java
@@ -0,0 +1,142 @@
+/* IPrivateKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.security.Key;
+import java.security.PublicKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+
+/**
+ * <p>An interface to private, or "personal", keyrings, which contain private
+ * credentials. The contract is that each such entry is known by a unique
+ * <i>alias</i>.</p>
+ *
+ * <p>What about public keys? and certificate-path?</p>
+ */
+public interface IPrivateKeyring extends IKeyring
+{
+
+ /**
+ * <p>Tests if this keyring contains a private key entry with the given
+ * <code>alias</code>.</p>
+ *
+ * @param alias The alias to check.
+ * @return <code>true</code> if this keyring contains a private key with the
+ * given <code>alias</code>; <code>false</code> otherwise.</p>
+ */
+ boolean containsPrivateKey(String alias);
+
+ /**
+ * <p>Returns the private key with the given <code>alias</code>.</p>
+ *
+ * @param alias The alias of the private key to find.
+ * @param password The password of the private key.
+ * @return The private, or secret, key if one is found; <code>null</code> if
+ * none were found.
+ * @throws UnrecoverableKeyException If the private key could not be
+ * recovered, possibly due to a bad password.
+ */
+ Key getPrivateKey(String alias, char[] password)
+ throws UnrecoverableKeyException;
+
+ /**
+ * <p>Adds a private key to this keyring.</p>
+ *
+ * @param alias The alias of the private key.
+ * @param key The private key.
+ * @param password The password used to protect this private key.
+ */
+ void putPrivateKey(String alias, Key key, char[] password);
+
+ /**
+ * <p>Checks if this keyring contains a public key with the given
+ * <code>alias</code>.</p>
+ *
+ * @param alias The alias to test.
+ * @return <code>true</code> if this keyring contains a public key entry with
+ * the given <code>alias</code>; <code>false</code> otherwise.
+ */
+ boolean containsPublicKey(String alias);
+
+ /**
+ * <p>Returns the public key with the given <code>alias</code>, or
+ * <code>null</code> if there is no such entry.</p>
+ *
+ * @param alias The alias of the public key to find.
+ * @return The public key; or <code>null</code> if none were found.
+ */
+ PublicKey getPublicKey(String alias);
+
+ /**
+ * <p>Sets a public key entry.</p>
+ *
+ * @param alias The alias for this public key.
+ * @param key The public key.
+ */
+ void putPublicKey(String alias, PublicKey key);
+
+ /**
+ * <p>Checks if this keyring contains a certificate path with the given
+ * <code>alias</code>.</p>
+ *
+ * @param alias The alias to check.
+ * @return <code>true</code> if this keyring contains a certificate path with
+ * the given <code>alias</code>; <code>false</code> otherwise.
+ */
+ boolean containsCertPath(String alias);
+
+ /**
+ * <p>Returns the certificate path with the given <code>alias</code>, or
+ * <code>null</code> if there is no such entry.</p>
+ *
+ * @param alias The alias of the certificate path to find.
+ * @return The certificate path for the designated <code>alias</code>; or
+ * <code>null</code> if none were found.
+ */
+ Certificate[] getCertPath(String alias);
+
+ /**
+ * <p>Sets a certificate path entry.</p>
+ *
+ * @param alias The alias for this certificate path.
+ * @param path The certificate path.
+ */
+ void putCertPath(String alias, Certificate[] path);
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/IPublicKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/IPublicKeyring.java
new file mode 100644
index 00000000000..ccf9ca73b55
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/IPublicKeyring.java
@@ -0,0 +1,81 @@
+/* IPublicKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.security.cert.Certificate;
+
+/**
+ * <p>An interface for keyrings that contain trusted (by the owner) public
+ * credentials (incl. certificates).</p>
+ *
+ * @see IKeyring
+ */
+public interface IPublicKeyring extends IKeyring
+{
+
+ /**
+ * <p>Tests if this keyring contains a certificate entry with the specified
+ * <code>alias</code>.</p>
+ *
+ * @param alias The alias of the certificate to check.
+ * @return <code>true</code> if this keyring contains a certificate entry
+ * that has the given <code>alias</code>; <code>false</code> otherwise.
+ */
+ boolean containsCertificate(String alias);
+
+ /**
+ * <p>Returns a certificate that has the given <code>alias</code>, or
+ * <code>null</code> if this keyring has no such entry.</p>
+ *
+ * @param alias The alias of the certificate to find.
+ * @return The certificate with the designated <code>alias</code>, or
+ * <code>null</code> if none found.
+ */
+ Certificate getCertificate(String alias);
+
+ /**
+ * <p>Adds a certificate in this keyring, with the given <code>alias</code>.</p>
+ *
+ * <p>What happens if there is already a certificate entry with this alias?</p>
+ *
+ * @param alias The alias of this certificate entry.
+ * @param cert The certificate.
+ */
+ void putCertificate(String alias, Certificate cert);
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/MalformedKeyringException.java b/libjava/classpath/gnu/javax/crypto/keyring/MalformedKeyringException.java
new file mode 100644
index 00000000000..44c953946d4
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/MalformedKeyringException.java
@@ -0,0 +1,58 @@
+/* MalformedKeyringException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.IOException;
+
+public class MalformedKeyringException extends IOException
+{
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ public MalformedKeyringException()
+ {
+ super();
+ }
+
+ public MalformedKeyringException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java
new file mode 100644
index 00000000000..7fed7c40c15
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java
@@ -0,0 +1,148 @@
+/* MaskableEnvelopeEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An envelope entry that can be "masked" -- placed in a state where the
+ * envelope's contents cannot be accessed, due to the envelope not being
+ * fully decoded, for example.
+ */
+public abstract class MaskableEnvelopeEntry extends EnvelopeEntry
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The masked state. */
+ protected boolean masked;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ public MaskableEnvelopeEntry(int type, Properties properties)
+ {
+ super(type, properties);
+ }
+
+ protected MaskableEnvelopeEntry(int type)
+ {
+ super(type);
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Sets the masked state to the specified value.
+ *
+ * @param masked The new masked state.
+ */
+ protected final void setMasked(boolean masked)
+ {
+ this.masked = masked;
+ }
+
+ /**
+ * Gets the masked state of this object. Certain operations on this object
+ * will fail if it is masked.
+ *
+ * @return The current masked state.
+ */
+ public boolean isMasked()
+ {
+ return masked;
+ }
+
+ public void add(Entry entry)
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ super.add(entry);
+ }
+
+ public boolean containsEntry(Entry entry)
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ return super.containsEntry(entry);
+ }
+
+ public List getEntries()
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ return new ArrayList(entries);
+ }
+
+ public List get(String alias)
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ return super.get(alias);
+ }
+
+ public boolean remove(Entry entry)
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ return super.remove(entry);
+ }
+
+ public void remove(String alias)
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ super.remove(alias);
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/MeteredInputStream.java b/libjava/classpath/gnu/javax/crypto/keyring/MeteredInputStream.java
new file mode 100644
index 00000000000..fcf2be746c9
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/MeteredInputStream.java
@@ -0,0 +1,137 @@
+/* MeteredInputStream.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+final class MeteredInputStream extends FilterInputStream
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ private int count;
+
+ private final int limit;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ MeteredInputStream(InputStream in, int limit)
+ {
+ super(in);
+ if (limit < 0)
+ throw new IllegalArgumentException("limit must be nonnegative");
+ this.limit = limit;
+ count = 0;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Tests if the number of bytes read has reached the limit.
+ *
+ * @return True if the limit has been reached.
+ */
+ public boolean limitReached()
+ {
+ return count == limit;
+ }
+
+ public int available() throws IOException
+ {
+ return Math.min(in.available(), limit - count);
+ }
+
+ public void close() throws IOException
+ {
+ in.close();
+ }
+
+ public void mark(int readLimit)
+ {
+ }
+
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ public int read() throws IOException
+ {
+ if (limitReached())
+ return -1;
+ int i = in.read();
+ if (i != -1)
+ count++;
+ return i;
+ }
+
+ public int read(byte[] buf) throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ public int read(byte[] buf, int off, int len) throws IOException
+ {
+ if (limitReached())
+ return -1;
+ int i = in.read(buf, off, Math.min(len, limit - count));
+ if (i != -1)
+ count += i;
+ return i;
+ }
+
+ public void reset() throws IOException
+ {
+ }
+
+ public long skip(long len) throws IOException
+ {
+ if (limitReached())
+ return 0L;
+ len = Math.min(len, limit - count);
+ len = in.skip(len);
+ count += (int) len;
+ return len;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java
new file mode 100644
index 00000000000..2e3a0d145c8
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java
@@ -0,0 +1,285 @@
+/* PasswordAuthenticatedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import gnu.java.security.Registry;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mac.MacFactory;
+import gnu.javax.crypto.mac.MacInputStream;
+import gnu.javax.crypto.mac.MacOutputStream;
+import gnu.javax.crypto.prng.IPBE;
+import gnu.javax.crypto.prng.PRNGFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.HashMap;
+
+/**
+ * <p>An entry authenticated with a password-based MAC.</p>
+ */
+public final class PasswordAuthenticatedEntry extends MaskableEnvelopeEntry
+ implements PasswordProtectedEntry, Registry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int TYPE = 3;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public PasswordAuthenticatedEntry(String mac, int maclen,
+ Properties properties)
+ {
+ super(TYPE, properties);
+
+ if (mac == null || mac.length() == 0)
+ {
+ throw new IllegalArgumentException("no MAC specified");
+ }
+ this.properties.put("mac", mac);
+ this.properties.put("maclen", String.valueOf(maclen));
+ setMasked(false);
+ }
+
+ private PasswordAuthenticatedEntry()
+ {
+ super(TYPE);
+ setMasked(true);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static PasswordAuthenticatedEntry decode(DataInputStream in,
+ char[] password)
+ throws IOException
+ {
+ PasswordAuthenticatedEntry entry = new PasswordAuthenticatedEntry();
+ entry.properties.decode(in);
+ IMac mac = entry.getMac(password);
+ int len = in.readInt() - mac.macSize();
+ MeteredInputStream min = new MeteredInputStream(in, len);
+ MacInputStream macin = new MacInputStream(min, mac);
+ DataInputStream in2 = new DataInputStream(macin);
+ entry.setMasked(false);
+ entry.decodeEnvelope(in2);
+ byte[] macValue = new byte[mac.macSize()];
+ in.readFully(macValue);
+ if (!Arrays.equals(macValue, mac.digest()))
+ {
+ throw new MalformedKeyringException("MAC verification failed");
+ }
+ return entry;
+ }
+
+ public static PasswordAuthenticatedEntry decode(DataInputStream in)
+ throws IOException
+ {
+ PasswordAuthenticatedEntry entry = new PasswordAuthenticatedEntry();
+ entry.defaultDecode(in);
+ if (!entry.properties.containsKey("mac"))
+ {
+ throw new MalformedKeyringException("no MAC");
+ }
+ if (!entry.properties.containsKey("maclen"))
+ {
+ throw new MalformedKeyringException("no MAC length");
+ }
+ if (!entry.properties.containsKey("salt"))
+ {
+ throw new MalformedKeyringException("no salt");
+ }
+ return entry;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public void verify(char[] password)
+ {
+ if (!isMasked() || payload == null)
+ {
+ return;
+ }
+ IMac m = null;
+ try
+ {
+ m = getMac(password);
+ }
+ catch (Exception x)
+ {
+ throw new IllegalArgumentException(x.toString());
+ }
+
+ m.update(payload, 0, payload.length - m.macSize());
+ byte[] macValue = new byte[m.macSize()];
+ System.arraycopy(payload, payload.length - macValue.length, macValue, 0,
+ macValue.length);
+ if (!Arrays.equals(macValue, m.digest()))
+ {
+ throw new IllegalArgumentException("MAC verification failed");
+ }
+ try
+ {
+ DataInputStream in = new DataInputStream(
+ new ByteArrayInputStream(
+ payload,
+ 0,
+ payload.length
+ - m.macSize()));
+ decodeEnvelope(in);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException("malformed keyring fragment");
+ }
+ setMasked(false);
+ payload = null;
+ }
+
+ public void authenticate(char[] password) throws IOException
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("entry is masked");
+ }
+ byte[] salt = new byte[8];
+ new SecureRandom ().nextBytes (salt);
+ properties.put("salt", Util.toString(salt));
+ IMac m = getMac(password);
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ MacOutputStream macout = new MacOutputStream(bout, m);
+ DataOutputStream out2 = new DataOutputStream(macout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry entry = (Entry) it.next();
+ entry.encode(out2);
+ }
+ bout.write(m.digest());
+ payload = bout.toByteArray();
+ }
+
+ public void encode(DataOutputStream out, char[] password) throws IOException
+ {
+ authenticate(password);
+ encode(out);
+ }
+
+ protected void encodePayload(DataOutputStream out) throws IOException
+ {
+ if (payload == null)
+ {
+ throw new IllegalStateException("mac not computed");
+ }
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private IMac getMac(char[] password) throws MalformedKeyringException
+ {
+ if (!properties.containsKey("salt"))
+ {
+ throw new MalformedKeyringException("no salt");
+ }
+ byte[] salt = Util.toBytesFromString(properties.get("salt"));
+ IMac mac = MacFactory.getInstance(properties.get("mac"));
+ if (mac == null)
+ {
+ throw new MalformedKeyringException("no such mac: "
+ + properties.get("mac"));
+ }
+ int keylen = mac.macSize();
+ int maclen = 0;
+ if (!properties.containsKey("maclen"))
+ {
+ throw new MalformedKeyringException("no MAC length");
+ }
+ try
+ {
+ maclen = Integer.parseInt(properties.get("maclen"));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new MalformedKeyringException("bad MAC length");
+ }
+
+ HashMap pbAttr = new HashMap();
+ pbAttr.put(IPBE.PASSWORD, password);
+ pbAttr.put(IPBE.SALT, salt);
+ pbAttr.put(IPBE.ITERATION_COUNT, ITERATION_COUNT);
+ IRandom kdf = PRNGFactory.getInstance("PBKDF2-HMAC-SHA");
+ kdf.init(pbAttr);
+
+ byte[] dk = new byte[keylen];
+ try
+ {
+ kdf.nextBytes(dk, 0, keylen);
+ }
+ catch (LimitReachedException shouldNotHappen)
+ {
+ throw new Error(shouldNotHappen.toString());
+ }
+
+ HashMap macAttr = new HashMap();
+ macAttr.put(IMac.MAC_KEY_MATERIAL, dk);
+ macAttr.put(IMac.TRUNCATED_SIZE, new Integer(maclen));
+ try
+ {
+ mac.init(macAttr);
+ }
+ catch (InvalidKeyException shouldNotHappen)
+ {
+ throw new Error(shouldNotHappen.toString());
+ }
+ return mac;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/PasswordEncryptedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PasswordEncryptedEntry.java
new file mode 100644
index 00000000000..26b4032bdfb
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/PasswordEncryptedEntry.java
@@ -0,0 +1,301 @@
+/* PasswordEncryptedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import gnu.java.security.Registry;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.Util;
+
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.mode.ModeFactory;
+import gnu.javax.crypto.pad.IPad;
+import gnu.javax.crypto.pad.PadFactory;
+import gnu.javax.crypto.pad.WrongPaddingException;
+import gnu.javax.crypto.prng.IPBE;
+import gnu.javax.crypto.prng.PRNGFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * An envelope that is encrypted with a password-derived key.
+ */
+public class PasswordEncryptedEntry extends MaskableEnvelopeEntry implements
+ PasswordProtectedEntry, Registry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 1;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ public PasswordEncryptedEntry(String cipher, String mode, int keylen,
+ Properties properties)
+ {
+ super(TYPE, properties);
+ if ((cipher == null || cipher.length() == 0)
+ || (mode == null || mode.length() == 0))
+ {
+ throw new IllegalArgumentException("cipher nor mode can be empty");
+ }
+ this.properties.put("cipher", cipher);
+ this.properties.put("mode", mode);
+ this.properties.put("keylen", String.valueOf(keylen));
+ setMasked(false);
+ }
+
+ private PasswordEncryptedEntry()
+ {
+ super(TYPE);
+ setMasked(true);
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ public static PasswordEncryptedEntry decode(DataInputStream in,
+ char[] password)
+ throws IOException
+ {
+ PasswordEncryptedEntry entry = decode(in);
+ try
+ {
+ entry.decrypt(password);
+ }
+ catch (WrongPaddingException wpe)
+ {
+ throw new MalformedKeyringException("wrong padding in decrypted data");
+ }
+ return entry;
+ }
+
+ public static PasswordEncryptedEntry decode(DataInputStream in)
+ throws IOException
+ {
+ PasswordEncryptedEntry entry = new PasswordEncryptedEntry();
+ entry.defaultDecode(in);
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public void decrypt(char[] password) throws IllegalArgumentException,
+ WrongPaddingException
+ {
+ if (!isMasked() || payload == null)
+ {
+ return;
+ }
+ IMode mode = getMode(password, IMode.DECRYPTION);
+ IPad padding = PadFactory.getInstance("PKCS7");
+ padding.init(mode.currentBlockSize());
+ byte[] buf = new byte[payload.length];
+ int count = 0;
+ for (int i = 0; i < payload.length; i++)
+ {
+ mode.update(payload, count, buf, count);
+ count += mode.currentBlockSize();
+ }
+ int padlen = padding.unpad(buf, 0, buf.length);
+ DataInputStream in = new DataInputStream(
+ new ByteArrayInputStream(
+ buf,
+ 0,
+ buf.length
+ - padlen));
+ try
+ {
+ decodeEnvelope(in);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException("decryption failed");
+ }
+ setMasked(false);
+ payload = null;
+ }
+
+ public void encrypt(char[] password) throws IOException
+ {
+ byte[] salt = new byte[8];
+ new SecureRandom ().nextBytes (salt);
+ properties.put("salt", Util.toString(salt));
+ IMode mode = getMode(password, IMode.ENCRYPTION);
+ IPad pad = PadFactory.getInstance("PKCS7");
+ pad.init(mode.currentBlockSize());
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ DataOutputStream out2 = new DataOutputStream(bout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry entry = (Entry) it.next();
+ entry.encode(out2);
+ }
+ byte[] plaintext = bout.toByteArray();
+ byte[] padding = pad.pad(plaintext, 0, plaintext.length);
+ payload = new byte[plaintext.length + padding.length];
+ byte[] lastBlock = new byte[mode.currentBlockSize()];
+ int l = mode.currentBlockSize() - padding.length;
+ System.arraycopy(plaintext, plaintext.length - l, lastBlock, 0, l);
+ System.arraycopy(padding, 0, lastBlock, l, padding.length);
+ int count = 0;
+ while (count + mode.currentBlockSize() < plaintext.length)
+ {
+ mode.update(plaintext, count, payload, count);
+ count += mode.currentBlockSize();
+ }
+ mode.update(lastBlock, 0, payload, count);
+ }
+
+ public void encode(DataOutputStream out, char[] password) throws IOException
+ {
+ encrypt(password);
+ encode(out);
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ if (payload == null)
+ {
+ throw new IllegalStateException("not encrypted");
+ }
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private IMode getMode(char[] password, int state)
+ {
+ String s = properties.get("salt");
+ if (s == null)
+ {
+ throw new IllegalArgumentException("no salt");
+ }
+ byte[] salt = Util.toBytesFromString(s);
+ IBlockCipher cipher = CipherFactory.getInstance(properties.get("cipher"));
+ if (cipher == null)
+ {
+ throw new IllegalArgumentException("no such cipher: "
+ + properties.get("cipher"));
+ }
+ int blockSize = cipher.defaultBlockSize();
+ if (properties.containsKey("block-size"))
+ {
+ try
+ {
+ blockSize = Integer.parseInt(properties.get("block-size"));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new IllegalArgumentException("bad block size: "
+ + nfe.getMessage());
+ }
+ }
+ IMode mode = ModeFactory.getInstance(properties.get("mode"), cipher,
+ blockSize);
+ if (mode == null)
+ {
+ throw new IllegalArgumentException("no such mode: "
+ + properties.get("mode"));
+ }
+
+ HashMap pbAttr = new HashMap();
+ pbAttr.put(IPBE.PASSWORD, password);
+ pbAttr.put(IPBE.SALT, salt);
+ pbAttr.put(IPBE.ITERATION_COUNT, ITERATION_COUNT);
+ IRandom kdf = PRNGFactory.getInstance("PBKDF2-HMAC-SHA");
+ kdf.init(pbAttr);
+
+ int keylen = 0;
+ if (!properties.containsKey("keylen"))
+ {
+ throw new IllegalArgumentException("no key length");
+ }
+ try
+ {
+ keylen = Integer.parseInt(properties.get("keylen"));
+ }
+ catch (NumberFormatException nfe)
+ {
+ }
+ byte[] dk = new byte[keylen];
+ byte[] iv = new byte[blockSize];
+ try
+ {
+ kdf.nextBytes(dk, 0, keylen);
+ kdf.nextBytes(iv, 0, blockSize);
+ }
+ catch (LimitReachedException shouldNotHappen)
+ {
+ throw new Error(shouldNotHappen.toString());
+ }
+ HashMap modeAttr = new HashMap();
+ modeAttr.put(IMode.KEY_MATERIAL, dk);
+ modeAttr.put(IMode.STATE, new Integer(state));
+ modeAttr.put(IMode.IV, iv);
+ try
+ {
+ mode.init(modeAttr);
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new IllegalArgumentException(ike.toString());
+ }
+ return mode;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/PasswordProtectedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PasswordProtectedEntry.java
new file mode 100644
index 00000000000..0dcf73eb8d2
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/PasswordProtectedEntry.java
@@ -0,0 +1,66 @@
+/* PasswordProtectedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public interface PasswordProtectedEntry
+{
+
+ // Constant.
+ // ------------------------------------------------------------------------
+
+ /**
+ * The iteration count for password-based KDFs.
+ */
+ Integer ITERATION_COUNT = new Integer(1000);
+
+ // Method.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Encodes this entry, protected by a password.
+ *
+ * @param out The output stream to encode to.
+ * @param password The password.
+ * @throws IOException If an I/O error occurs.
+ */
+ void encode(DataOutputStream out, char[] password) throws IOException;
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/PrimitiveEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PrimitiveEntry.java
new file mode 100644
index 00000000000..4c9ff0ff1d9
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/PrimitiveEntry.java
@@ -0,0 +1,129 @@
+/* PrimitiveEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.util.Date;
+
+/**
+ * A primitive entry is an entry that contains a single cryptographic entity.
+ */
+public abstract class PrimitiveEntry extends Entry
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The creation date. */
+ protected Date creationDate;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ protected PrimitiveEntry(int type, Date creationDate, Properties properties)
+ {
+ super(type, properties);
+ if (creationDate == null)
+ {
+ this.creationDate = new Date();
+ }
+ else
+ {
+ this.creationDate = (Date) creationDate.clone();
+ }
+ if (!this.properties.containsKey("alias")
+ || this.properties.get("alias").length() == 0)
+ {
+ throw new IllegalArgumentException(
+ "primitive entries MUST have an alias");
+ }
+ this.properties.put("creation-date", String.valueOf(creationDate.getTime()));
+ }
+
+ protected PrimitiveEntry(int type)
+ {
+ super(type);
+ }
+
+ // Instance method.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the alias of this primitive entry.
+ *
+ * @return The alias.
+ */
+ public String getAlias()
+ {
+ return properties.get("alias");
+ }
+
+ /**
+ * Returns the creation date of this primitive entry.
+ *
+ * @return The creation date.
+ */
+ public Date getCreationDate()
+ {
+ return (Date) creationDate.clone();
+ }
+
+ public boolean equals(Object object)
+ {
+ if (!getClass().equals(object.getClass()))
+ return false;
+ return getAlias().equals(((PrimitiveEntry) object).getAlias());
+ }
+
+ protected final void makeCreationDate() throws MalformedKeyringException
+ {
+ String s = properties.get("creation-date");
+ if (s == null)
+ {
+ throw new MalformedKeyringException("no creation date");
+ }
+ try
+ {
+ creationDate = new Date(Long.parseLong(s));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new MalformedKeyringException("invalid creation date");
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/PrivateKeyEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PrivateKeyEntry.java
new file mode 100644
index 00000000000..30634991570
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/PrivateKeyEntry.java
@@ -0,0 +1,221 @@
+/* PrivateKeyEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.key.KeyPairCodecFactory;
+import gnu.java.security.key.dss.DSSPrivateKey;
+import gnu.java.security.key.rsa.GnuRSAPrivateKey;
+
+import gnu.javax.crypto.key.GnuSecretKey;
+import gnu.javax.crypto.key.dh.GnuDHPrivateKey;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Date;
+
+/**
+ * <p>An immutable class representing a private or secret key entry.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class PrivateKeyEntry extends PrimitiveEntry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int TYPE = 7;
+
+ /** The key. */
+ private Key key;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Creates a new key entry.</p>
+ *
+ * @param key The key.
+ * @param creationDate The entry creation date.
+ * @param properties The entry properties.
+ * @throws IllegalArgumentException If any parameter is null.
+ */
+ public PrivateKeyEntry(Key key, Date creationDate, Properties properties)
+ {
+ super(TYPE, creationDate, properties);
+
+ if (key == null)
+ {
+ throw new IllegalArgumentException("no private key");
+ }
+ if (!(key instanceof PrivateKey) && !(key instanceof GnuSecretKey))
+ {
+ throw new IllegalArgumentException("not a private or secret key");
+ }
+ this.key = key;
+ }
+
+ private PrivateKeyEntry()
+ {
+ super(TYPE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static PrivateKeyEntry decode(DataInputStream in) throws IOException
+ {
+ PrivateKeyEntry entry = new PrivateKeyEntry();
+ entry.defaultDecode(in);
+ String type = entry.properties.get("type");
+ if (type == null)
+ {
+ throw new MalformedKeyringException("no key type");
+ }
+ if (type.equalsIgnoreCase("RAW-DSS"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
+ entry.key = coder.decodePrivateKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("RAW-RSA"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("rsa");
+ entry.key = coder.decodePrivateKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("RAW-DH"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dh");
+ entry.key = coder.decodePrivateKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("RAW"))
+ {
+ entry.key = new GnuSecretKey(entry.payload, null);
+ }
+ else if (type.equalsIgnoreCase("PKCS8"))
+ {
+ try
+ {
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ entry.key = kf.generatePrivate(new PKCS8EncodedKeySpec(
+ entry.payload));
+ }
+ catch (Exception x)
+ {
+ }
+ if (entry.key == null)
+ {
+ try
+ {
+ KeyFactory kf = KeyFactory.getInstance("DSA");
+ entry.key = kf.generatePrivate(new PKCS8EncodedKeySpec(
+ entry.payload));
+ }
+ catch (Exception x)
+ {
+ }
+ if (entry.key == null)
+ {
+ throw new MalformedKeyringException(
+ "could not decode PKCS#8 key");
+ }
+ }
+ }
+ else
+ {
+ throw new MalformedKeyringException("unsupported key type " + type);
+ }
+ return entry;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns this entry's key.</p>
+ *
+ * @return The key.
+ */
+ public Key getKey()
+ {
+ return key;
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ String format = key.getFormat();
+ if (key instanceof DSSPrivateKey)
+ {
+ properties.put("type", "RAW-DSS");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
+ payload = coder.encodePrivateKey((PrivateKey) key);
+ }
+ else if (key instanceof GnuRSAPrivateKey)
+ {
+ properties.put("type", "RAW-RSA");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("rsa");
+ payload = coder.encodePrivateKey((PrivateKey) key);
+ }
+ else if (key instanceof GnuDHPrivateKey)
+ {
+ properties.put("type", "RAW-DH");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dh");
+ payload = coder.encodePrivateKey((PrivateKey) key);
+ }
+ else if (key instanceof GnuSecretKey)
+ {
+ properties.put("type", "RAW");
+ payload = key.getEncoded();
+ }
+ else if (format != null && format.equals("PKCS#8"))
+ {
+ properties.put("type", "PKCS8");
+ payload = key.getEncoded();
+ }
+ else
+ {
+ throw new IllegalArgumentException("unsupported private key");
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/Properties.java b/libjava/classpath/gnu/javax/crypto/keyring/Properties.java
new file mode 100644
index 00000000000..646b5711df2
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/Properties.java
@@ -0,0 +1,227 @@
+/* Properties.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * A set of <code>(name =&gt; value)</code> pairs used in keyring entries.
+ * Keys and values are simple strings, with the key never being empty and
+ * always treated case-insensitively.
+ */
+public class Properties implements Cloneable
+{
+
+ // Field.
+ // ------------------------------------------------------------------------
+
+ private HashMap props;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new properties object.
+ */
+ public Properties()
+ {
+ props = new HashMap();
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Removes all properties from this object.
+ */
+ public void clear()
+ {
+ props.clear();
+ }
+
+ /**
+ * Creates a copy of this properties object.
+ *
+ * @return The copy.
+ */
+ public Object clone()
+ {
+ Properties result = new Properties();
+ result.props.putAll(props);
+ return result;
+ }
+
+ /**
+ * Tests if this object contains a given property name.
+ *
+ * @param key The key to test.
+ * @return True if this object contains the given key.
+ */
+ public boolean containsKey(String key)
+ {
+ if (key == null || key.length() == 0)
+ {
+ return false;
+ }
+ return props.containsKey(canonicalize(key));
+ }
+
+ /**
+ * Tests if this object contains a given property value.
+ *
+ * @param value The value to test.
+ * @return True if this object contains the given value.
+ */
+ public boolean containsValue(String value)
+ {
+ if (value == null)
+ {
+ return false;
+ }
+ return props.containsValue(value);
+ }
+
+ /**
+ * Adds a new property to this object.
+ *
+ * @param key The key, which can neither be null nor empty.
+ * @param value The value, which cannot be null.
+ * @return The old value mapped by the key, if any.
+ * @throws IllegalArgumentException If either the key or value parameter
+
+ * is null, or if the key is empty.
+ */
+ public String put(String key, String value)
+ {
+ if (key == null || value == null || key.length() == 0)
+ {
+ throw new IllegalArgumentException("key nor value can be null");
+ }
+ return (String) props.put(canonicalize(key), value);
+ }
+
+ /**
+ * Returns the value mapped by the given key, or null if there is no
+ * such mapping.
+ *
+ * @param key
+ */
+ public String get(String key)
+ {
+ if (key == null || key.length() == 0)
+ {
+ return null;
+ }
+ return (String) props.get(canonicalize(key));
+ }
+
+ /**
+ * Removes a key and its value from this object.
+ *
+ * @param key The key of the property to remove.
+ * @return The old value mapped by the key, if any.
+ */
+ public String remove(String key)
+ {
+ if (key == null || key.length() == 0)
+ {
+ return null;
+ }
+ return (String) props.remove(canonicalize(key));
+ }
+
+ /**
+ * Decodes a set of properties from the given input stream.
+ *
+ * @param in The input stream.
+ * @throws IOException If an I/O error occurs.
+ */
+ public void decode(DataInputStream in) throws IOException
+ {
+ int len = in.readInt();
+ MeteredInputStream min = new MeteredInputStream(in, len);
+ DataInputStream in2 = new DataInputStream(min);
+ while (!min.limitReached())
+ {
+ String name = in2.readUTF();
+ String value = in2.readUTF();
+ put(name, value);
+ }
+ }
+
+ /**
+ * Encodes this set of properties to the given output stream.
+ *
+ * @param out The output stream to encode to.
+ * @throws IOException If an I/O error occurs.
+ */
+ public void encode(DataOutputStream out) throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ DataOutputStream out2 = new DataOutputStream(buf);
+ for (Iterator it = props.entrySet().iterator(); it.hasNext();)
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ out2.writeUTF((String) entry.getKey());
+ out2.writeUTF((String) entry.getValue());
+ }
+ out.writeInt(buf.size());
+ buf.writeTo(out);
+ }
+
+ public String toString()
+ {
+ return props.toString();
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private String canonicalize(String key)
+ {
+ return key.toLowerCase();
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/keyring/PublicKeyEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PublicKeyEntry.java
new file mode 100644
index 00000000000..528e70cc648
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/keyring/PublicKeyEntry.java
@@ -0,0 +1,192 @@
+/* PublicKeyEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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.javax.crypto.keyring;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.PublicKey;
+import java.security.KeyFactory;
+import java.security.spec.X509EncodedKeySpec;
+
+import java.util.Date;
+
+import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.key.KeyPairCodecFactory;
+import gnu.java.security.key.dss.DSSPublicKey;
+import gnu.java.security.key.rsa.GnuRSAPublicKey;
+import gnu.javax.crypto.key.dh.GnuDHPublicKey;
+
+public final class PublicKeyEntry extends PrimitiveEntry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 6;
+
+ private PublicKey key;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public PublicKeyEntry(PublicKey key, Date creationDate, Properties properties)
+ {
+ super(TYPE, creationDate, properties);
+
+ if (key == null)
+ {
+ throw new IllegalArgumentException("no key specified");
+ }
+ this.key = key;
+ }
+
+ private PublicKeyEntry()
+ {
+ super(TYPE);
+ }
+
+ // Class method.
+ // ------------------------------------------------------------------------
+
+ public static PublicKeyEntry decode(DataInputStream in) throws IOException
+ {
+ PublicKeyEntry entry = new PublicKeyEntry();
+ entry.defaultDecode(in);
+ String type = entry.properties.get("type");
+ if (type == null)
+ {
+ throw new MalformedKeyringException("no key type");
+ }
+ if (type.equalsIgnoreCase("RAW-DSS"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
+ entry.key = coder.decodePublicKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("RAW-RSA"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("rsa");
+ entry.key = coder.decodePublicKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("RAW-DH"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dh");
+ entry.key = coder.decodePublicKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("X.509"))
+ {
+ try
+ {
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ entry.key = kf.generatePublic(new X509EncodedKeySpec(entry.payload));
+ }
+ catch (Exception x)
+ {
+ }
+ if (entry.key == null)
+ {
+ try
+ {
+ KeyFactory kf = KeyFactory.getInstance("DSA");
+ entry.key = kf.generatePublic(new X509EncodedKeySpec(
+ entry.payload));
+ }
+ catch (Exception x)
+ {
+ }
+ if (entry.key == null)
+ {
+ throw new MalformedKeyringException(
+ "could not decode X.509 key");
+ }
+ }
+ }
+ else
+ {
+ throw new MalformedKeyringException("unsupported public key type: "
+ + type);
+ }
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the public key.
+ *
+ * @return The public key.
+ */
+ public PublicKey getKey()
+ {
+ return key;
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ if (key instanceof DSSPublicKey)
+ {
+ properties.put("type", "RAW-DSS");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
+ payload = coder.encodePublicKey(key);
+ }
+ else if (key instanceof GnuRSAPublicKey)
+ {
+ properties.put("type", "RAW-RSA");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("rsa");
+ payload = coder.encodePublicKey(key);
+ }
+ else if (key instanceof GnuDHPublicKey)
+ {
+ properties.put("type", "RAW-DH");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dh");
+ payload = coder.encodePublicKey(key);
+ }
+ else if (key.getFormat() != null && key.getFormat().equals("X.509"))
+ {
+ properties.put("type", "X.509");
+ payload = key.getEncoded();
+ }
+ else
+ {
+ throw new IllegalArgumentException("cannot encode public key");
+ }
+ }
+}
OpenPOWER on IntegriCloud