Initial revision

From-SVN: r102074
This commit is contained in:
Tom Tromey
2005-07-16 00:30:23 +00:00
parent 6f4434b39b
commit f911ba985a
4557 changed files with 1000262 additions and 0 deletions
@@ -0,0 +1,237 @@
/* Engine -- generic getInstance method.
Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
/**
* Generic implementation of the getInstance methods in the various
* engine classes in java.security.
* <p>
* These classes ({@link java.security.Signature} for example) can be
* thought of as the "chrome, upholstery, and steering wheel", and the SPI
* (service provider interface, e.g. {@link java.security.SignatureSpi})
* classes can be thought of as the "engine" -- providing the actual
* functionality of whatever cryptographic algorithm the instance
* represents.
*
* @see Provider
* @author Casey Marshall
*/
public final class Engine
{
// Constants.
// ------------------------------------------------------------------------
/** Prefix for aliases. */
private static final String ALG_ALIAS = "Alg.Alias.";
/** Maximum number of aliases to try. */
private static final int MAX_ALIASES = 5;
/** Argument list for no-argument constructors. */
private static final Object[] NO_ARGS = new Object[0];
// Constructor.
// ------------------------------------------------------------------------
/** This class cannot be instantiated. */
private Engine() { }
// Class method.
// ------------------------------------------------------------------------
/**
* Get the implementation for <i>algorithm</i> for service
* <i>service</i> from <i>provider</i>. The service is e.g.
* "Signature", and the algorithm "DSA".
*
* @param service The service name.
* @param algorithm The name of the algorithm to get.
* @param provider The provider to get the implementation from.
* @return The engine class for the specified algorithm; the object
* returned is typically a subclass of the SPI class for that
* service, but callers should check that this is so.
* @throws NoSuchAlgorithmException If the implementation cannot be
* found or cannot be instantiated.
* @throws InvocationTargetException If the SPI class's constructor
* throws an exception.
* @throws IllegalArgumentException If any of the three arguments are null.
*/
public static Object getInstance(String service, String algorithm,
Provider provider)
throws InvocationTargetException, NoSuchAlgorithmException
{
return getInstance(service, algorithm, provider, NO_ARGS);
}
/**
* Get the implementation for <i>algorithm</i> for service
* <i>service</i> from <i>provider</i>, passing <i>initArgs</i> to the
* SPI class's constructor (which cannot be null; pass a zero-length
* array if the SPI takes no arguments). The service is e.g.
* "Signature", and the algorithm "DSA".
*
* @param service The service name.
* @param algorithm The name of the algorithm to get.
* @param provider The provider to get the implementation from.
* @param initArgs The arguments to pass to the SPI class's
* constructor (cannot be null).
* @return The engine class for the specified algorithm; the object
* returned is typically a subclass of the SPI class for that
* service, but callers should check that this is so.
* @throws NoSuchAlgorithmException If the implementation cannot be
* found or cannot be instantiated.
* @throws InvocationTargetException If the SPI class's constructor
* throws an exception.
* @throws IllegalArgumentException If any of the four arguments are null.
*/
public static Object getInstance(String service, String algorithm,
Provider provider, Object[] initArgs)
throws InvocationTargetException, NoSuchAlgorithmException
{
if (service == null || algorithm == null
|| provider == null || initArgs == null)
throw new IllegalArgumentException();
// If there is no property "service.algorithm"
if (provider.getProperty(service + "." + algorithm) == null)
{
// Iterate through aliases, until we find the class name or resolve
// too many aliases.
String alias = null;
int count = 0;
while ((alias = provider.getProperty(
ALG_ALIAS + service + "." + algorithm)) != null)
{
if (algorithm.equals(alias)) // Refers to itself!
break;
algorithm = alias;
if (count++ > MAX_ALIASES)
throw new NoSuchAlgorithmException("too many aliases");
}
if (provider.getProperty(service + "." + algorithm) == null)
throw new NoSuchAlgorithmException(algorithm);
}
// Find and instantiate the implementation.
Class clazz = null;
ClassLoader loader = provider.getClass().getClassLoader();
Constructor constructor = null;
String error = algorithm;
try
{
if (loader != null)
clazz = loader.loadClass(provider.getProperty(service+"."+algorithm));
else
clazz = Class.forName(provider.getProperty(service+"."+algorithm));
constructor = getCompatibleConstructor(clazz, initArgs);
return constructor.newInstance(initArgs);
}
catch (ClassNotFoundException cnfe)
{
error = "class not found: " + algorithm;
}
catch (IllegalAccessException iae)
{
error = "illegal access: " + iae.getMessage();
}
catch (InstantiationException ie)
{
error = "instantiation exception: " + ie.getMessage();
}
catch (ExceptionInInitializerError eiie)
{
error = "exception in initializer: " + eiie.getMessage();
}
catch (SecurityException se)
{
error = "security exception: " + se.getMessage();
}
catch (NoSuchMethodException nsme)
{
error = "no appropriate constructor found";
}
throw new NoSuchAlgorithmException(error);
}
// Own methods.
// ------------------------------------------------------------------------
/**
* Find a constructor in the given class that can take the specified
* argument list, allowing any of which to be null.
*
* @param clazz The class from which to get the constructor.
* @param initArgs The argument list to be passed to the constructor.
* @return The constructor.
* @throws NoSuchMethodException If no constructor of the given class
* can take the specified argument array.
*/
private static Constructor getCompatibleConstructor(Class clazz,
Object[] initArgs)
throws NoSuchMethodException
{
Constructor[] c = clazz.getConstructors();
outer:for (int i = 0; i < c.length; i++)
{
Class[] argTypes = c[i].getParameterTypes();
if (argTypes.length != initArgs.length)
continue;
for (int j = 0; j < argTypes.length; j++)
{
if (initArgs[j] != null &&
!argTypes[j].isAssignableFrom(initArgs[j].getClass()))
continue outer;
}
// If we reach this point, we know this constructor (c[i]) has
// the same number of parameters as the target parameter list,
// and all our parameters are either (1) null, or (2) assignable
// to the target parameter type.
return c[i];
}
throw new NoSuchMethodException();
}
}
@@ -0,0 +1,509 @@
/* OID.java -- numeric representation of an object identifier
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security;
import gnu.java.security.der.DEREncodingException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.StringTokenizer;
/**
* This immutable class represents an object identifier, or OID.
*
* <p>OIDs are represented as a series of hierarcical tokens, each of
* which is usually represented as a single, unsigned integer. The
* hierarchy works so that later tokens are considered within the group
* of earlier tokens. Thus, the OID for the Serpent block cipher,
* 1.3.6.1.4.1.11591.13.2, is maintained by the GNU project, whose OID
* is 1.3.6.1.4.1.11591 (which is, in turn, part of bigger, more general
* bodies; the topmost, 1, stands for the OIDs assigned by the
* International Standards Organization, ISO).
*
* <p>OIDs can be represented in a variety of ways, including the
* dotted-decimal form we use here.
*
* <p>OIDs may be relative, in which case the first two elements of the
* OID are omitted.
*
* @author Casey Marshall (csm@gnu.org)
*/
public class OID implements Cloneable, Comparable, java.io.Serializable
{
// Fields.
// ------------------------------------------------------------------------
/**
* The numeric ID structure.
*/
private int[] components;
/**
* The string representation of this OID, in dotted-decimal format.
*/
private transient String strRep;
/**
* The DER encoding of this OID.
*/
private transient byte[] der;
/**
* Whether or not this OID is relative.
*/
private boolean relative;
// Constructors.
// ------------------------------------------------------------------------
/**
* Create a new OID from the given byte array. The argument (which can
* neither be null nor zero-length) is copied to prevent subsequent
* modification.
*
* @param components The numeric IDs.
* @throws IllegalArgumentException If <i>components</i> is null or empty.
*/
public OID(int[] components)
{
this(components, false);
}
/**
* Create a new OID from the given byte array. The argument (which can
* neither be null nor zero-length) is copied to prevent subsequent
* modification.
*
* @param components The numeric IDs.
* @param relative The relative flag.
* @throws IllegalArgumentException If <i>components</i> is null or empty.
*/
public OID(int[] components, boolean relative)
{
if (components == null || components.length == 0)
throw new IllegalArgumentException();
this.components = (int[]) components.clone();
this.relative = relative;
}
/**
* Create a new OID from the given dotted-decimal representation.
*
* @param strRep The string representation of the OID.
* @throws IllegalArgumentException If the string does not contain at
* least one integer.
* @throws NumberFormatException If the string does not contain only
* numbers and periods ('.').
*/
public OID(String strRep)
{
this(strRep, false);
}
/**
* Create a new OID from the given dotted-decimal representation.
*
* @param strRep The string representation of the OID.
* @param relative The relative flag.
* @throws IllegalArgumentException If the string does not contain at
* least one integer.
* @throws NumberFormatException If the string does not contain only
* numbers and periods ('.').
*/
public OID(String strRep, boolean relative)
{
this.relative = relative;
this.strRep = strRep;
components = fromString(strRep);
}
/**
* Construct a new OID from the DER bytes in an input stream. This method
* does not read the tag or the length field from the input stream, so
* the caller must supply the number of octets in this OID's encoded
* form.
*
* @param derIn The DER input stream.
* @param len The number of bytes in the encoded form.
* @throws IOException If an error occurs reading the OID.
*/
public OID(InputStream derIn, int len) throws IOException
{
this(derIn, len, false);
}
/**
* Construct a new OID from the DER bytes in an input stream. This method
* does not read the tag or the length field from the input stream, so
* the caller must supply the number of octets in this OID's encoded
* form.
*
* @param derIn The DER input stream.
* @param len The number of bytes in the encoded form.
* @param relative The relative flag.
* @throws IOException If an error occurs reading the OID.
*/
public OID(InputStream derIn, int len, boolean relative) throws IOException
{
der = new byte[len];
derIn.read(der);
this.relative = relative;
try
{
components = fromDER(der, relative);
}
catch (ArrayIndexOutOfBoundsException aioobe)
{
aioobe.printStackTrace();
throw aioobe;
}
}
/**
* Construct a new OID from the given DER bytes.
*
* @param encoded The DER encoded OID.
* @throws IOException If an error occurs reading the OID.
*/
public OID(byte[] encoded) throws IOException
{
this(encoded, false);
}
/**
* Construct a new OID from the given DER bytes.
*
* @param root The root OID.
* @param encoded The encoded relative OID.
* @param relative The relative flag.
*/
public OID(byte[] encoded, boolean relative) throws IOException
{
der = (byte[]) encoded.clone();
this.relative = relative;
try
{
components = fromDER(der, relative);
}
catch (ArrayIndexOutOfBoundsException aioobe)
{
aioobe.printStackTrace();
throw aioobe;
}
}
/**
* Our private constructor.
*/
private OID()
{
}
// Instance methods.
// ------------------------------------------------------------------------
/**
* Return the numeric IDs of this OID. The value returned is copied to
* prevent modification.
*
* @return The IDs in a new integer array.
*/
public int[] getIDs()
{
return (int[]) components.clone();
}
/**
* Get the DER encoding of this OID, minus the tag and length fields.
*
* @return The DER bytes.
*/
public byte[] getDER()
{
if (der == null)
{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
int i = 0;
if (!relative)
{
int b = components[i++] * 40 + (components.length > 1
? components[i++] : 0);
encodeSubID(bout, b);
}
for ( ; i < components.length; i++)
encodeSubID(bout, components[i]);
der = bout.toByteArray();
}
return (byte[]) der.clone();
}
/**
* Get the parent OID of this OID. That is, if this OID is "1.2.3.4",
* then the parent OID will be "1.2.3". If this OID is a top-level
* OID, this method returns null.
*
* @return The parent OID, or null.
*/
public OID getParent()
{
if (components.length == 1)
return null;
int[] parent = new int[components.length - 1];
System.arraycopy(components, 0, parent, 0, parent.length);
return new OID(parent);
}
public OID getChild(int id)
{
int[] child = new int[components.length + 1];
System.arraycopy(components, 0, child, 0, components.length);
child[child.length - 1] = id;
return new OID(child);
}
/**
* Get the root OID of this OID. That is, the first two components.
*
* @return The root OID.
*/
public OID getRoot()
{
if (components.length <= 2)
return this;
int[] root = new int[2];
root[0] = components[0];
root[1] = components[1];
return new OID(root);
}
public boolean isRelative()
{
return relative;
}
/**
* Returns a copy of this OID.
*
* @return The copy.
*/
public Object clone()
{
OID oid = new OID();
oid.components = this.components;
oid.strRep = this.strRep;
return oid;
}
/* Nice idea, but possibly too expensive for whatever benefit it
* provides.
public String getShortName()
{
return OIDTable.getShortName(this);
}
public String getLongName()
{
return OIDTable.getLongName(this);
}
*/
/**
* Returns the value of this OID in dotted-decimal format.
*
* @return The string representation.
*/
public String toString()
{
if (strRep != null)
return strRep;
else
{
StringBuffer buf = new StringBuffer();
for (int i = 0; i < components.length; i++)
{
buf.append((long) components[i] & 0xFFFFFFFFL);
if (i < components.length - 1)
buf.append('.');
}
return (strRep = buf.toString());
}
}
/**
* Computes a hash code for this OID.
*
* @return The hash code.
*/
public int hashCode()
{
int ret = 0;
for (int i = 0; i < components.length; i++)
ret += components[i] << (i & 31);
return ret;
}
/**
* Tests whether or not this OID equals another.
*
* @return Whether or not this OID equals the other.
*/
public boolean equals(Object o)
{
if (!(o instanceof OID))
return false;
return java.util.Arrays.equals(components, ((OID) o).components);
}
/**
* Compares this OID to another. The comparison is essentially
* lexicographic, where the two OIDs are compared until their
* first difference, then that difference is returned. If one OID is
* shorter, but all elements equal between the two for the shorter
* length, then the shorter OID is lesser than the longer.
*
* @param o The object to compare.
* @return An integer less than, equal to, or greater than zero if
* this object is less than, equal to, or greater than the
* argument.
* @throws ClassCastException If <i>o</i> is not an OID.
*/
public int compareTo(Object o)
{
if (equals(o))
return 0;
int[] components2 = ((OID) o).components;
int len = Math.min(components.length, components2.length);
for (int i = 0; i < len; i++)
{
if (components[i] != components2[i])
return (components[i] < components2[i]) ? -1 : 1;
}
if (components.length == components2.length)
return 0;
return (components.length < components2.length) ? -1 : 1;
}
// Own methods.
// ------------------------------------------------------------------------
private static int[] fromDER(byte[] der, boolean relative)
throws DEREncodingException
{
// cannot be longer than this.
int[] components = new int[der.length + 1];
int count = 0;
int i = 0;
if (!relative && i < der.length)
{
// Non-relative OIDs have the first two arcs coded as:
//
// i = first_arc * 40 + second_arc;
//
int j = (der[i] & 0xFF);
components[count++] = j / 40;
components[count++] = j % 40;
i++;
}
while (i < der.length)
{
int j = 0;
do
{
j = der[i++] & 0xFF;
components[count] <<= 7;
components[count] |= j & 0x7F;
if (i >= der.length && (j & 0x80) != 0)
throw new DEREncodingException("malformed OID");
}
while ((j & 0x80) != 0);
count++;
}
if (count == components.length)
return components;
int[] ret = new int[count];
System.arraycopy(components, 0, ret, 0, count);
return ret;
}
private static int[] fromString(String strRep) throws NumberFormatException
{
if (strRep.startsWith("OID.") || strRep.startsWith("oid."))
strRep = strRep.substring(4);
StringTokenizer tok = new StringTokenizer(strRep, ".");
if (tok.countTokens() == 0)
throw new IllegalArgumentException();
int[] components = new int[tok.countTokens()];
int i = 0;
while (tok.hasMoreTokens())
{
components[i++] = Integer.parseInt(tok.nextToken());
}
return components;
}
private static void encodeSubID(ByteArrayOutputStream out, int id)
{
if (id < 128)
{
out.write(id);
}
else if (id < 16384)
{
out.write((id >>> 7) | 0x80);
out.write(id & 0x7F);
}
else if (id < 2097152)
{
out.write((id >>> 14) | 0x80);
out.write(((id >>> 7) | 0x80) & 0xFF);
out.write(id & 0x7F);
}
else if (id < 268435456)
{
out.write( (id >>> 21) | 0x80);
out.write(((id >>> 14) | 0x80) & 0xFF);
out.write(((id >>> 7) | 0x80) & 0xFF);
out.write(id & 0x7F);
}
}
}
@@ -0,0 +1,667 @@
/* PolicyFile.java -- policy file reader
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.Policy;
import java.security.Principal;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.Security;
import java.security.UnresolvedPermission;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
/**
* An implementation of a {@link java.security.Policy} object whose
* permissions are specified by a <em>policy file</em>.
*
* <p>The approximate syntax of policy files is:</p>
*
* <pre>
* policyFile ::= keystoreOrGrantEntries ;
*
* keystoreOrGrantEntries ::= keystoreOrGrantEntry |
* keystoreOrGrantEntries keystoreOrGrantEntry |
* EMPTY ;
*
* keystoreOrGrantEntry ::= keystoreEntry | grantEntry ;
*
* keystoreEntry ::= "keystore" keystoreUrl ';' |
* "keystore" keystoreUrl ',' keystoreAlgorithm ';' ;
*
* keystoreUrl ::= URL ;
* keystoreAlgorithm ::= STRING ;
*
* grantEntry ::= "grant" domainParameters '{' permissions '}' ';'
*
* domainParameters ::= domainParameter |
* domainParameter ',' domainParameters ;
*
* domainParameter ::= "signedBy" signerNames |
* "codeBase" codeBaseUrl |
* "principal" principalClassName principalName |
* "principal" principalName ;
*
* signerNames ::= quotedString ;
* codeBaseUrl ::= URL ;
* principalClassName ::= STRING ;
* principalName ::= quotedString ;
*
* quotedString ::= quoteChar STRING quoteChar ;
* quoteChar ::= '"' | '\'';
*
* permissions ::= permission | permissions permission ;
*
* permission ::= "permission" permissionClassName permissionTarget permissionAction |
* "permission" permissionClassName permissionTarget |
* "permission" permissionClassName;
* </pre>
*
* <p>Comments are either form of Java comments. Keystore entries only
* affect subsequent grant entries, so if a grant entry preceeds a
* keystore entry, that grant entry is not affected by that keystore
* entry. Certian instances of <code>${property-name}</code> will be
* replaced with <code>System.getProperty("property-name")</code> in
* quoted strings.</p>
*
* <p>This class will load the following files when created or
* refreshed, in order:</p>
*
* <ol>
* <li>The file <code>${java.home}/lib/security/java.policy</code>.</li>
* <li>All URLs specified by security properties
* <code>"policy.file.<i>n</i>"</code>, for increasing <i>n</i>
* starting from 1. The sequence stops at the first undefined
* property, so you must set <code>"policy.file.1"</code> if you also
* set <code>"policy.file.2"</code>, and so on.</li>
* <li>The URL specified by the property
* <code>"java.security.policy"</code>.</li>
* </ol>
*
* @author Casey Marshall (csm@gnu.org)
* @see java.security.Policy
*/
public final class PolicyFile extends Policy
{
// Constants and fields.
// -------------------------------------------------------------------------
private static final boolean DEBUG = true;
// Package-private to avoid a trampoline.
static void debug(String msg)
{
System.err.print(">> PolicyFile: ");
System.err.println(msg);
}
private static void debug(Throwable t)
{
System.err.println(">> PolicyFile");
t.printStackTrace(System.err);
}
private static final String DEFAULT_POLICY = System.getProperty("java.home")
+ System.getProperty("file.separator") + "lib"
+ System.getProperty("file.separator") + "security"
+ System.getProperty("file.separator") + "java.policy";
private final Map cs2pc;
// Constructors.
// -------------------------------------------------------------------------
public PolicyFile()
{
cs2pc = new HashMap();
refresh();
}
// Instance methods.
// -------------------------------------------------------------------------
public PermissionCollection getPermissions(CodeSource codeSource)
{
Permissions perms = new Permissions();
for (Iterator it = cs2pc.entrySet().iterator(); it.hasNext(); )
{
Map.Entry e = (Map.Entry) it.next();
CodeSource cs = (CodeSource) e.getKey();
if (cs.implies(codeSource))
{
if (DEBUG) debug(cs+" -> "+codeSource);
PermissionCollection pc = (PermissionCollection) e.getValue();
for (Enumeration ee = pc.elements(); ee.hasMoreElements(); )
{
perms.add((Permission) ee.nextElement());
}
}
else
if (DEBUG) debug(cs+" !-> "+codeSource);
}
if (DEBUG) debug ("returning permissions " + perms + " for " + codeSource);
return perms;
}
public void refresh()
{
cs2pc.clear();
List policyFiles = new LinkedList();
try
{
policyFiles.add(new File(DEFAULT_POLICY).toURL());
if (DEBUG) debug ("defualt policy is " + DEFAULT_POLICY);
policyFiles.addAll((List) AccessController.doPrivileged(
new PrivilegedExceptionAction()
{
public Object run() throws Exception
{
LinkedList l = new LinkedList();
for (int i = 1; ; i++)
{
String s = Security.getProperty("policy.file."+i);
if (DEBUG) debug("policy.file."+i+"="+s);
if (s == null)
break;
l.add(new URL(s));
}
String s = System.getProperty("java.security.policy");
if (DEBUG) debug("java.security.policy="+s);
if (s != null)
l.add(new URL(s));
return l;
}
}));
}
catch (PrivilegedActionException pae)
{
if (DEBUG) debug(pae);
}
catch (MalformedURLException mue)
{
if (DEBUG) debug(mue);
}
for (Iterator it = policyFiles.iterator(); it.hasNext(); )
{
try
{
URL url = (URL) it.next();
parse(url);
}
catch (IOException ioe)
{
if (DEBUG) debug(ioe);
}
}
}
public String toString()
{
return super.toString() + " [ " + cs2pc.toString() + " ]";
}
// Own methods.
// -------------------------------------------------------------------------
private static final int STATE_BEGIN = 0;
private static final int STATE_GRANT = 1;
private static final int STATE_PERMS = 2;
/**
* Parse a policy file, incorporating the permission definitions
* described therein.
*
* @param url The URL of the policy file to read.
* @throws IOException if an I/O error occurs, or if the policy file
* cannot be parsed.
*/
private void parse(final URL url) throws IOException
{
if (DEBUG) debug ("reading policy file from " + url);
final StreamTokenizer in = new StreamTokenizer(new InputStreamReader(url.openStream()));
in.resetSyntax();
in.slashSlashComments(true);
in.slashStarComments(true);
in.wordChars('A', 'Z');
in.wordChars('a', 'z');
in.wordChars('0', '9');
in.wordChars('.', '.');
in.wordChars('_', '_');
in.wordChars('$', '$');
in.whitespaceChars(' ', ' ');
in.whitespaceChars('\t', '\t');
in.whitespaceChars('\f', '\f');
in.whitespaceChars('\n', '\n');
in.whitespaceChars('\r', '\r');
in.quoteChar('\'');
in.quoteChar('"');
int tok;
int state = STATE_BEGIN;
List keystores = new LinkedList();
URL currentBase = null;
List currentCerts = new LinkedList();
Permissions currentPerms = new Permissions();
while ((tok = in.nextToken()) != StreamTokenizer.TT_EOF)
{
switch (tok)
{
case '{':
if (state != STATE_GRANT)
error(url, in, "spurious '{'");
state = STATE_PERMS;
tok = in.nextToken();
break;
case '}':
if (state != STATE_PERMS)
error(url, in, "spurious '}'");
state = STATE_BEGIN;
currentPerms.setReadOnly();
Certificate[] c = null;
if (!currentCerts.isEmpty())
c = (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()]);
cs2pc.put(new CodeSource(currentBase, c), currentPerms);
currentCerts.clear();
currentPerms = new Permissions();
currentBase = null;
tok = in.nextToken();
if (tok != ';')
in.pushBack();
continue;
}
if (tok != StreamTokenizer.TT_WORD)
{
error(url, in, "expecting word token");
}
// keystore "<keystore-path>" [',' "<keystore-type>"] ';'
if (in.sval.equalsIgnoreCase("keystore"))
{
String alg = KeyStore.getDefaultType();
tok = in.nextToken();
if (tok != '"' && tok != '\'')
error(url, in, "expecting key store URL");
String store = in.sval;
tok = in.nextToken();
if (tok == ',')
{
tok = in.nextToken();
if (tok != '"' && tok != '\'')
error(url, in, "expecting key store type");
alg = in.sval;
tok = in.nextToken();
}
if (tok != ';')
error(url, in, "expecting semicolon");
try
{
KeyStore keystore = KeyStore.getInstance(alg);
keystore.load(new URL(url, store).openStream(), null);
keystores.add(keystore);
}
catch (Exception x)
{
error(url, in, x.toString());
}
}
else if (in.sval.equalsIgnoreCase("grant"))
{
if (state != STATE_BEGIN)
error(url, in, "extraneous grant keyword");
state = STATE_GRANT;
}
else if (in.sval.equalsIgnoreCase("signedBy"))
{
if (state != STATE_GRANT && state != STATE_PERMS)
error(url, in, "spurious 'signedBy'");
if (keystores.isEmpty())
error(url, in, "'signedBy' with no keystores");
tok = in.nextToken();
if (tok != '"' && tok != '\'')
error(url, in, "expecting signedBy name");
StringTokenizer st = new StringTokenizer(in.sval, ",");
while (st.hasMoreTokens())
{
String alias = st.nextToken();
for (Iterator it = keystores.iterator(); it.hasNext(); )
{
KeyStore keystore = (KeyStore) it.next();
try
{
if (keystore.isCertificateEntry(alias))
currentCerts.add(keystore.getCertificate(alias));
}
catch (KeyStoreException kse)
{
error(url, in, kse.toString());
}
}
}
tok = in.nextToken();
if (tok != ',')
{
if (state != STATE_GRANT)
error(url, in, "spurious ','");
in.pushBack();
}
}
else if (in.sval.equalsIgnoreCase("codeBase"))
{
if (state != STATE_GRANT)
error(url, in, "spurious 'codeBase'");
tok = in.nextToken();
if (tok != '"' && tok != '\'')
error(url, in, "expecting code base URL");
String base = expand(in.sval);
if (File.separatorChar != '/')
base = base.replace(File.separatorChar, '/');
try
{
currentBase = new URL(base);
}
catch (MalformedURLException mue)
{
error(url, in, mue.toString());
}
tok = in.nextToken();
if (tok != ',')
in.pushBack();
}
else if (in.sval.equalsIgnoreCase("principal"))
{
if (state != STATE_GRANT)
error(url, in, "spurious 'principal'");
tok = in.nextToken();
if (tok == StreamTokenizer.TT_WORD)
{
tok = in.nextToken();
if (tok != '"' && tok != '\'')
error(url, in, "expecting principal name");
String name = in.sval;
Principal p = null;
try
{
Class pclass = Class.forName(in.sval);
Constructor c =
pclass.getConstructor(new Class[] { String.class });
p = (Principal) c.newInstance(new Object[] { name });
}
catch (Exception x)
{
error(url, in, x.toString());
}
for (Iterator it = keystores.iterator(); it.hasNext(); )
{
KeyStore ks = (KeyStore) it.next();
try
{
for (Enumeration e = ks.aliases(); e.hasMoreElements(); )
{
String alias = (String) e.nextElement();
if (ks.isCertificateEntry(alias))
{
Certificate cert = ks.getCertificate(alias);
if (!(cert instanceof X509Certificate))
continue;
if (p.equals(((X509Certificate) cert).getSubjectDN()) ||
p.equals(((X509Certificate) cert).getSubjectX500Principal()))
currentCerts.add(cert);
}
}
}
catch (KeyStoreException kse)
{
error(url, in, kse.toString());
}
}
}
else if (tok == '"' || tok == '\'')
{
String alias = in.sval;
for (Iterator it = keystores.iterator(); it.hasNext(); )
{
KeyStore ks = (KeyStore) it.next();
try
{
if (ks.isCertificateEntry(alias))
currentCerts.add(ks.getCertificate(alias));
}
catch (KeyStoreException kse)
{
error(url, in, kse.toString());
}
}
}
else
error(url, in, "expecting principal");
tok = in.nextToken();
if (tok != ',')
in.pushBack();
}
else if (in.sval.equalsIgnoreCase("permission"))
{
if (state != STATE_PERMS)
error(url, in, "spurious 'permission'");
tok = in.nextToken();
if (tok != StreamTokenizer.TT_WORD)
error(url, in, "expecting permission class name");
String className = in.sval;
Class clazz = null;
try
{
clazz = Class.forName(className);
}
catch (ClassNotFoundException cnfe)
{
}
tok = in.nextToken();
if (tok == ';')
{
if (clazz == null)
{
currentPerms.add(new UnresolvedPermission(className,
null, null, (Certificate[]) currentCerts.toArray(new Certificate[0])));
continue;
}
try
{
currentPerms.add((Permission) clazz.newInstance());
}
catch (Exception x)
{
error(url, in, x.toString());
}
continue;
}
if (tok != '"' && tok != '\'')
error(url, in, "expecting permission target");
String target = expand(in.sval);
tok = in.nextToken();
if (tok == ';')
{
if (clazz == null)
{
currentPerms.add(new UnresolvedPermission(className,
target, null, (Certificate[]) currentCerts.toArray(new Certificate[0])));
continue;
}
try
{
Constructor c =
clazz.getConstructor(new Class[] { String.class });
currentPerms.add((Permission) c.newInstance(
new Object[] { target }));
}
catch (Exception x)
{
error(url, in, x.toString());
}
continue;
}
if (tok != ',')
error(url, in, "expecting ','");
tok = in.nextToken();
if (tok == StreamTokenizer.TT_WORD)
{
if (!in.sval.equalsIgnoreCase("signedBy"))
error(url, in, "expecting 'signedBy'");
try
{
Constructor c =
clazz.getConstructor(new Class[] { String.class });
currentPerms.add((Permission) c.newInstance(
new Object[] { target }));
}
catch (Exception x)
{
error(url, in, x.toString());
}
in.pushBack();
continue;
}
if (tok != '"' && tok != '\'')
error(url, in, "expecting permission action");
String action = in.sval;
if (clazz == null)
{
currentPerms.add(new UnresolvedPermission(className,
target, action, (Certificate[]) currentCerts.toArray(new Certificate[0])));
continue;
}
else
{
try
{
Constructor c = clazz.getConstructor(
new Class[] { String.class, String.class });
currentPerms.add((Permission) c.newInstance(
new Object[] { target, action }));
}
catch (Exception x)
{
error(url, in, x.toString());
}
}
tok = in.nextToken();
if (tok != ';' && tok != ',')
error(url, in, "expecting ';' or ','");
}
}
}
/**
* Expand all instances of <code>"${property-name}"</code> into
* <code>System.getProperty("property-name")</code>.
*/
private static String expand(final String s)
{
final StringBuffer result = new StringBuffer();
final StringBuffer prop = new StringBuffer();
int state = 0;
for (int i = 0; i < s.length(); i++)
{
switch (state)
{
case 0:
if (s.charAt(i) == '$')
state = 1;
else
result.append(s.charAt(i));
break;
case 1:
if (s.charAt(i) == '{')
state = 2;
else
{
state = 0;
result.append('$').append(s.charAt(i));
}
break;
case 2:
if (s.charAt(i) == '}')
{
String p = prop.toString();
if (p.equals("/"))
p = "file.separator";
p = System.getProperty(p);
if (p == null)
p = "";
result.append(p);
prop.setLength(0);
state = 0;
}
else
prop.append(s.charAt(i));
break;
}
}
if (state != 0)
result.append('$').append('{').append(prop);
return result.toString();
}
/**
* I miss macros.
*/
private static void error(URL base, StreamTokenizer in, String msg)
throws IOException
{
throw new IOException(base+":"+in.lineno()+": "+msg);
}
}
@@ -0,0 +1,89 @@
/* GetPropertyAction.java
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.action;
import java.security.PrivilegedAction;
/**
* PrivilegedAction implementation that calls System.getProperty() with
* the property name passed to its constructor.
*
* Example of use:
* <code>
* GetPropertyAction action = new GetPropertyAction("http.proxyPort");
* String port = AccessController.doPrivileged(action);
* </code>
*/
public class GetPropertyAction implements PrivilegedAction
{
String name;
String value = null;
public GetPropertyAction()
{
}
public GetPropertyAction(String propName)
{
setParameters(propName);
}
public GetPropertyAction(String propName, String defaultValue)
{
setParameters(propName, defaultValue);
}
public Object run()
{
return System.getProperty(name, value);
}
public GetPropertyAction setParameters(String propName)
{
this.name = propName;
this.value = null;
return this;
}
public GetPropertyAction setParameters(String propName, String defaultValue)
{
this.name = propName;
this.value = defaultValue;
return this;
}
}
@@ -0,0 +1,93 @@
/* GetSecurityPropertyAction.java
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.action;
import java.security.PrivilegedAction;
import java.security.Security;
/**
* PrivilegedAction implementation that calls Security.getProperty()
* with the property name passed to its constructor.
*
* Example of use:
* <code>
* GetSecurityPropertyAction action = new GetSecurityPropertyAction("javax.net.ssl.trustStorePassword");
* String passwd = AccessController.doPrivileged(action);
* </code>
*/
public class GetSecurityPropertyAction implements PrivilegedAction
{
private String name;
private String value;
public GetSecurityPropertyAction()
{
}
public GetSecurityPropertyAction(String propName)
{
setParameters(propName);
}
public GetSecurityPropertyAction(String propName, String defaultValue)
{
setParameters(propName, defaultValue);
}
public GetSecurityPropertyAction setParameters(String propName)
{
this.name = propName;
this.value = null;
return this;
}
public GetSecurityPropertyAction setParameters(String propName, String defaultValue)
{
this.name = propName;
this.value = defaultValue;
return this;
}
public Object run()
{
String val = Security.getProperty(name);
if (val == null)
val = value;
return val;
}
}
@@ -0,0 +1,77 @@
/* SetAccessibleAction.java
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.action;
import java.lang.reflect.AccessibleObject;
import java.security.PrivilegedAction;
/**
* PrivilegedAction implementation that calls setAccessible(true) on the
* AccessibleObject passed to its constructor.
*
* Example of use:
* <code>
* Field dataField = cl.getDeclaredField("data");
* AccessController.doPrivileged(new SetAccessibleAction(dataField));
* </code>
*/
public class SetAccessibleAction implements PrivilegedAction
{
AccessibleObject member;
public SetAccessibleAction()
{
}
public SetAccessibleAction(AccessibleObject member)
{
this.member = member;
}
public Object run()
{
member.setAccessible(true);
return null;
}
public SetAccessibleAction setMember(AccessibleObject member)
{
this.member = member;
return this;
}
}
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in gnu.java.security.action package.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - gnu.java.security.action</title></head>
<body>
<p></p>
</body>
</html>
@@ -0,0 +1,46 @@
/* BER.java -- basic encoding rules (BER) constants.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.ber;
import gnu.java.security.der.DER;
public interface BER extends DER
{
BERValue END_OF_SEQUENCE = new BERValue(0, null);
}
@@ -0,0 +1,54 @@
/* BEREncodingException.java --- BER Encoding Exception
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.ber;
import gnu.java.security.der.DEREncodingException;
public class BEREncodingException extends DEREncodingException
{
public BEREncodingException()
{
super ();
}
public BEREncodingException (String msg)
{
super (msg);
}
}
@@ -0,0 +1,103 @@
/* BERReader.java -- basic encoding rules (BER) reader.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.ber;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
public class BERReader extends DERReader implements BER
{
/**
* Create a new DER reader from a byte array.
*
* @param in The encoded bytes.
*/
public BERReader(byte[] in)
{
super(in);
}
public BERReader (byte[] in, int off, int len)
{
super(in, off, len);
}
/**
* Create a new DER readed from an input stream.
*
* @param in The encoded bytes.
*/
public BERReader(InputStream in)
{
super(in);
}
public DERValue read() throws IOException
{
in.mark(2);
int tag = in.read();
if (tag == -1)
throw new EOFException();
int length = in.read();
if (length == 0)
{
if (tag == 0)
return END_OF_SEQUENCE;
return new BERValue(tag, CONSTRUCTED_VALUE, new byte[] { (byte) tag, 0 });
}
else
{
in.reset();
return super.read();
}
}
public int peek() throws IOException
{
in.mark(1);
int ret = in.read();
in.reset();
return ret;
}
}
@@ -0,0 +1,82 @@
/* BERReader.java -- basic encoding rules (BER) value.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.ber;
import gnu.java.security.der.DERValue;
public class BERValue extends DERValue
{
private boolean indefinite;
public BERValue(int tag, Object value, byte[] encoded)
{
super(tag, 0, value, encoded);
indefinite = true;
}
public BERValue(int tag, int length, Object value, byte[] encoded)
{
super(tag, length, value, encoded);
}
public BERValue(int tag, Object value)
{
super(tag, 0, value, null);
}
public static boolean isIndefinite(DERValue value)
{
if (value instanceof BERValue)
return ((BERValue) value).getIndefinite();
return false;
}
public boolean getIndefinite()
{
return indefinite;
}
public int getLength()
{
if (indefinite)
return 0;
return super.getLength();
}
}
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in gnu.java.security.ber package.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - gnu.java.security.ber</title></head>
<body>
<p></p>
</body>
</html>
@@ -0,0 +1,317 @@
/* BitString.java -- Java representation of the BIT STRING type.
Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.der;
import java.math.BigInteger;
import java.util.Arrays;
/**
* Immutable representation of a bit string, which is equivalent to a
* byte array except some number of the rightmost bits are ignored. For
* example, this could be the bit string:
*
* <pre> 00010101 11101101 11010xxx</pre>
*
* <p>Where the "xxx" represents three bits that should be ignored, and
* can have any value.
*
* @author Casey Marshall (csm@gnu.org)
*/
public class BitString implements Cloneable, Comparable
{
// Fields.
// ------------------------------------------------------------------------
/** The bits themselves. */
private final byte[] bytes;
/**
* The exportable byte array. This array has the ignored bits
* removed.
*/
private transient byte[] externBytes;
/** The number of bits ignored at the end of the byte array. */
private final int ignoredBits;
/** This bit string as a boolean array. */
private transient boolean[] boolVal;
// Constructors.
// ------------------------------------------------------------------------
/**
* Create a new bit string, shifting the given byte array if needed.
*
* @param bytes The byte array holding the bit string.
* @param ignoredBits The number of bits to ignore.
* @param doShift Pass true in this parameter if the byte array has
* not yet been shifted left by <i>ignoredBits</i>.
* @throws IllegalArgumentException If <i>ignoredBits</i> is negative
* or greater than 7.
* @throws NullPointerException If <i>bytes</i> is null.
*/
public BitString(byte[] bytes, int ignoredBits, boolean doShift)
{
this(bytes, 0, bytes.length, ignoredBits, doShift);
}
/**
* Create a new bit string, shifting the given byte array if needed.
*
* @param bytes The byte array holding the bit string.
* @param offset The offset where the meaningful bytes begin.
* @param length The number of meaningful bytes.
* @param ignoredBits The number of bits to ignore.
* @param doShift Pass true in this parameter if the byte array has
* not yet been shifted left by <i>ignoredBits</i>.
* @throws IllegalArgumentException If <i>ignoredBits</i> is negative
* or greater than 7.
* @throws NullPointerException If <i>bytes</i> is null.
*/
public BitString(byte[] bytes, int offset, int length,
int ignoredBits, boolean doShift)
{
if (ignoredBits < 0 || ignoredBits > 7)
throw new IllegalArgumentException();
if (bytes == null)
throw new NullPointerException();
if (doShift && ignoredBits > 0)
{
this.externBytes = new byte[length];
System.arraycopy(bytes, offset, externBytes, 0, length);
this.bytes = new BigInteger(externBytes).shiftLeft(ignoredBits)
.toByteArray();
}
else
{
this.bytes = new byte[length];
System.arraycopy(bytes, offset, this.bytes, 0, length);
}
this.ignoredBits = ignoredBits;
}
/**
* Create a new bit string.
*
* @param bytes The byte array holding the bit string.
* @param offset The offset where the meaningful bytes begin.
* @param length The number of meaningful bytes.
* @param ignoredBits The number of bits to ignore.
* @throws IllegalArgumentException If <i>ignoredBits</i> is negative
* or greater than 7.
* @throws NullPointerException If <i>bytes</i> is null.
*/
public BitString(byte[] bytes, int offset, int length, int ignoredBits)
{
this(bytes, offset, length, ignoredBits, false);
}
/**
* Create a new bit string.
*
* @param bytes The byte array holding the bit string.
* @param ignoredBits The number of bits to ignore.
* @throws IllegalArgumentException If <i>ignoredBits</i> is negative
* or greater than 7.
* @throws NullPointerException If <i>bytes</i> is null.
*/
public BitString(byte[] bytes, int ignoredBits)
{
this(bytes, 0, bytes.length, ignoredBits, false);
}
/**
* Create a new bit string.
*
* @param bytes The byte array holding the bit string.
* @param offset The offset where the meaningful bytes begin.
* @param length The number of meaningful bytes.
* @throws NullPointerException If <i>bytes</i> is null.
*/
public BitString(byte[] bytes, int offset, int length)
{
this(bytes, offset, length, 0, false);
}
/**
* Create a new bit string.
*
* @param bytes The byte array holding the bit string.
* @throws NullPointerException If <i>bytes</i> is null.
*/
public BitString(byte[] bytes)
{
this(bytes, 0, bytes.length, 0, false);
}
// Instance methods.
// ------------------------------------------------------------------------
/**
* Return this bit string as a byte array, with the ignored bits
* trimmed off. The byte array is cloned every time this method is
* called to prevent modification.
*
* @return The trimmed byte array.
*/
public byte[] toByteArray()
{
if (ignoredBits == 0)
return (byte[]) bytes.clone();
if (externBytes == null)
externBytes = new BigInteger(bytes).shiftRight(ignoredBits).toByteArray();
return (byte[]) externBytes.clone();
}
/**
* Returns this bit string as a byte array, with the ignored bits
* present. The byte array is cloned every time this method is
* called to prevent modification.
*
* @return The byte array.
*/
public byte[] getShiftedByteArray()
{
return (byte[]) bytes.clone();
}
/**
* Returns the number of ignored bits.
*
* @return The number of ignored bits.
*/
public int getIgnoredBits()
{
return ignoredBits;
}
/**
* Returns the size, in bits, of this bit string.
*
* @return The size of this bit string.
*/
public int size()
{
return (bytes.length << 3) - ignoredBits;
}
/**
* Return this bit string as a boolean array. The value returned is of
* size {@link #size()}, and each <code>true</code> value
* corresponding to each "1" in this bit string. The boolean array is
* cloned before it is returned.
*
* @return The boolean array.
*/
public boolean[] toBooleanArray()
{
if (boolVal == null)
{
boolVal = new boolean[size()];
for (int i = 0, j = 7, k = 0; i < boolVal.length; i++)
{
boolVal[i] = (bytes[k] & 1 << j--) != 0;
if (j < 0)
{
j = 7;
k++;
}
}
}
return (boolean[]) boolVal.clone();
}
public Object clone()
{
try
{
return super.clone();
}
catch (CloneNotSupportedException cce)
{
throw new InternalError(cce.getMessage());
}
}
public int compareTo(Object o)
{
BitString that = (BitString) o;
if (this.equals(that))
return 0;
if (this.bytes.length != that.bytes.length)
return (this.bytes.length < that.bytes.length) ? -1 : 1;
if (this.ignoredBits != that.ignoredBits)
return (this.ignoredBits < that.ignoredBits) ? -1 : 1;
for (int i = 0; i < this.bytes.length; i++)
if (this.bytes[i] != that.bytes[i])
return (this.bytes[i] < that.bytes[i]) ? -1 : 1;
return 0; // not reached.
}
public boolean equals(Object o)
{
if (!(o instanceof BitString))
return false;
BitString that = (BitString) o;
// True for cloned instances.
if (this.bytes == that.bytes && this.ignoredBits == that.ignoredBits)
return true;
if (this.ignoredBits == that.ignoredBits)
return Arrays.equals(this.bytes, that.bytes);
return false;
}
public String toString()
{
StringBuffer sb = new StringBuffer();
for (int i = 0, j = 7, k = 0; i < size(); i++)
{
sb.append((bytes[k] & 1 << j) != 0 ? "1" : "0");
j--;
if (j < 0)
{
j = 7;
k++;
}
}
return sb.toString();
}
}
@@ -0,0 +1,86 @@
/* DER.java -- Basic constants in DER sequences.
Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.der;
/**
* The set of tags for DER types.
*
* @author Casey Marshall (csm@gnu.org)
*/
public interface DER
{
int UNIVERSAL = 0x00;
int APPLICATION = 0x40;
int CONTEXT = 0x80;
int PRIVATE = 0xC0;
int CONSTRUCTED = 0x20;
int ANY = 0x00;
int BOOLEAN = 0x01;
int INTEGER = 0x02;
int BIT_STRING = 0x03;
int OCTET_STRING = 0x04;
int NULL = 0x05;
int OBJECT_IDENTIFIER = 0x06;
int REAL = 0x09;
int ENUMERATED = 0x0a;
int RELATIVE_OID = 0x0d;
int SEQUENCE = 0x10;
int SET = 0x11;
Object CONSTRUCTED_VALUE = new Object();
int NUMERIC_STRING = 0x12;
int PRINTABLE_STRING = 0x13;
int T61_STRING = 0x14;
int VIDEOTEX_STRING = 0x15;
int IA5_STRING = 0x16;
int GRAPHIC_STRING = 0x19;
int ISO646_STRING = 0x1A;
int GENERAL_STRING = 0x1B;
int UTF8_STRING = 0x0C;
int UNIVERSAL_STRING = 0x1C;
int BMP_STRING = 0x1E;
int UTC_TIME = 0x17;
int GENERALIZED_TIME = 0x18;
}
@@ -0,0 +1,54 @@
/* DEREncodingException.java --- DER Encoding Exception
Copyright (C) 1999,2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.der;
import java.io.IOException;
public class DEREncodingException extends IOException
{
public DEREncodingException()
{
super ();
}
public DEREncodingException (String msg)
{
super (msg);
}
}
@@ -0,0 +1,437 @@
/* DERReader.java -- parses ASN.1 DER sequences
Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.der;
import gnu.java.security.OID;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
/**
* This class decodes DER sequences into Java objects. The methods of
* this class do not have knowledge of higher-levels of structure in the
* DER stream -- such as ASN.1 constructions -- and it is therefore up
* to the calling application to determine if the data are structured
* properly by inspecting the {@link DERValue} that is returned.
*
* @author Casey Marshall (csm@gnu.org)
*/
public class DERReader implements DER
{
// Fields.
// ------------------------------------------------------------------------
protected InputStream in;
protected final ByteArrayOutputStream encBuf;
// Constructor.
// ------------------------------------------------------------------------
/**
* Create a new DER reader from a byte array.
*
* @param in The encoded bytes.
*/
public DERReader(byte[] in)
{
this(new ByteArrayInputStream(in));
}
public DERReader (byte[] in, int off, int len)
{
this (new ByteArrayInputStream (in, off, len));
}
/**
* Create a new DER readed from an input stream.
*
* @param in The encoded bytes.
*/
public DERReader(InputStream in)
{
if (!in.markSupported())
this.in = new BufferedInputStream(in, 16384);
else
this.in = in;
encBuf = new ByteArrayOutputStream(2048);
}
// Class methods.
// ------------------------------------------------------------------------
/**
* Convenience method for reading a single primitive value from the
* given byte array.
*
* @param encoded The encoded bytes.
* @throws IOException If the bytes do not represent an encoded
* object.
*/
public static DERValue read(byte[] encoded) throws IOException
{
return new DERReader(encoded).read();
}
// Instance methods.
// ------------------------------------------------------------------------
public void skip (int bytes) throws IOException
{
in.skip (bytes);
}
/**
* Decode a single value from the input stream, returning it in a new
* {@link DERValue}. By "single value" we mean any single type in its
* entirety -- including constructed types such as SEQUENCE and all
* the values they contain. Usually it is sufficient to call this
* method once to parse and return the top-level structure, then to
* inspect the returned value for the proper contents.
*
* @return The parsed DER structure.
* @throws IOException If an error occurs reading from the input
* stream.
* @throws DEREncodingException If the input does not represent a
* valid DER stream.
*/
public DERValue read() throws IOException
{
int tag = in.read();
if (tag == -1)
throw new EOFException();
encBuf.write(tag);
int len = readLength();
DERValue value = null;
if ((tag & CONSTRUCTED) == CONSTRUCTED)
{
in.mark(2048);
byte[] encoded = new byte[len];
in.read(encoded);
encBuf.write(encoded);
value = new DERValue(tag, len, CONSTRUCTED_VALUE, encBuf.toByteArray());
in.reset();
encBuf.reset();
return value;
}
switch (tag & 0xC0)
{
case UNIVERSAL:
value = new DERValue(tag, len, readUniversal(tag, len),
encBuf.toByteArray());
encBuf.reset();
break;
case CONTEXT:
byte[] encoded = new byte[len];
in.read(encoded);
encBuf.write(encoded);
value = new DERValue(tag, len, encoded, encBuf.toByteArray());
encBuf.reset();
break;
case APPLICATION:
// This should not be reached, since (I think) APPLICATION is
// always constructed.
throw new DEREncodingException("non-constructed APPLICATION data");
default:
throw new DEREncodingException("PRIVATE class not supported");
}
return value;
}
protected int readLength() throws IOException
{
int i = in.read();
if (i == -1)
throw new EOFException();
encBuf.write(i);
if ((i & ~0x7F) == 0)
{
return i;
}
else if (i < 0xFF)
{
byte[] octets = new byte[i & 0x7F];
in.read(octets);
encBuf.write(octets);
return new BigInteger(1, octets).intValue();
}
throw new DEREncodingException();
}
// Own methods.
// ------------------------------------------------------------------------
private Object readUniversal(int tag, int len) throws IOException
{
byte[] value = new byte[len];
in.read(value);
encBuf.write(value);
switch (tag & 0x1F)
{
case BOOLEAN:
if (value.length != 1)
throw new DEREncodingException();
return Boolean.valueOf(value[0] != 0);
case NULL:
if (len != 0)
throw new DEREncodingException();
return null;
case INTEGER:
case ENUMERATED:
return new BigInteger(value);
case BIT_STRING:
byte[] bits = new byte[len - 1];
System.arraycopy(value, 1, bits, 0, bits.length);
return new BitString(bits, value[0] & 0xFF);
case OCTET_STRING:
return value;
case NUMERIC_STRING:
case PRINTABLE_STRING:
case T61_STRING:
case VIDEOTEX_STRING:
case IA5_STRING:
case GRAPHIC_STRING:
case ISO646_STRING:
case GENERAL_STRING:
case UNIVERSAL_STRING:
case BMP_STRING:
case UTF8_STRING:
return makeString(tag, value);
case UTC_TIME:
case GENERALIZED_TIME:
return makeTime(tag, value);
case OBJECT_IDENTIFIER:
return new OID(value);
case RELATIVE_OID:
return new OID(value, true);
default:
throw new DEREncodingException("unknown tag " + tag);
}
}
private static String makeString(int tag, byte[] value)
throws IOException
{
switch (tag & 0x1F)
{
case NUMERIC_STRING:
case PRINTABLE_STRING:
case T61_STRING:
case VIDEOTEX_STRING:
case IA5_STRING:
case GRAPHIC_STRING:
case ISO646_STRING:
case GENERAL_STRING:
return fromIso88591(value);
case UNIVERSAL_STRING:
// XXX The docs say UniversalString is encoded in four bytes
// per character, but Java has no support (yet) for UTF-32.
//return new String(buf, "UTF-32");
case BMP_STRING:
return fromUtf16Be(value);
case UTF8_STRING:
return fromUtf8(value);
default:
throw new DEREncodingException("unknown string tag");
}
}
private static String fromIso88591(byte[] bytes)
{
StringBuffer str = new StringBuffer(bytes.length);
for (int i = 0; i < bytes.length; i++)
str.append((char) (bytes[i] & 0xFF));
return str.toString();
}
private static String fromUtf16Be(byte[] bytes) throws IOException
{
if ((bytes.length & 0x01) != 0)
throw new IOException("UTF-16 bytes are odd in length");
StringBuffer str = new StringBuffer(bytes.length / 2);
for (int i = 0; i < bytes.length; i += 2)
{
char c = (char) ((bytes[i] << 8) & 0xFF);
c |= (char) (bytes[i+1] & 0xFF);
str.append(c);
}
return str.toString();
}
private static String fromUtf8(byte[] bytes) throws IOException
{
StringBuffer str = new StringBuffer((int)(bytes.length / 1.5));
for (int i = 0; i < bytes.length; )
{
char c = 0;
if ((bytes[i] & 0xE0) == 0xE0)
{
if ((i + 2) >= bytes.length)
throw new IOException("short UTF-8 input");
c = (char) ((bytes[i++] & 0x0F) << 12);
if ((bytes[i] & 0x80) != 0x80)
throw new IOException("malformed UTF-8 input");
c |= (char) ((bytes[i++] & 0x3F) << 6);
if ((bytes[i] & 0x80) != 0x80)
throw new IOException("malformed UTF-8 input");
c |= (char) (bytes[i++] & 0x3F);
}
else if ((bytes[i] & 0xC0) == 0xC0)
{
if ((i + 1) >= bytes.length)
throw new IOException("short input");
c = (char) ((bytes[i++] & 0x1F) << 6);
if ((bytes[i] & 0x80) != 0x80)
throw new IOException("malformed UTF-8 input");
c |= (char) (bytes[i++] & 0x3F);
}
else if ((bytes[i] & 0xFF) < 0x80)
{
c = (char) (bytes[i++] & 0xFF);
}
else
throw new IOException("badly formed UTF-8 sequence");
str.append(c);
}
return str.toString();
}
private Date makeTime(int tag, byte[] value) throws IOException
{
Calendar calendar = Calendar.getInstance();
String str = makeString(PRINTABLE_STRING, value);
// Classpath's SimpleDateFormat does not work for parsing these
// types of times, so we do this by hand.
String date = str;
String tz = "";
if (str.indexOf("+") > 0)
{
date = str.substring(0, str.indexOf("+"));
tz = str.substring(str.indexOf("+"));
}
else if (str.indexOf("-") > 0)
{
date = str.substring(0, str.indexOf("-"));
tz = str.substring(str.indexOf("-"));
}
else if (str.endsWith("Z"))
{
date = str.substring(0, str.length()-2);
tz = "Z";
}
if (!tz.equals("Z") && tz.length() > 0)
calendar.setTimeZone(TimeZone.getTimeZone(tz));
else
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
if ((tag & 0x1F) == UTC_TIME)
{
if (date.length() < 10) // must be at least 10 chars long
throw new DEREncodingException("cannot parse date");
// UTCTime is of the form "yyMMddHHmm[ss](Z|(+|-)hhmm)"
try
{
int year = Integer.parseInt(str.substring(0, 2));
if (year < 50)
year += 2000;
else
year += 1900;
calendar.set(year,
Integer.parseInt(str.substring( 2, 4))-1, // month
Integer.parseInt(str.substring( 4, 6)), // day
Integer.parseInt(str.substring( 6, 8)), // hour
Integer.parseInt(str.substring( 8, 10))); // minute
if (date.length() == 12);
calendar.set(Calendar.SECOND,
Integer.parseInt(str.substring(10, 12)));
}
catch (NumberFormatException nfe)
{
throw new DEREncodingException("cannot parse date");
}
}
else
{
if (date.length() < 10) // must be at least 10 chars long
throw new DEREncodingException("cannot parse date");
// GeneralTime is of the form "yyyyMMddHH[mm[ss[(.|,)SSSS]]]"
// followed by "Z" or "(+|-)hh[mm]"
try
{
calendar.set(
Integer.parseInt(date.substring(0, 4)), // year
Integer.parseInt(date.substring(4, 6))-1, // month
Integer.parseInt(date.substring(6, 8)), // day
Integer.parseInt(date.substring(8, 10)), 0); // hour, min
switch (date.length())
{
case 19:
case 18:
case 17:
case 16:
calendar.set(Calendar.MILLISECOND,
Integer.parseInt(date.substring(15)));
case 14:
calendar.set(Calendar.SECOND,
Integer.parseInt(date.substring(12, 14)));
case 12:
calendar.set(Calendar.MINUTE,
Integer.parseInt(date.substring(10, 12)));
}
}
catch (NumberFormatException nfe)
{
throw new DEREncodingException("cannot parse date");
}
}
return calendar.getTime();
}
}
@@ -0,0 +1,170 @@
/* DERValue.java -- a value read or written to a DER encoding.
Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.der;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class DERValue implements DER
{
// Fields.
// ------------------------------------------------------------------------
private final int tagClass;
private final boolean constructed;
private final int tag;
private int length;
private final Object value;
private byte[] encoded;
// Constructor.
// ------------------------------------------------------------------------
public DERValue(int tag, int length, Object value, byte[] encoded)
{
tagClass = tag & 0xC0;
this.tag = tag & 0x1F;
constructed = (tag & CONSTRUCTED) == CONSTRUCTED;
this.length = length;
this.value = value;
if (encoded != null)
this.encoded = (byte[]) encoded.clone();
}
public DERValue(int tag, Object value)
{
this(tag, 0, value, null);
}
// Instance methods.
// ------------------------------------------------------------------------
public int getExternalTag()
{
return tagClass | tag | (constructed ? 0x20 : 0x00);
}
public int getTag()
{
return tag;
}
public int getTagClass()
{
return tagClass;
}
public boolean isConstructed()
{
return constructed;
}
public int getLength()
{
if (encoded == null)
{
try
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
length = DERWriter.write(out, this);
encoded = out.toByteArray();
}
catch (IOException ioe)
{
encoded = new byte[0];
}
}
return length;
}
public Object getValue()
{
return value;
}
public Object getValueAs (final int derType) throws IOException
{
byte[] encoded = getEncoded ();
encoded[0] = (byte) derType;
return DERReader.read (encoded).getValue ();
}
public byte[] getEncoded()
{
if (encoded == null)
{
try
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
length = DERWriter.write(out, this);
encoded = out.toByteArray();
}
catch (IOException ioe)
{
encoded = new byte[0];
}
}
return (byte[]) encoded.clone();
}
public int getEncodedLength()
{
if (encoded == null)
{
try
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
length = DERWriter.write(out, this);
encoded = out.toByteArray();
}
catch (IOException ioe)
{
encoded = new byte[0];
}
}
return encoded.length;
}
public String toString()
{
return "DERValue [ tag=" + tag + ", class=" + tagClass + ", constructed="
+ constructed + ", value=" + value + " ]";
}
}
@@ -0,0 +1,349 @@
/* DERWriter.java -- write Java types in DER format.
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.der;
import gnu.java.security.OID;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
/**
* Methods that allow various Java types to be written as a DER
* (Distinguished Encoding Rules) stream to the specified output stream.
* DER is used to encode ASN.1 constructions, but this class provides no
* methods for interacting with ASN.1. Rather, callers should construct
* their output objects properly for whatever ASN.1 construct is being
* output.
*
* <p>This class only defines static methods; there are no instance
* variables needed.
*
* @author Casey Marshall (csm@gnu.org)
*/
public class DERWriter implements DER
{
// Constructors.
// ------------------------------------------------------------------------
/** This class only has static methods. */
private DERWriter()
{
}
// Class methods.
// ------------------------------------------------------------------------
public static int write(OutputStream out, DERValue object)
throws IOException
{
out.write(object.getExternalTag());
Object value = object.getValue();
if (value == null)
{
writeLength(out, 0);
return 0;
}
if (value instanceof Boolean)
return writeBoolean(out, (Boolean) value);
else if (value instanceof BigInteger)
return writeInteger(out, (BigInteger) value);
else if (value instanceof Date)
return writeDate(out, object.getExternalTag(), (Date) value);
else if (value instanceof String)
return writeString(out, object.getExternalTag(), (String) value);
else if (value instanceof List)
return writeSequence(out, (List) value);
else if (value instanceof Set)
return writeSet(out, (Set) value);
else if (value instanceof BitString)
return writeBitString(out, (BitString) value);
else if (value instanceof OID)
return writeOID(out, (OID) value);
else if (value instanceof byte[])
{
writeLength(out, ((byte[]) value).length);
out.write((byte[]) value);
return ((byte[]) value).length;
}
else if (value instanceof DERValue)
{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
write(bout, (DERValue) value);
byte[] buf = bout.toByteArray();
writeLength(out, buf.length);
out.write(buf);
return buf.length;
}
else
throw new DEREncodingException("cannot encode " + value.getClass().getName());
}
public static int definiteEncodingSize(int length)
{
if (length < 128)
return 1;
else if (length < 256)
return 2;
else if (length < 65536)
return 3;
else if (length < 16777216)
return 4;
else
return 5;
}
// Own methods.
// ------------------------------------------------------------------------
/**
* Write a BOOLEAN type to the given output stream.
*
* @param out The sink output stream.
* @param b The boolean value to write.
*/
private static int writeBoolean(OutputStream out, Boolean b)
throws IOException
{
writeLength(out, 1);
if (b.booleanValue())
out.write(0xFF);
else
out.write(0);
return 1;
}
/**
* Write an INTEGER type to the given output stream.
*
* @param out The sink output stream.
* @param integer The integer to write.
*/
private static int writeInteger(OutputStream out, BigInteger integer)
throws IOException
{
byte[] bytes = integer.toByteArray();
writeLength(out, bytes.length);
out.write(bytes);
return bytes.length;
}
private static int writeSequence(OutputStream out, List sequence)
throws IOException
{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
for (Iterator i = sequence.iterator(); i.hasNext(); )
{
write(bout, (DERValue) i.next());
}
byte[] buf = bout.toByteArray();
writeLength(out, buf.length);
out.write(buf);
return buf.length;
}
private static int writeSet(OutputStream out, Set set)
throws IOException
{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
for (Iterator i = set.iterator(); i.hasNext(); )
{
write(bout, (DERValue) i.next());
}
byte[] buf = bout.toByteArray();
writeLength(out, buf.length);
out.write(buf);
return buf.length;
}
private static int writeOID(OutputStream out, OID oid)
throws IOException
{
byte[] der = oid.getDER();
writeLength(out, der.length);
out.write(der);
return der.length;
}
private static int writeBitString(OutputStream out, BitString bs)
throws IOException
{
byte[] buf = bs.getShiftedByteArray();
out.write(buf.length + 1);
out.write(bs.getIgnoredBits());
out.write(buf);
return buf.length;
}
private static int writeString(OutputStream out, int tag, String str)
throws IOException
{
byte[] b = null;
switch (tag & 0x1F)
{
case NUMERIC_STRING:
case PRINTABLE_STRING:
case T61_STRING:
case VIDEOTEX_STRING:
case IA5_STRING:
case GRAPHIC_STRING:
case ISO646_STRING:
case GENERAL_STRING:
b = toIso88591(str);
break;
case UNIVERSAL_STRING:
case BMP_STRING:
b = toUtf16Be(str);
break;
case UTF8_STRING:
default:
b = toUtf8(str);
break;
}
writeLength(out, b.length);
out.write(b);
return b.length;
}
private static byte[] toIso88591(String string)
{
byte[] result = new byte[string.length()];
for (int i = 0; i < string.length(); i++)
result[i] = (byte) string.charAt(i);
return result;
}
private static byte[] toUtf16Be(String string)
{
byte[] result = new byte[string.length() * 2];
for (int i = 0; i < string.length(); i++)
{
result[i*2 ] = (byte) ((string.charAt(i) >>> 8) & 0xFF);
result[i*2+1] = (byte) (string.charAt(i) & 0xFF);
}
return result;
}
private static byte[] toUtf8(String string)
{
ByteArrayOutputStream buf =
new ByteArrayOutputStream((int)(string.length() * 1.5));
for (int i = 0; i < string.length(); i++)
{
char c = string.charAt(i);
if (c < 0x0080)
buf.write(c & 0xFF);
else if (c < 0x0800)
{
buf.write(0xC0 | ((c >>> 6) & 0x3F));
buf.write(0x80 | (c & 0x3F));
}
else
{
buf.write(0xE0 | ((c >>> 12) & 0x0F));
buf.write(0x80 | ((c >>> 6) & 0x3F));
buf.write(0x80 | (c & 0x3F));
}
}
return buf.toByteArray();
}
private static int writeDate(OutputStream out, int tag, Date date)
throws IOException
{
SimpleDateFormat sdf = null;
if ((tag & 0x1F) == UTC_TIME)
sdf = new SimpleDateFormat("yyMMddHHmmss'Z'");
else
sdf = new SimpleDateFormat("yyyyMMddHHmmss'.'SSS'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
byte[] b = sdf.format(date).getBytes("ISO-8859-1");
writeLength(out, b.length);
out.write(b);
return b.length;
}
// Package method.
// ------------------------------------------------------------------------
static void writeLength(OutputStream out, int len) throws IOException
{
if (len < 128)
out.write(len);
else if (len < 256)
{
out.write(0x81);
out.write(len);
}
else if (len < 65536)
{
out.write(0x82);
out.write(len >> 8);
out.write(len);
}
else if (len < 16777216)
{
out.write(0x83);
out.write(len >> 16);
out.write(len >> 8);
out.write(len);
}
else
{
out.write(0x84);
out.write(len >> 24);
out.write(len >> 16);
out.write(len >> 8);
out.write(len);
}
}
}
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in gnu.java.security.der package.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - gnu.java.security.der</title></head>
<body>
<p></p>
</body>
</html>
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in gnu.java.security package.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - gnu.java.security</title></head>
<body>
<p></p>
</body>
</html>
@@ -0,0 +1,364 @@
/* PKCS7SignedData.java -- reader for PKCS#7 signedData objects
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.pkcs;
import gnu.java.security.OID;
import gnu.java.security.ber.BER;
import gnu.java.security.ber.BEREncodingException;
import gnu.java.security.ber.BERReader;
import gnu.java.security.ber.BERValue;
import gnu.java.security.der.DERValue;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.cert.CRL;
import java.security.cert.CRLException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* The SignedData object in PKCS #7. This is a read-only implementation of
* this format, and is used to provide signed Jar file support.
*
* @author Casey Marshall (csm@gnu.org)
*/
public class PKCS7SignedData
{
public static final OID PKCS7_DATA = new OID("1.2.840.113549.1.7.1");
public static final OID PKCS7_SIGNED_DATA = new OID("1.2.840.113549.1.7.2");
private BigInteger version;
private Set digestAlgorithms;
private OID contentType;
private byte[] content;
private Certificate[] certificates;
private CRL[] crls;
private Set signerInfos;
private static final boolean DEBUG = false;
private static void debug(String msg)
{
System.err.print("PKCS7SignedData >> ");
System.err.println(msg);
}
public PKCS7SignedData(InputStream in)
throws CRLException, CertificateException, IOException
{
this(new BERReader(in));
}
/**
* Parse an encoded PKCS#7 SignedData object. The ASN.1 format of this
* object is:
*
* <pre>
* SignedData ::= SEQUENCE {
* version Version,
* digestAlgorithms DigestAlgorithmIdentifiers,
* contentInfo ContentInfo,
* certificates
* [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
* crls
* [1] IMPLICIT CertificateRevocationLists OPTIONAL,
* signerInfos SignerInfos }
*
* Version ::= INTEGER
*
* DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
*
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier
*
* ContentInfo ::= SEQUENCE {
* contentType ContentType,
* content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
*
* ContentType ::= OBJECT IDENTIFIER
*
* ExtendedCertificatesAndCertificates ::=
* SET OF ExtendedCertificatesAndCertificate
*
* ExtendedCertificatesAndCertificate ::= CHOICE {
* certificate Certificate, -- from X.509
* extendedCertificate [0] IMPLICIT ExtendedCertificate }
*
* CertificateRevocationLists ::= SET OF CertificateRevocationList
* -- from X.509
*
* SignerInfos ::= SET OF SignerInfo
*
* SignerInfo ::= SEQUENCE {
* version Version,
* issuerAndSerialNumber IssuerAndSerialNumber,
* digestAlgorithm DigestAlgorithmIdentifier,
* authenticatedAttributes
* [0] IMPLICIT Attributes OPTIONAL,
* digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
* encryptedDigest EncryptedDigest,
* unauthenticatedAttributes
* [1] IMPLICIT Attributes OPTIONAL }
*
* EncryptedDigest ::= OCTET STRING
* </pre>
*
* <p>(Readers who are confused as to why it takes 40 levels of indirection
* to specify "data with a signature", rest assured that the present author
* is as confused as you are).</p>
*/
public PKCS7SignedData(BERReader ber)
throws CRLException, CertificateException, IOException
{
CertificateFactory x509 = CertificateFactory.getInstance("X509");
DERValue val = ber.read();
if (!val.isConstructed())
throw new BEREncodingException("malformed ContentInfo");
val = ber.read();
if (val.getTag() != BER.OBJECT_IDENTIFIER)
throw new BEREncodingException("malformed ContentType");
if (!PKCS7_SIGNED_DATA.equals(val.getValue()))
throw new BEREncodingException("content is not SignedData");
val = ber.read();
if (val.getTag() != 0)
throw new BEREncodingException("malformed Content");
val = ber.read();
if (!val.isConstructed())
throw new BEREncodingException("malformed SignedData");
if (DEBUG)
debug("SignedData: " + val);
val = ber.read();
if (val.getTag() != BER.INTEGER)
throw new BEREncodingException("expecting Version");
version = (BigInteger) val.getValue();
if (DEBUG)
debug(" Version: " + version);
digestAlgorithms = new HashSet();
val = ber.read();
if (!val.isConstructed())
throw new BEREncodingException("malformed DigestAlgorithmIdentifiers");
if (DEBUG)
debug(" DigestAlgorithmIdentifiers: " + val);
int count = 0;
DERValue val2 = ber.read();
while (val2 != BER.END_OF_SEQUENCE &&
(val.getLength() > 0 && val.getLength() > count))
{
if (!val2.isConstructed())
throw new BEREncodingException("malformed AlgorithmIdentifier");
if (DEBUG)
debug(" AlgorithmIdentifier: " + val2);
count += val2.getEncodedLength();
val2 = ber.read();
if (val2.getTag() != BER.OBJECT_IDENTIFIER)
throw new BEREncodingException("malformed AlgorithmIdentifier");
if (DEBUG)
debug(" ID: " + val2.getValue());
List algId = new ArrayList(2);
algId.add(val2.getValue());
val2 = ber.read();
if (val2 != BER.END_OF_SEQUENCE)
{
count += val2.getEncodedLength();
if (val2.getTag() == BER.NULL)
algId.add(null);
else
algId.add(val2.getEncoded());
if (DEBUG)
debug(" params: " + new BigInteger(1, val2.getEncoded()).toString(16));
if (val2.isConstructed())
ber.skip(val2.getLength());
if (BERValue.isIndefinite(val))
val2 = ber.read();
}
else
algId.add(null);
digestAlgorithms.add(algId);
}
val = ber.read();
if (!val.isConstructed())
throw new BEREncodingException("malformed ContentInfo");
if (DEBUG)
debug(" ContentInfo: " + val);
val2 = ber.read();
if (val2.getTag() != BER.OBJECT_IDENTIFIER)
throw new BEREncodingException("malformed ContentType");
contentType = (OID) val2.getValue();
if (DEBUG)
debug(" ContentType: " + contentType);
if (BERValue.isIndefinite(val)
|| (val.getLength() > 0 && val.getLength() > val2.getEncodedLength()))
{
val2 = ber.read();
if (val2 != BER.END_OF_SEQUENCE)
{
content = val2.getEncoded();
if (BERValue.isIndefinite(val))
val2 = ber.read();
if (DEBUG)
debug(" Content: " + new BigInteger(1, content).toString(16));
}
}
val = ber.read();
if (val.getTag() == 0)
{
if (!val.isConstructed())
throw new BEREncodingException("malformed ExtendedCertificatesAndCertificates");
if (DEBUG)
debug(" ExtendedCertificatesAndCertificates: " + val);
count = 0;
val2 = ber.read();
List certs = new LinkedList();
while (val2 != BER.END_OF_SEQUENCE &&
(val.getLength() > 0 && val.getLength() > count))
{
Certificate cert =
x509.generateCertificate(new ByteArrayInputStream(val2.getEncoded()));
if (DEBUG)
debug(" Certificate: " + cert);
certs.add(cert);
count += val2.getEncodedLength();
ber.skip(val2.getLength());
if (BERValue.isIndefinite(val) || val.getLength() > count)
val2 = ber.read();
}
certificates = (Certificate[]) certs.toArray(new Certificate[certs.size()]);
val = ber.read();
}
if (val.getTag() == 1)
{
if (!val.isConstructed())
throw new BEREncodingException("malformed CertificateRevocationLists");
if (DEBUG)
debug(" CertificateRevocationLists: " + val);
count = 0;
val2 = ber.read();
List crls = new LinkedList();
while (val2 != BER.END_OF_SEQUENCE &&
(val.getLength() > 0 && val.getLength() > count))
{
CRL crl = x509.generateCRL(new ByteArrayInputStream(val2.getEncoded()));
if (DEBUG)
debug (" CRL: " + crl);
crls.add(crl);
count += val2.getEncodedLength();
ber.skip(val2.getLength());
if (BERValue.isIndefinite(val) || val.getLength() > count)
val2 = ber.read();
}
this.crls = (CRL[]) crls.toArray(new CRL[crls.size()]);
val = ber.read();
}
signerInfos = new HashSet();
if (!val.isConstructed())
throw new BEREncodingException("malformed SignerInfos");
if (DEBUG)
debug(" SignerInfos: " + val);
// FIXME read this more carefully.
// Since we are just reading a file (probably) we just read until we
// reach the end.
while (true)
{
int i = ber.peek();
if (i == 0 || i == -1)
break;
signerInfos.add(new SignerInfo(ber));
}
}
public BigInteger getVersion()
{
return version;
}
public Certificate[] getCertificates()
{
return (certificates != null ? (Certificate[]) certificates.clone()
: null);
}
public OID getContentType()
{
return contentType;
}
public byte[] getContent()
{
return (content != null ? (byte[]) content.clone() : null);
}
public Set getDigestAlgorithms()
{
// FIXME copy contents too, they are mutable!!!
return Collections.unmodifiableSet(digestAlgorithms);
}
public Set getSignerInfos()
{
Set copy = new HashSet();
for (Iterator it = signerInfos.iterator(); it.hasNext(); )
copy.add(it.next());
return Collections.unmodifiableSet(copy);
}
}
@@ -0,0 +1,279 @@
/* SignerInfo.java -- a SignerInfo object, from PKCS #7
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.pkcs;
import gnu.java.security.OID;
import gnu.java.security.ber.BER;
import gnu.java.security.ber.BEREncodingException;
import gnu.java.security.ber.BERReader;
import gnu.java.security.ber.BERValue;
import gnu.java.security.der.DERValue;
import java.io.IOException;
import java.math.BigInteger;
import javax.security.auth.x500.X500Principal;
public class SignerInfo
{
private final BigInteger version;
private final BigInteger serialNumber;
private final X500Principal issuer;
private final OID digestAlgorithmId;
private final byte[] digestAlgorithmParams;
private final byte[] authenticatedAttributes;
private final OID digestEncryptionAlgorithmId;
private final byte[] digestEncryptionAlgorithmParams;
private final byte[] encryptedDigest;
private final byte[] unauthenticatedAttributes;
private static final boolean DEBUG = false;
private static void debug(String msg)
{
System.err.print("SignerInfo >> ");
System.err.println(msg);
}
/**
* Parse a SignerInfo object.
*/
public SignerInfo(BERReader ber) throws IOException
{
DERValue val = ber.read();
if (DEBUG)
debug("SignerInfo: " + val);
if (!val.isConstructed())
throw new BEREncodingException("malformed SignerInfo");
val = ber.read();
if (val.getTag() != BER.INTEGER)
throw new BEREncodingException("malformed Version");
version = (BigInteger) val.getValue();
if (DEBUG)
debug(" Version: " + version);
val = ber.read();
if (!val.isConstructed())
throw new BEREncodingException("malformed IssuerAndSerialNumber");
if (DEBUG)
debug(" IssuerAndSerialNumber: " + val);
val = ber.read();
if (!val.isConstructed())
throw new BEREncodingException("malformed Issuer");
issuer = new X500Principal(val.getEncoded());
ber.skip(val.getLength());
if (DEBUG)
debug(" Issuer: " + issuer);
val = ber.read();
if (val.getTag() != BER.INTEGER)
throw new BEREncodingException("malformed SerialNumber");
serialNumber = (BigInteger) val.getValue();
if (DEBUG)
debug(" SerialNumber: " + serialNumber);
val = ber.read();
if (!val.isConstructed())
throw new BEREncodingException("malformed DigestAlgorithmIdentifier");
if (DEBUG)
debug(" DigestAlgorithmIdentifier: " + val);
int count = 0;
DERValue val2 = ber.read();
if (val2.getTag() != BER.OBJECT_IDENTIFIER)
throw new BEREncodingException("malformed AlgorithmIdentifier");
digestAlgorithmId = (OID) val2.getValue();
if (DEBUG)
debug(" OID: " + digestAlgorithmId);
if (BERValue.isIndefinite(val))
{
val2 = ber.read();
if (val2 != BER.END_OF_SEQUENCE)
{
digestAlgorithmParams = val2.getEncoded();
val2 = ber.read();
if (val2 != BER.END_OF_SEQUENCE)
throw new BEREncodingException("expecting BER end-of-sequence");
}
else
digestAlgorithmParams = null;
}
else if (val2.getEncodedLength() < val.getLength())
{
val2 = ber.read();
digestAlgorithmParams = val2.getEncoded();
if (val2.isConstructed())
ber.skip(val2.getLength());
}
else
digestAlgorithmParams = null;
if(DEBUG)
debug(" params: " + (digestAlgorithmParams == null ? null
: new BigInteger(digestAlgorithmParams).toString(16)));
val = ber.read();
if (val.getTag() == 0)
{
authenticatedAttributes = val.getEncoded();
val = ber.read();
if (val.isConstructed())
ber.skip(val.getLength());
if (DEBUG)
debug(" AuthenticatedAttributes: " + val);
val = ber.read();
}
else
authenticatedAttributes = null;
if (!val.isConstructed())
throw new BEREncodingException("malformed DigestEncryptionAlgorithmIdentifier");
if (DEBUG)
debug(" DigestEncryptionAlgorithmIdentifier: " + val);
count = 0;
val2 = ber.read();
if (val2.getTag() != BER.OBJECT_IDENTIFIER)
throw new BEREncodingException("malformed AlgorithmIdentifier");
digestEncryptionAlgorithmId = (OID) val2.getValue();
if (DEBUG)
debug(" OID: " + digestEncryptionAlgorithmId);
if (BERValue.isIndefinite(val))
{
val2 = ber.read();
if (val2 != BER.END_OF_SEQUENCE)
{
digestEncryptionAlgorithmParams = val2.getEncoded();
val2 = ber.read();
if (val2 != BER.END_OF_SEQUENCE)
throw new BEREncodingException("expecting BER end-of-sequence");
}
else
digestEncryptionAlgorithmParams = null;
}
else if (val2.getEncodedLength() < val.getLength())
{
val2 = ber.read();
digestEncryptionAlgorithmParams = val2.getEncoded();
if (val2.isConstructed())
ber.skip(val2.getLength());
}
else
digestEncryptionAlgorithmParams = null;
if(DEBUG)
debug(" params: " + (digestEncryptionAlgorithmParams == null ? null
: new BigInteger(digestEncryptionAlgorithmParams).toString(16)));
val = ber.read();
if (val.getTag() != BER.OCTET_STRING)
throw new BEREncodingException("malformed EncryptedDigest");
encryptedDigest = (byte[]) val.getValue();
if (DEBUG)
debug(" EncryptedDigest: " + new BigInteger(1, encryptedDigest).toString(16));
if (ber.peek() == 1)
unauthenticatedAttributes = ber.read().getEncoded();
else
unauthenticatedAttributes = null;
if (ber.peek() == 0)
ber.read();
}
public BigInteger getVersion()
{
return version;
}
public BigInteger getSerialNumber()
{
return serialNumber;
}
public X500Principal getIssuer()
{
return issuer;
}
public OID getDigestAlgorithmId()
{
return digestAlgorithmId;
}
public byte[] getDigestAlgorithmParams()
{
return (digestAlgorithmParams != null
? (byte[]) digestAlgorithmParams.clone()
: null);
}
public byte[] getAuthenticatedAttributes()
{
return (authenticatedAttributes != null
? (byte[]) authenticatedAttributes.clone()
: null);
}
public OID getDigestEncryptionAlgorithmId()
{
return digestEncryptionAlgorithmId;
}
public byte[] getDigestEncryptionAlgorithmParams()
{
return (digestEncryptionAlgorithmParams != null
? (byte[]) digestEncryptionAlgorithmParams.clone()
: null);
}
public byte[] getEncryptedDigest()
{
return (encryptedDigest != null ? (byte[]) encryptedDigest.clone() : null);
}
public byte[] getUnauthenticatedAttributes()
{
return (unauthenticatedAttributes != null
? (byte[]) unauthenticatedAttributes.clone()
: null);
}
}
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in gnu.java.security.pkcs package.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - gnu.java.security.pkcs</title></head>
<body>
<p></p>
</body>
</html>
@@ -0,0 +1,102 @@
/* CollectionCertStore.java -- Collection-based cert store.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.security.InvalidAlgorithmParameterException;
import java.security.cert.CRL;
import java.security.cert.CRLSelector;
import java.security.cert.CertSelector;
import java.security.cert.CertStoreException;
import java.security.cert.CertStoreParameters;
import java.security.cert.CertStoreSpi;
import java.security.cert.Certificate;
import java.security.cert.CollectionCertStoreParameters;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
public final class CollectionCertStoreImpl extends CertStoreSpi
{
// Fields.
// -------------------------------------------------------------------------
private final Collection store;
// Constructors.
// -------------------------------------------------------------------------
public CollectionCertStoreImpl(CertStoreParameters params)
throws InvalidAlgorithmParameterException
{
super(params);
if (! (params instanceof CollectionCertStoreParameters))
throw new InvalidAlgorithmParameterException("not a CollectionCertStoreParameters object");
store = ((CollectionCertStoreParameters) params).getCollection();
}
// Instance methods.
// -------------------------------------------------------------------------
public Collection engineGetCertificates(CertSelector selector)
throws CertStoreException
{
LinkedList result = new LinkedList();
for (Iterator it = store.iterator(); it.hasNext(); )
{
Object o = it.next();
if ((o instanceof Certificate) && selector.match((Certificate) o))
result.add(o);
}
return result;
}
public Collection engineGetCRLs(CRLSelector selector)
throws CertStoreException
{
LinkedList result = new LinkedList();
for (Iterator it = store.iterator(); it.hasNext(); )
{
Object o = it.next();
if ((o instanceof CRL) && selector.match((CRL) o))
result.add(o);
}
return result;
}
}
@@ -0,0 +1,134 @@
/* DSAKeyFactory.java -- DSA key factory.
Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactorySpi;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
/**
* DSA key factory.
*
* @author Casey Marshall (rsdio@metastatic.org)
*/
public class DSAKeyFactory extends KeyFactorySpi
{
// Constructor.
// ------------------------------------------------------------------------
public DSAKeyFactory()
{
super();
}
// Instance methods.
// ------------------------------------------------------------------------
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
throws InvalidKeySpecException
{
if (!(keySpec instanceof DSAPrivateKeySpec))
throw new InvalidKeySpecException();
return new GnuDSAPrivateKey(
((DSAPrivateKeySpec) keySpec).getX(),
((DSAPrivateKeySpec) keySpec).getP(),
((DSAPrivateKeySpec) keySpec).getQ(),
((DSAPrivateKeySpec) keySpec).getG());
}
protected PublicKey engineGeneratePublic(KeySpec keySpec)
throws InvalidKeySpecException
{
if (!(keySpec instanceof DSAPublicKeySpec))
throw new InvalidKeySpecException();
return new GnuDSAPublicKey(
((DSAPublicKeySpec) keySpec).getY(),
((DSAPublicKeySpec) keySpec).getP(),
((DSAPublicKeySpec) keySpec).getQ(),
((DSAPublicKeySpec) keySpec).getG());
}
protected KeySpec engineGetKeySpec(Key key, Class keySpec)
throws InvalidKeySpecException
{
if ((key instanceof DSAPublicKey) &&
keySpec.isAssignableFrom(DSAPublicKeySpec.class))
{
return new DSAPublicKeySpec(((DSAPublicKey) key).getY(),
((DSAPublicKey) key).getParams().getP(),
((DSAPublicKey) key).getParams().getQ(),
((DSAPublicKey) key).getParams().getG());
}
if ((key instanceof DSAPrivateKey) &&
keySpec.isAssignableFrom(DSAPrivateKeySpec.class))
{
return new DSAPrivateKeySpec(((DSAPrivateKey) key).getX(),
((DSAPrivateKey) key).getParams().getP(),
((DSAPrivateKey) key).getParams().getQ(),
((DSAPrivateKey) key).getParams().getG());
}
throw new InvalidKeySpecException();
}
protected Key engineTranslateKey(Key key) throws InvalidKeyException
{
if ((key instanceof GnuDSAPublicKey) || (key instanceof GnuDSAPrivateKey))
return key;
if (key instanceof DSAPublicKey)
return new GnuDSAPublicKey(((DSAPublicKey) key).getY(),
((DSAPublicKey) key).getParams().getP(),
((DSAPublicKey) key).getParams().getQ(),
((DSAPublicKey) key).getParams().getG());
if (key instanceof DSAPrivateKey)
return new GnuDSAPrivateKey(((DSAPrivateKey) key).getX(),
((DSAPrivateKey) key).getParams().getP(),
((DSAPrivateKey) key).getParams().getQ(),
((DSAPrivateKey) key).getParams().getG());
throw new InvalidKeyException();
}
}
@@ -0,0 +1,171 @@
/* GnuDSAKeyPairGenerator.java --- Gnu DSA Key Pair Generator
Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.math.BigInteger;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidParameterException;
import java.security.KeyPair;
import java.security.KeyPairGeneratorSpi;
import java.security.SecureRandom;
import java.security.interfaces.DSAParams;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.DSAParameterSpec;
import java.util.Random;
public class DSAKeyPairGenerator extends KeyPairGeneratorSpi
implements java.security.interfaces.DSAKeyPairGenerator
{
int keysize;
SecureRandom random;
private BigInteger q = null; // the small prime
private BigInteger p = null; // the big prime
private BigInteger g = null;
DSAKeyPairGenerator()
{
keysize = 1024;
}
public void initialize(int keysize, SecureRandom random)
{
//if( ((keysize % 64) != 0) || (keysize < 512) || (keysize > 1024) )
// throw new InvalidAlgorithmParameterException("Invalid key size");
this.keysize = keysize;
this.random = random;
}
public void initialize(AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidAlgorithmParameterException
{
if( !( params instanceof DSAParameterSpec ) )
throw new InvalidAlgorithmParameterException("Must be DSAParameterSpec");
DSAParameterSpec dsaparameterspec = (DSAParameterSpec)params;
p = dsaparameterspec.getP();
q = dsaparameterspec.getQ();
g = dsaparameterspec.getG();
this.random = random;
}
public void initialize(DSAParams params, SecureRandom random)
throws InvalidParameterException
{
if(params.getP() != null)
p = params.getP();
else
throw new InvalidParameterException();
if(params.getQ() != null)
q = params.getQ();
else
throw new InvalidParameterException();
if(params.getG() != null)
g = params.getG();
else
throw new InvalidParameterException();
this.random = random;
}
public void initialize(int modlen, boolean genParams, SecureRandom random)
throws InvalidParameterException
{
if( ((modlen % 64) != 0) || (modlen < 512) || (modlen > 1024) )
throw new InvalidParameterException();
if( (genParams == false) && (modlen != 512) && (modlen != 768) && (modlen != 1024) )
throw new InvalidParameterException();
this.keysize = modlen;
this.random = random;
p = null;
q = null;
g = null;
}
public KeyPair generateKeyPair()
{
if( getDefaults() == false) {
try {
AlgorithmParameterGenerator apgDSA = AlgorithmParameterGenerator.getInstance("DSA");
AlgorithmParameters apDSA = apgDSA.generateParameters();
DSAParameterSpec dsaparameterspec = (DSAParameterSpec)apDSA.getParameterSpec( DSAParameterSpec.class );
p = dsaparameterspec.getP();
q = dsaparameterspec.getQ();
g = dsaparameterspec.getG();
} catch ( Exception e ) {
return null;
}
}
BigInteger x = new BigInteger( 159, new Random() );
BigInteger y = g.modPow( x, p );
return new KeyPair( new GnuDSAPublicKey(y,p,q,g), new GnuDSAPrivateKey(x,p,q,g));
//return new KeyPair( public, private );
}
//These constants are Sun's Constants copied from the
//Cryptography Specification
private boolean getDefaults()
{
if( keysize == 512) {
p = new BigInteger("fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e17", 16);
q = new BigInteger("962eddcc369cba8ebb260ee6b6a126d9346e38c5", 16);
g = new BigInteger("678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca4", 16);
return true;
} else if( keysize == 768) {
p = new BigInteger("e9e642599d355f37c97ffd3567120b8e25c9cd43e927b3a9670fbec5d890141922d2c3b3ad2480093799869d1e846aab49fab0ad26d2ce6a22219d470bce7d777d4a21fbe9c270b57f607002f3cef8393694cf45ee3688c11a8c56ab127a3daf", 16);
q = new BigInteger("9cdbd84c9f1ac2f38d0f80f42ab952e7338bf511", 16);
g = new BigInteger("30470ad5a005fb14ce2d9dcd87e38bc7d1b1c5facbaecbe95f190aa7a31d23c4dbbcbe06174544401a5b2c020965d8c2bd2171d3668445771f74ba084d2029d83c1c158547f3a9f1a2715be23d51ae4d3e5a1f6a7064f316933a346d3f529252", 16);
} else if( keysize == 512) {
p = new BigInteger("fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b76b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7", 16);
q = new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5", 16);
g = new BigInteger("f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d0782675159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e13c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243bcca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a", 16);
}
return false;
}
}
@@ -0,0 +1,128 @@
/* DSAParameterGenerator.java --- DSA Parameter Generator Implementation
Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.util.Prime;
import java.math.BigInteger;
import java.security.AlgorithmParameterGeneratorSpi;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.DSAParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.util.Random;
public class DSAParameterGenerator extends AlgorithmParameterGeneratorSpi
{
private int size;
private SecureRandom random = null;
public DSAParameterGenerator()
{
size = 1024;
}
public void engineInit(int size, SecureRandom random)
{
if( (size < 512) || (size > 1024) || ( (size % 64) != 0) )
//throw new InvalidAlgorithmParameterException("Invalid Size");
return;
this.size = size;
this.random = random;
}
public void engineInit(AlgorithmParameterSpec genParamSpec, SecureRandom random)
throws InvalidAlgorithmParameterException
{
if( !( genParamSpec instanceof DSAParameterSpec ) )
throw new InvalidAlgorithmParameterException("Must be DSAParameterSpec");
DSAParameterSpec dsaparameterspec = (DSAParameterSpec)genParamSpec;
int tmp = dsaparameterspec.getP().bitLength();
if( (tmp < 512) || (tmp > 1024) || ( (tmp % 64) != 0) )
throw new InvalidAlgorithmParameterException("Invalid Size");
this.random = random;
}
//For more information see IEEE P1363 A.16.1 (10/05/98 Draft)
public AlgorithmParameters engineGenerateParameters()
{
DSAParameterSpec dsaparameterspec;
int L = size;
BigInteger r, p, k, h, g;
//q 2^159 < q < 2^160
r = Prime.generateRandomPrime( 159, 160, BigInteger.valueOf(1));
// 2^(L-1) < p < 2^L
p = Prime.generateRandomPrime( r, BigInteger.valueOf(1), L - 1, L, BigInteger.valueOf(1));
k = p.subtract( BigInteger.valueOf(1) );
k = k.divide( r );
Random rand = new Random();
h = BigInteger.valueOf(1);
for(;;) {
h = h.add(BigInteger.valueOf( 1 ) );
g = h.modPow(k, p);
if( g.compareTo( BigInteger.valueOf(1) ) != 1 )
break;
}
try {
dsaparameterspec = new DSAParameterSpec(p, r, g);
AlgorithmParameters ap = AlgorithmParameters.getInstance("DSA");
ap.init( dsaparameterspec );
return ap;
} catch ( NoSuchAlgorithmException nsae ) {
return null;
} catch ( InvalidParameterSpecException ipse) {
return null;
}
}
}
@@ -0,0 +1,150 @@
/* DSAParameters.java --- DSA Parameters Implementation
Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.io.ASN1ParsingException;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.der.DERWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.AlgorithmParametersSpi;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.DSAParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.util.ArrayList;
/*
ASN.1 Encoding for DSA from rfc2459
id-dsa ID ::= { iso(1) member-body(2) us(840) x9-57(10040)
x9cm(4) 1 }
Dss-Parms ::= SEQUENCE {
p INTEGER,
q INTEGER,
g INTEGER }
*/
public class DSAParameters extends AlgorithmParametersSpi
{
private BigInteger q; // the small prime
private BigInteger p; // the big prime
private BigInteger g;
public void engineInit(AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException
{
if( paramSpec instanceof DSAParameterSpec ) {
DSAParameterSpec dsaParamSpec = (DSAParameterSpec)paramSpec;
p = dsaParamSpec.getP();
q = dsaParamSpec.getQ();
g = dsaParamSpec.getG();
}
else
throw new InvalidParameterSpecException("Only accepts DSAParameterSpec");
}
public void engineInit(byte[] params)
throws IOException
{
DERReader in = new DERReader(params);
DERValue val = in.read();
if (val.getValue() != DER.CONSTRUCTED_VALUE)
throw new ASN1ParsingException("badly formed parameters");
try
{
p = (BigInteger) in.read().getValue();
q = (BigInteger) in.read().getValue();
g = (BigInteger) in.read().getValue();
}
catch (Exception x)
{
throw new ASN1ParsingException("badly formed parameters");
}
}
public void engineInit(byte[] params, String format)
throws IOException
{
if( !format.equals("ASN.1") )
throw new IOException("Invalid Format: Only accepts ASN.1");
engineInit( params );
}
public AlgorithmParameterSpec engineGetParameterSpec(Class paramSpec)
throws InvalidParameterSpecException
{
if( paramSpec.isAssignableFrom(DSAParameterSpec.class) )
return new DSAParameterSpec(p, q, g);
else
throw new InvalidParameterSpecException("Only accepts DSAParameterSpec");
}
public byte[] engineGetEncoded()
throws IOException
{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ArrayList seq = new ArrayList(3);
seq.add(new DERValue(DER.INTEGER, p));
seq.add(new DERValue(DER.INTEGER, q));
seq.add(new DERValue(DER.INTEGER, g));
DERWriter.write(bout, new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, seq));
return bout.toByteArray();
}
public byte[] engineGetEncoded(String format)
throws IOException
{
if( !format.equals("ASN.1") )
throw new IOException("Invalid Format: Only accepts ASN.1");
return engineGetEncoded();
}
public String engineToString()
{
return ("q: " + q + " p: " + p + " g: " + g);
}
}
@@ -0,0 +1,251 @@
/* DSASignature.java --
Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.der.DERWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.SignatureException;
import java.security.SignatureSpi;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.util.ArrayList;
import java.util.Random;
public class DSASignature extends SignatureSpi
{
private DSAPublicKey publicKey;
private DSAPrivateKey privateKey;
private final MessageDigest digest;
private final SecureRandom random;
public DSASignature() throws NoSuchAlgorithmException
{
random = new SecureRandom();
digest = MessageDigest.getInstance ("SHA1");
}
private void init()
{
digest.reset();
}
public void engineInitVerify (PublicKey publicKey)
throws InvalidKeyException
{
if (publicKey instanceof DSAPublicKey)
this.publicKey = (DSAPublicKey) publicKey;
else
throw new InvalidKeyException();
init();
}
public void engineInitSign (PrivateKey privateKey)
throws InvalidKeyException
{
if (privateKey instanceof DSAPrivateKey)
this.privateKey = (DSAPrivateKey) privateKey;
else
throw new InvalidKeyException ("not a DSA private key");
init();
}
public void engineInitSign (PrivateKey privateKey,
SecureRandom random)
throws InvalidKeyException
{
if (privateKey instanceof DSAPrivateKey)
this.privateKey = (DSAPrivateKey) privateKey;
else
throw new InvalidKeyException ("not a DSA private key");
appRandom = random;
init();
}
public void engineUpdate(byte b)
throws SignatureException
{
digest.update (b);
}
public void engineUpdate (byte[] b, int off, int len)
throws SignatureException
{
digest.update (b, off, len);
}
public byte[] engineSign() throws SignatureException
{
if (privateKey == null)
throw new SignatureException ("not initialized for signing");
try
{
BigInteger g = privateKey.getParams().getG();
BigInteger p = privateKey.getParams().getP();
BigInteger q = privateKey.getParams().getQ();
BigInteger x = privateKey.getX();
BigInteger k = new BigInteger (159, appRandom != null ? appRandom : random);
BigInteger r = g.modPow(k, p);
r = r.mod(q);
byte bytes[] = digest.digest();
BigInteger sha = new BigInteger (1, bytes);
BigInteger s = sha.add (x.multiply (r));
s = s.multiply (k.modInverse(q)).mod (q);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ArrayList seq = new ArrayList (2);
seq.add(0, new DERValue (DER.INTEGER, r));
seq.add(1, new DERValue (DER.INTEGER, s));
DERWriter.write (bout, new DERValue (DER.CONSTRUCTED | DER.SEQUENCE, seq));
return bout.toByteArray();
}
catch (IOException ioe)
{
SignatureException se = new SignatureException();
se.initCause (ioe);
throw se;
}
catch (ArithmeticException ae)
{
SignatureException se = new SignatureException();
se.initCause (ae);
throw se;
}
}
public int engineSign (byte[] outbuf, int offset, int len)
throws SignatureException
{
byte tmp[] = engineSign();
if (tmp.length > len)
throw new SignatureException ("output buffer too short");
System.arraycopy (tmp, 0, outbuf, offset, tmp.length);
return tmp.length;
}
public boolean engineVerify (byte[] sigBytes)
throws SignatureException
{
// Decode sigBytes from ASN.1 DER encoding
try
{
DERReader in = new DERReader (sigBytes);
DERValue val = in.read();
if (!val.isConstructed())
throw new SignatureException ("badly formed signature");
BigInteger r = (BigInteger) in.read().getValue();
BigInteger s = (BigInteger) in.read().getValue();
BigInteger g = publicKey.getParams().getG();
BigInteger p = publicKey.getParams().getP();
BigInteger q = publicKey.getParams().getQ();
BigInteger y = publicKey.getY();
BigInteger w = s.modInverse (q);
byte bytes[] = digest.digest();
BigInteger sha = new BigInteger (1, bytes);
BigInteger u1 = w.multiply (sha).mod ( q );
BigInteger u2 = r.multiply (w).mod(q);
BigInteger v = g.modPow (u1, p).multiply (y.modPow (u2, p)).mod (p).mod (q);
if (v.equals (r))
return true;
else
return false;
}
catch (IOException ioe)
{
SignatureException se = new SignatureException ("badly formed signature");
se.initCause (ioe);
throw se;
}
}
public void engineSetParameter (String param,
Object value)
throws InvalidParameterException
{
throw new InvalidParameterException();
}
public void engineSetParameter (AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException
{
throw new InvalidParameterException();
}
public Object engineGetParameter (String param)
throws InvalidParameterException
{
throw new InvalidParameterException();
}
public Object clone() throws CloneNotSupportedException
{
return super.clone();
}
}
@@ -0,0 +1,68 @@
/* DefaultPolicy.java --
Copyright (C) 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.Policy;
/**
* This is just a stub policy implementation which grants all permissions
* to any code source. FIXME: This should be replaced with a real
* implementation that reads the policy configuration from a file, like
* $JAVA_HOME/jre/lib/security/java.security.
*/
public class DefaultPolicy extends Policy
{
static Permission allPermission = new AllPermission();
public PermissionCollection getPermissions(CodeSource codesource)
{
Permissions perms = new Permissions();
perms.add(allPermission);
return perms;
}
public void refresh()
{
// Nothing.
}
}
@@ -0,0 +1,303 @@
/* EncodedKeyFactory.java -- encoded key factory.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.OID;
import gnu.java.security.der.BitString;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.IOException;
import java.math.BigInteger;
import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactorySpi;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.DSAParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.spec.DHParameterSpec;
/**
* A factory for keys encoded in either the X.509 format (for public
* keys) or the PKCS#8 format (for private keys).
*
* @author Casey Marshall (rsdio@metastatic.org)
*/
public class EncodedKeyFactory extends KeyFactorySpi
{
// Constants.
// ------------------------------------------------------------------------
private static final OID ID_DSA = new OID("1.2.840.10040.4.1");
private static final OID ID_RSA = new OID("1.2.840.113549.1.1.1");
private static final OID ID_DH = new OID("1.2.840.10046.2.1");
// Instance methods.
// ------------------------------------------------------------------------
public PublicKey engineGeneratePublic(KeySpec spec)
throws InvalidKeySpecException
{
if (!(spec instanceof X509EncodedKeySpec))
throw new InvalidKeySpecException("only supports X.509 key specs");
DERReader der = new DERReader(((X509EncodedKeySpec) spec).getEncoded());
try
{
DERValue spki = der.read();
if (!spki.isConstructed())
{
throw new InvalidKeySpecException("malformed encoded key");
}
DERValue alg = der.read();
if (!alg.isConstructed())
{
throw new InvalidKeySpecException("malformed encoded key");
}
DERValue val = der.read();
if (!(val.getValue() instanceof OID))
{
throw new InvalidKeySpecException("malformed encoded key");
}
OID algId = (OID) val.getValue();
byte[] algParams = null;
if (alg.getLength() > val.getEncodedLength())
{
val = der.read();
algParams = val.getEncoded();
if (val.isConstructed())
der.skip(val.getLength());
}
val = der.read();
if (!(val.getValue() instanceof BitString))
{
throw new InvalidKeySpecException("malformed encoded key");
}
byte[] publicKey = ((BitString) val.getValue()).toByteArray();
if (algId.equals(ID_DSA))
{
BigInteger p = null, g = null, q = null, Y;
if (algParams != null)
{
DERReader dsaParams = new DERReader(algParams);
val = dsaParams.read();
if (!val.isConstructed())
throw new InvalidKeySpecException("malformed DSA parameters");
val = dsaParams.read();
if (!(val.getValue() instanceof BigInteger))
throw new InvalidKeySpecException("malformed DSA parameters");
p = (BigInteger) val.getValue();
val = dsaParams.read();
if (!(val.getValue() instanceof BigInteger))
throw new InvalidKeySpecException("malformed DSA parameters");
q = (BigInteger) val.getValue();
val = dsaParams.read();
if (!(val.getValue() instanceof BigInteger))
throw new InvalidKeySpecException("malformed DSA parameters");
g = (BigInteger) val.getValue();
}
DERReader dsaPub = new DERReader(publicKey);
val = dsaPub.read();
if (!(val.getValue() instanceof BigInteger))
throw new InvalidKeySpecException("malformed DSA parameters");
Y = (BigInteger) val.getValue();
return new GnuDSAPublicKey(Y, p, q, g);
}
else if (algId.equals(ID_RSA))
{
DERReader rsaParams = new DERReader(publicKey);
if (!rsaParams.read().isConstructed())
{
throw new InvalidKeySpecException("malformed encoded key");
}
return new GnuRSAPublicKey(new RSAPublicKeySpec(
(BigInteger) rsaParams.read().getValue(),
(BigInteger) rsaParams.read().getValue()));
}
else if (algId.equals(ID_DH))
{
if (algParams == null)
throw new InvalidKeySpecException("missing DH parameters");
DERReader dhParams = new DERReader(algParams);
val = dhParams.read();
BigInteger p, g, q, Y;
if (!val.isConstructed())
throw new InvalidKeySpecException("malformed DH parameters");
val = dhParams.read();
if (!(val.getValue() instanceof BigInteger))
throw new InvalidKeySpecException("malformed DH parameters");
p = (BigInteger) val.getValue();
val = dhParams.read();
if (!(val.getValue() instanceof BigInteger))
throw new InvalidKeySpecException("malformed DH parameters");
g = (BigInteger) val.getValue();
val = dhParams.read();
if (!(val.getValue() instanceof BigInteger))
throw new InvalidKeySpecException("malformed DH parameters");
q = (BigInteger) val.getValue();
DERReader dhPub = new DERReader(publicKey);
val = dhPub.read();
if (!(val.getValue() instanceof BigInteger))
throw new InvalidKeySpecException("malformed DH parameters");
Y = (BigInteger) val.getValue();
return (PublicKey) new GnuDHPublicKey(new DHParameterSpec(p, g), Y, q);
}
else
throw new InvalidKeySpecException("unknown algorithm: " + algId);
}
catch (IOException ioe)
{
throw new InvalidKeySpecException(ioe.getMessage());
}
}
public PrivateKey engineGeneratePrivate(KeySpec spec)
throws InvalidKeySpecException
{
if (!(spec instanceof PKCS8EncodedKeySpec))
{
throw new InvalidKeySpecException("only supports PKCS8 key specs");
}
DERReader der = new DERReader(((PKCS8EncodedKeySpec) spec).getEncoded());
try
{
DERValue pki = der.read();
if (!pki.isConstructed())
{
throw new InvalidKeySpecException("malformed encoded key");
}
DERValue val = der.read();
if (!(val.getValue() instanceof BigInteger))
{
throw new InvalidKeySpecException("malformed encoded key");
}
DERValue alg = der.read();
if (!alg.isConstructed())
{
throw new InvalidKeySpecException("malformed encoded key");
}
val = der.read();
if (!(val.getValue() instanceof OID))
{
throw new InvalidKeySpecException("malformed encoded key");
}
OID algId = (OID) val.getValue();
byte[] algParams = null;
if (alg.getLength() > val.getEncodedLength())
{
val = der.read();
algParams = val.getEncoded();
if (val.isConstructed())
der.skip(val.getLength());
}
byte[] privateKey = (byte[]) der.read().getValue();
if (algId.equals(ID_DSA))
{
if (algParams == null)
{
throw new InvalidKeySpecException("missing DSA parameters");
}
AlgorithmParameters params = AlgorithmParameters.getInstance("DSA");
params.init(algParams);
DSAParameterSpec dsaSpec = (DSAParameterSpec)
params.getParameterSpec(DSAParameterSpec.class);
DERReader dsaPriv = new DERReader(privateKey);
return new GnuDSAPrivateKey((BigInteger) dsaPriv.read().getValue(),
dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG());
}
else if (algId.equals(ID_RSA))
{
DERReader rsaParams = new DERReader(privateKey);
if (!rsaParams.read().isConstructed())
throw new InvalidKeySpecException("malformed encoded key");
return new GnuRSAPrivateKey(new RSAPrivateCrtKeySpec(
(BigInteger) rsaParams.read().getValue(), // n
(BigInteger) rsaParams.read().getValue(), // e
(BigInteger) rsaParams.read().getValue(), // d
(BigInteger) rsaParams.read().getValue(), // p
(BigInteger) rsaParams.read().getValue(), // q
(BigInteger) rsaParams.read().getValue(), // d mod (p - 1)
(BigInteger) rsaParams.read().getValue(), // d mod (q - 1)
(BigInteger) rsaParams.read().getValue())); // (inv q) mod p
}
else
throw new InvalidKeySpecException("unknown algorithm: " + algId);
}
catch (InvalidParameterSpecException iapse)
{
throw new InvalidKeySpecException(iapse.getMessage());
}
catch (NoSuchAlgorithmException nsae)
{
throw new InvalidKeySpecException(nsae.getMessage());
}
catch (IOException ioe)
{
throw new InvalidKeySpecException(ioe.getMessage());
}
}
public KeySpec engineGetKeySpec(Key key, Class speClass)
throws InvalidKeySpecException
{
if ((key instanceof PrivateKey) && key.getFormat().equals("PKCS#8")
&& speClass.isAssignableFrom(PKCS8EncodedKeySpec.class))
return new PKCS8EncodedKeySpec(key.getEncoded());
else if ((key instanceof PublicKey) && key.getFormat().equals("X.509")
&& speClass.isAssignableFrom(X509EncodedKeySpec.class))
return new X509EncodedKeySpec(key.getEncoded());
else
throw new InvalidKeySpecException();
}
public Key engineTranslateKey(Key key) throws InvalidKeyException
{
throw new InvalidKeyException("translating keys not supported");
}
}
@@ -0,0 +1,168 @@
/* Gnu.java --- Gnu provider main class
Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.Provider;
public final class Gnu extends Provider
{
public Gnu()
{
super("GNU", 1.0, "GNU provider v1.0 implementing SHA-1, MD5, DSA, RSA, X.509 Certificates and CRLs, PKIX certificate path validators, Collection cert stores");
AccessController.doPrivileged (new PrivilegedAction()
{
public Object run()
{
// Note that all implementation class names are referenced by using
// Class.getName(). That way when we staticly link the Gnu provider
// we automatically get all the implementation classes.
// Signature
put("Signature.SHA1withDSA",
gnu.java.security.provider.DSASignature.class.getName());
put("Alg.Alias.Signature.DSS", "SHA1withDSA");
put("Alg.Alias.Signature.DSA", "SHA1withDSA");
put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA");
put("Alg.Alias.Signature.DSAwithSHA", "SHA1withDSA");
put("Alg.Alias.Signature.DSAwithSHA1", "SHA1withDSA");
put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.OID.1.2.840.10040.4.3", "SHA1withDSA");
put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
put("Alg.Alias.Signature.1.3.14.3.2.13", "SHA1withDSA");
put("Alg.Alias.Signature.1.3.14.3.2.27", "SHA1withDSA");
put("Signature.MD2withRSA", MD2withRSA.class.getName());
put("Signature.MD2withRSA ImplementedIn", "Software");
put("Alg.Alias.Signature.md2WithRSAEncryption", "MD2withRSA");
put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.2", "MD2withRSA");
put("Alg.Alias.Signature.1.2.840.113549.1.1.2", "MD2withRSA");
put("Signature.MD4withRSA", MD4withRSA.class.getName());
put("Signature.MD4withRSA ImplementedIn", "Software");
put("Alg.Alias.Signature.md4WithRSAEncryption", "MD4withRSA");
put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.3", "MD4withRSA");
put("Alg.Alias.Signature.1.2.840.113549.1.1.3", "MD4withRSA");
put("Signature.MD5withRSA", MD5withRSA.class.getName());
put("Signature.MD5withRSA ImplementedIn", "Software");
put("Alg.Alias.Signature.md5WithRSAEncryption", "MD5withRSA");
put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.4", "MD5withRSA");
put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5withRSA");
put("Signature.SHA1withRSA", SHA1withRSA.class.getName());
put("Signature.SHA1withRSA ImplementedIn", "Software");
put("Alg.Alias.Signature.sha-1WithRSAEncryption", "SHA1withRSA");
put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5", "SHA1withRSA");
put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
// Key Pair Generator
put("KeyPairGenerator.DSA",
gnu.java.security.provider.DSAKeyPairGenerator.class.getName());
put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSA");
put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA");
put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA");
// Key Factory
put("KeyFactory.DSA",
gnu.java.security.provider.DSAKeyFactory.class.getName());
put("KeyFactory.Encoded", EncodedKeyFactory.class.getName());
put("KeyFactory.Encoded ImplementedIn", "Software");
put("Alg.Alias.KeyFactory.X.509", "Encoded");
put("Alg.Alias.KeyFactory.X509", "Encoded");
put("Alg.Alias.KeyFactory.PKCS#8", "Encoded");
put("Alg.Alias.KeyFactory.PKCS8", "Encoded");
put("KeyFactory.RSA", RSAKeyFactory.class.getName());
put("Alg.Alias.KeyFactory.OID.1.2.840.10040.4.1", "DSA");
put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSA");
put("Alg.Alias.KeyFactory.1.3.14.3.2.12", "DSA");
// Message Digests
put("MessageDigest.SHA", gnu.java.security.provider.SHA.class.getName());
put("MessageDigest.MD5", gnu.java.security.provider.MD5.class.getName());
// Format "Alias", "Actual Name"
put("Alg.Alias.MessageDigest.SHA1", "SHA");
put("Alg.Alias.MessageDigest.SHA-1", "SHA");
put("Alg.Alias.MessageDigest.SHA-160", "SHA");
// Algorithm Parameters
put("AlgorithmParameters.DSA",
gnu.java.security.provider.DSAParameters.class.getName());
put("Alg.Alias.AlgorithmParameters.DSS", "DSA");
put("Alg.Alias.AlgorithmParameters.SHAwithDSA", "DSA");
put("Alg.Alias.AlgorithmParameters.OID.1.2.840.10040.4.3", "DSA");
put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4.3", "DSA");
// Algorithm Parameter Generator
put("AlgorithmParameterGenerator.DSA",
gnu.java.security.provider.DSAParameterGenerator.class.getName());
// SecureRandom
put("SecureRandom.SHA1PRNG",
gnu.java.security.provider.SHA1PRNG.class.getName());
// CertificateFactory
put("CertificateFactory.X509", X509CertificateFactory.class.getName());
put("CertificateFactory.X509 ImplementedIn", "Software");
put("Alg.Alias.CertificateFactory.X.509", "X509");
// CertPathValidator
put("CertPathValidator.PKIX", PKIXCertPathValidatorImpl.class.getName());
put("CertPathValidator.PKIX ImplementedIn", "Software");
// CertStore
put("CertStore.Collection", CollectionCertStoreImpl.class.getName());
return null;
}
});
}
}
@@ -0,0 +1,115 @@
/* GnuDHPublicKey.java -- A Diffie-Hellman public key.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.OID;
import gnu.java.security.der.BitString;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERValue;
import java.math.BigInteger;
import java.util.ArrayList;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
public class GnuDHPublicKey implements DHPublicKey
{
// Fields.
// -------------------------------------------------------------------------
private byte[] encoded;
private final DHParameterSpec params;
private final BigInteger Y;
private final BigInteger q;
// Constructor.
// -------------------------------------------------------------------------
public GnuDHPublicKey(DHParameterSpec params, BigInteger Y, BigInteger q)
{
this.params = params;
this.Y = Y;
this.q = q;
}
// Instance methods.
// -------------------------------------------------------------------------
public BigInteger getY()
{
return Y;
}
public DHParameterSpec getParams()
{
return params;
}
public String getAlgorithm()
{
return "DH";
}
public String getFormat()
{
return "X.509";
}
public byte[] getEncoded()
{
if (encoded != null)
return (byte[]) encoded.clone();
ArrayList spki = new ArrayList(2);
ArrayList alg = new ArrayList(2);
alg.add(new DERValue(DER.OBJECT_IDENTIFIER, new OID("1.2.840.10046.2.1")));
ArrayList param = new ArrayList(3);
param.add(new DERValue(DER.INTEGER, params.getP()));
param.add(new DERValue(DER.INTEGER, params.getG()));
param.add(new DERValue(DER.INTEGER, q));
alg.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, param));
spki.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, alg));
spki.add(new DERValue(DER.BIT_STRING, new BitString(Y.toByteArray())));
encoded = new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, spki).getEncoded();
if (encoded != null)
return (byte[]) encoded.clone();
return null;
}
}
@@ -0,0 +1,147 @@
/* GnuDSAPrivateKey.java --- Gnu DSA Private Key
Copyright (C) 1999,2003,2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERValue;
import gnu.java.security.der.DERWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPrivateKey;
import java.security.spec.DSAParameterSpec;
import java.util.ArrayList;
public class GnuDSAPrivateKey implements DSAPrivateKey
{
private byte[] encodedKey;
BigInteger x;
BigInteger p;
BigInteger q;
BigInteger g;
public GnuDSAPrivateKey(BigInteger x, BigInteger p, BigInteger q, BigInteger g )
{
this.x = x;
this.p = p;
this.q = q;
this.g = g;
}
public String getAlgorithm()
{
return "DSA";
}
public String getFormat()
{
return "PKCS#8";
}
/**
* Encodes this key as a <code>PrivateKeyInfo</code>, as described in
* PKCS #8. The ASN.1 specification for this structure is:
*
* <blockquote><pre>
* PrivateKeyInfo ::= SEQUENCE {
* version Version,
* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
* privateKey PrivateKey,
* attributes [0] IMPLICIT Attributes OPTIONAL }
*
* Version ::= INTEGER
*
* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
*
* PrivateKey ::= OCTET STRING
*
* Attributes ::= SET OF Attribute
* </pre></blockquote>
*
* <p>DSA private keys (in Classpath at least) have no attributes.
*/
public byte[] getEncoded()
{
if (encodedKey != null)
return (byte[]) encodedKey.clone();
try
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
ArrayList pki = new ArrayList(3);
pki.add(new DERValue(DER.INTEGER, BigInteger.ZERO));
ArrayList algId = new ArrayList(2);
algId.add(new DERValue(DER.OBJECT_IDENTIFIER,
new OID("1.2.840.10040.4.1")));
ArrayList algParams = new ArrayList(3);
algParams.add(new DERValue(DER.INTEGER, p));
algParams.add(new DERValue(DER.INTEGER, q));
algParams.add(new DERValue(DER.INTEGER, g));
algId.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, algParams));
pki.add(new DERValue(DER.OCTET_STRING, x.toByteArray()));
DERWriter.write(out, new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, pki));
return (byte[]) (encodedKey = out.toByteArray()).clone();
}
catch (IOException ioe)
{
return null;
}
}
public DSAParams getParams()
{
return (DSAParams)(new DSAParameterSpec(p,q,g));
}
public BigInteger getX()
{
return x;
}
public String toString()
{
return "GnuDSAPrivateKey: x="
+ (x != null ? x.toString(16) : "null") + " p="
+ (p != null ? p.toString(16) : "null") + " q="
+ (q != null ? q.toString(16) : "null") + " g="
+ (g != null ? g.toString(16) : "null");
}
}
@@ -0,0 +1,137 @@
/* GnuDSAPublicKey.java --- Gnu DSA Public Key
Copyright (C) 1999,2003,2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.OID;
import gnu.java.security.der.BitString;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERValue;
import gnu.java.security.der.DERWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.DSAParameterSpec;
import java.util.ArrayList;
public class GnuDSAPublicKey implements DSAPublicKey
{
private byte[] encodedKey;
BigInteger y;
BigInteger p;
BigInteger q;
BigInteger g;
public GnuDSAPublicKey(BigInteger y, BigInteger p, BigInteger q, BigInteger g )
{
this.y = y;
this.p = p;
this.q = q;
this.g = g;
}
public String getAlgorithm()
{
return "DSA";
}
public String getFormat()
{
return "X.509";
}
/**
* The encoded form of DSA public keys is:
*
* <blockquote><pre>
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING }
* </pre></blockquote>
*/
public byte[] getEncoded()
{
if (encodedKey != null)
return (byte[]) encodedKey.clone();
try
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
ArrayList spki = new ArrayList(2);
ArrayList alg = new ArrayList(2);
alg.add(new DERValue(DER.OBJECT_IDENTIFIER,
new OID("1.2.840.113549.1.1.1")));
ArrayList params = new ArrayList(3);
params.add(new DERValue(DER.INTEGER, p));
params.add(new DERValue(DER.INTEGER, q));
params.add(new DERValue(DER.INTEGER, g));
alg.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, params));
spki.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, alg));
spki.add(new DERValue(DER.BIT_STRING, new BitString(y.toByteArray())));
DERWriter.write(out, new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, spki));
return (byte[]) (encodedKey = out.toByteArray()).clone();
}
catch (IOException ioe)
{
return null;
}
}
public DSAParams getParams()
{
if (p == null || q == null || g == null)
return null;
return (DSAParams)(new DSAParameterSpec(p,q,g));
}
public BigInteger getY()
{
return y;
}
public String toString()
{
return
"GnuDSAPublicKey: y=" + (y != null ? y.toString(16) : "(null)") +
" p=" + (p != null ? p.toString(16) : "(null)") +
" q=" + (q != null ? q.toString(16) : "(null)") +
" g=" + (g != null ? g.toString(16) : "(null)");
}
}
@@ -0,0 +1,164 @@
/* GnuRSAPrivateKey.java -- GNU RSA private key.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERValue;
import java.math.BigInteger;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.util.ArrayList;
class GnuRSAPrivateKey implements RSAPrivateCrtKey
{
// Fields.
// -------------------------------------------------------------------------
private final RSAPrivateCrtKeySpec spec;
private byte[] encodedKey;
// Constructor.
// -------------------------------------------------------------------------
public GnuRSAPrivateKey(RSAPrivateCrtKeySpec spec)
{
this.spec = spec;
}
// Instance methods.
// -------------------------------------------------------------------------
public BigInteger getModulus()
{
return spec.getModulus();
}
public BigInteger getPrivateExponent()
{
return spec.getPrivateExponent();
}
public BigInteger getCrtCoefficient()
{
return spec.getCrtCoefficient();
}
public BigInteger getPrimeExponentP()
{
return spec.getPrimeExponentP();
}
public BigInteger getPrimeExponentQ()
{
return spec.getPrimeExponentQ();
}
public BigInteger getPrimeP()
{
return spec.getPrimeP();
}
public BigInteger getPrimeQ()
{
return spec.getPrimeQ();
}
public BigInteger getPublicExponent()
{
return spec.getPublicExponent();
}
public String getAlgorithm()
{
return "RSA";
}
public String getFormat()
{
return "PKCS#8";
}
/**
* The encoded form is:
*
* <pre>
* RSAPrivateKey ::= SEQUENCE {
* version Version,
* modulus INTEGER, -- n
* publicExponent INTEGER, -- e
* privateExponent INTEGER, -- d
* prime1 INTEGER, -- p
* prime2 INTEGER, -- q
* exponent1 INTEGER, -- d mod (p-1)
* exponent2 INTEGER, -- d mod (q-1)
* coefficient INTEGER -- (inverse of q) mod p }
* </pre>
*
* <p>Which is in turn encoded in a PrivateKeyInfo structure from PKCS#8.
*/
public byte[] getEncoded()
{
if (encodedKey != null)
return (byte[]) encodedKey.clone();
ArrayList key = new ArrayList(9);
key.add(new DERValue(DER.INTEGER, BigInteger.ZERO));
key.add(new DERValue(DER.INTEGER, getModulus()));
key.add(new DERValue(DER.INTEGER, getPublicExponent()));
key.add(new DERValue(DER.INTEGER, getPrivateExponent()));
key.add(new DERValue(DER.INTEGER, getPrimeP()));
key.add(new DERValue(DER.INTEGER, getPrimeQ()));
key.add(new DERValue(DER.INTEGER, getPrimeExponentP()));
key.add(new DERValue(DER.INTEGER, getPrimeExponentQ()));
key.add(new DERValue(DER.INTEGER, getCrtCoefficient()));
DERValue pk = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, key);
ArrayList pki = new ArrayList(3);
pki.add(new DERValue(DER.INTEGER, BigInteger.ZERO));
ArrayList alg = new ArrayList(2);
alg.add(new DERValue(DER.OBJECT_IDENTIFIER,
new OID("1.2.840.113549.1.1.1")));
alg.add(new DERValue(DER.NULL, null));
pki.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, alg));
pki.add(new DERValue(DER.OCTET_STRING, pk.getEncoded()));
encodedKey = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, pki).getEncoded();
return (byte[]) encodedKey.clone();
}
}
@@ -0,0 +1,109 @@
/* GnuRSAPublicKey.java -- GNU RSA public key.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.OID;
import gnu.java.security.der.BitString;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERValue;
import java.math.BigInteger;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
import java.util.ArrayList;
class GnuRSAPublicKey implements RSAPublicKey
{
// Fields.
// -------------------------------------------------------------------------
private final RSAPublicKeySpec spec;
private byte[] encodedKey;
// Constructor.
// -------------------------------------------------------------------------
public GnuRSAPublicKey(RSAPublicKeySpec spec)
{
this.spec = spec;
}
// Instance methods.
// -------------------------------------------------------------------------
public BigInteger getModulus()
{
return spec.getModulus();
}
public BigInteger getPublicExponent()
{
return spec.getPublicExponent();
}
public String getAlgorithm()
{
return "RSA";
}
public String getFormat()
{
return "X.509";
}
public byte[] getEncoded()
{
if (encodedKey != null)
return (byte[]) encodedKey.clone();
ArrayList key = new ArrayList(2);
key.add(new DERValue(DER.INTEGER, getModulus()));
key.add(new DERValue(DER.INTEGER, getPublicExponent()));
DERValue rsapk = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, key);
ArrayList alg = new ArrayList(2);
alg.add(new DERValue(DER.OBJECT_IDENTIFIER,
new OID("1.2.840.113549.1.1.1")));
alg.add(new DERValue(DER.NULL, null));
ArrayList spki = new ArrayList(2);
spki.add(new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, alg));
spki.add(new DERValue(DER.BIT_STRING, new BitString(rsapk.getEncoded())));
encodedKey = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, spki).getEncoded();
return (byte[]) encodedKey.clone();
}
}
@@ -0,0 +1,54 @@
/* MD2withRSA.java -- MD2 with RSA encryption signatures.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD2withRSA extends RSA
{
// Constructor.
// -------------------------------------------------------------------------
public MD2withRSA() throws NoSuchAlgorithmException
{
super(MessageDigest.getInstance("MD2"), DIGEST_ALGORITHM.getChild(2));
}
}
@@ -0,0 +1,54 @@
/* MD4withRSA.java -- MD4 with RSA encryption signatures.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD4withRSA extends RSA
{
// Constructor.
// -------------------------------------------------------------------------
public MD4withRSA() throws NoSuchAlgorithmException
{
super(MessageDigest.getInstance("MD4"), DIGEST_ALGORITHM.getChild(4));
}
}
@@ -0,0 +1,338 @@
/* MD5.java -- Class implementing the MD5 algorithm as specified in RFC1321.
Copyright (C) 1999, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.security.MessageDigest;
/**
This class implements the MD5 algorithm as described in RFC1321.
@see java.security.MessageDigest
*/
public class MD5 extends MessageDigest implements Cloneable
{
private final int W[] = new int[16];
private long bytecount;
private int A;
private int B;
private int C;
private int D;
public MD5()
{
super("MD5");
engineReset ();
}
public Object clone()
{
return new MD5 (this);
}
private MD5 (MD5 copy)
{
this ();
bytecount = copy.bytecount;
A = copy.A;
B = copy.B;
C = copy.C;
D = copy.D;
System.arraycopy (copy.W, 0, W, 0, 16);
}
public int engineGetDigestLength()
{
return 16;
}
// Intialize the A,B,C,D needed for the hash
public void engineReset()
{
bytecount = 0;
A = 0x67452301;
B = 0xefcdab89;
C = 0x98badcfe;
D = 0x10325476;
for(int i = 0; i < 16; i++)
W[i] = 0;
}
public void engineUpdate (byte b)
{
int i = (int)bytecount % 64;
int shift = (3 - i % 4) * 8;
int idx = i / 4;
// if you could index ints, this would be: W[idx][shift/8] = b
W[idx] = (W[idx] & ~(0xff << shift)) | ((b & 0xff) << shift);
// if we've filled up a block, then process it
if ((++ bytecount) % 64 == 0)
munch ();
}
public void engineUpdate (byte bytes[], int off, int len)
{
if (len < 0)
throw new ArrayIndexOutOfBoundsException ();
int end = off + len;
while (off < end)
engineUpdate (bytes[off++]);
}
public byte[] engineDigest()
{
long bitcount = bytecount * 8;
engineUpdate ((byte)0x80); // 10000000 in binary; the start of the padding
// add the rest of the padding to fill this block out, but leave 8
// bytes to put in the original bytecount
while ((int)bytecount % 64 != 56)
engineUpdate ((byte)0);
// add the length of the original, unpadded block to the end of
// the padding
W[14] = SWAP((int)(0xffffffff & bitcount));
W[15] = SWAP((int)(0xffffffff & (bitcount >>> 32)));
bytecount += 8;
// digest the fully padded block
munch ();
A = SWAP(A);
B = SWAP(B);
C = SWAP(C);
D = SWAP(D);
byte[] result = new byte[] {(byte)(A >>> 24), (byte)(A >>> 16),
(byte)(A >>> 8), (byte)A,
(byte)(B >>> 24), (byte)(B >>> 16),
(byte)(B >>> 8), (byte)B,
(byte)(C >>> 24), (byte)(C >>> 16),
(byte)(C >>> 8), (byte)C,
(byte)(D >>> 24), (byte)(D >>> 16),
(byte)(D >>> 8), (byte)D};
engineReset ();
return result;
}
private int F( int X, int Y, int Z)
{
return ((X & Y) | (~X & Z));
}
private int G( int X, int Y, int Z)
{
return ((X & Z) | (Y & ~Z));
}
private int H( int X, int Y, int Z)
{
return (X ^ Y ^ Z);
}
private int I( int X, int Y, int Z)
{
return (Y ^ (X | ~Z));
}
private int rotateLeft( int i, int count)
{
//Taken from FIPS 180-1
return ( (i << count) | (i >>> (32 - count)) ) ;
}
/* Round 1. */
private int FF( int a, int b, int c, int d, int k, int s, int i)
{
/* Let [abcd k s i] denote the operation */
a += F(b,c,d) + k + i;
return b + rotateLeft(a, s);
}
/* Round 2. */
private int GG( int a, int b, int c, int d, int k, int s, int i)
{
/* Let [abcd k s i] denote the operation */
a += G(b,c,d) + k + i;
return b + rotateLeft(a, s);
}
/* Round 3. */
private int HH( int a, int b, int c, int d, int k, int s, int i)
{
/* Let [abcd k s t] denote the operation */
a += H(b,c,d) + k + i;
return b + rotateLeft(a, s);
}
/* Round 4. */
private int II( int a, int b, int c, int d, int k, int s, int i)
{
/* Let [abcd k s t] denote the operation */
a += I(b,c,d) + k + i;
return b + rotateLeft(a, s);
}
private int SWAP(int n)
{
//Copied from md5.c in FSF Gnu Privacy Guard 0.9.2
return (( (0xff & n) << 24) | ((n & 0xff00) << 8) | ((n >>> 8) & 0xff00) | (n >>> 24));
}
private void munch()
{
int AA,BB,CC,DD, j;
int X[] = new int[16];
/* Copy block i into X. */
for(j = 0; j < 16; j++)
X[j] = SWAP(W[j]);
/* Save A as AA, B as BB, C as CC, and D as DD. */
AA = A;
BB = B;
CC = C;
DD = D;
/* The hex constants are from md5.c
in FSF Gnu Privacy Guard 0.9.2 */
/* Round 1. */
/* Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
/* Do the following 16 operations. */
A = FF(A,B,C,D, X[0], 7, 0xd76aa478);
D = FF(D,A,B,C, X[1], 12, 0xe8c7b756);
C = FF(C,D,A,B, X[2], 17, 0x242070db);
B = FF(B,C,D,A, X[3], 22, 0xc1bdceee);
A = FF(A,B,C,D, X[4], 7, 0xf57c0faf);
D = FF(D,A,B,C, X[5], 12, 0x4787c62a);
C = FF(C,D,A,B, X[6], 17, 0xa8304613);
B = FF(B,C,D,A, X[7], 22, 0xfd469501);
A = FF(A,B,C,D, X[8], 7, 0x698098d8);
D = FF(D,A,B,C, X[9], 12, 0x8b44f7af);
C = FF(C,D,A,B, X[10], 17, 0xffff5bb1);
B = FF(B,C,D,A, X[11], 22, 0x895cd7be);
A = FF(A,B,C,D, X[12], 7, 0x6b901122);
D = FF(D,A,B,C, X[13], 12, 0xfd987193);
C = FF(C,D,A,B, X[14], 17, 0xa679438e);
B = FF(B,C,D,A, X[15], 22, 0x49b40821);
/* Round 2. */
/* Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
/* Do the following 16 operations. */
A = GG(A,B,C,D, X[1], 5, 0xf61e2562);
D = GG(D,A,B,C, X[6], 9, 0xc040b340);
C = GG(C,D,A,B, X[11], 14, 0x265e5a51);
B = GG(B,C,D,A, X[0], 20, 0xe9b6c7aa);
A = GG(A,B,C,D, X[5], 5, 0xd62f105d);
D = GG(D,A,B,C, X[10], 9, 0x02441453);
C = GG(C,D,A,B, X[15], 14, 0xd8a1e681);
B = GG(B,C,D,A, X[4], 20, 0xe7d3fbc8);
A = GG(A,B,C,D, X[9], 5, 0x21e1cde6);
D = GG(D,A,B,C, X[14], 9, 0xc33707d6);
C = GG(C,D,A,B, X[3], 14, 0xf4d50d87);
B = GG(B,C,D,A, X[8], 20, 0x455a14ed);
A = GG(A,B,C,D, X[13], 5, 0xa9e3e905);
D = GG(D,A,B,C, X[2], 9, 0xfcefa3f8);
C = GG(C,D,A,B, X[7], 14, 0x676f02d9);
B = GG(B,C,D,A, X[12], 20, 0x8d2a4c8a);
/* Round 3. */
/* Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
/* Do the following 16 operations. */
A = HH(A,B,C,D, X[5], 4, 0xfffa3942);
D = HH(D,A,B,C, X[8], 11, 0x8771f681);
C = HH(C,D,A,B, X[11], 16, 0x6d9d6122);
B = HH(B,C,D,A, X[14], 23, 0xfde5380c);
A = HH(A,B,C,D, X[1], 4, 0xa4beea44);
D = HH(D,A,B,C, X[4], 11, 0x4bdecfa9);
C = HH(C,D,A,B, X[7], 16, 0xf6bb4b60);
B = HH(B,C,D,A, X[10], 23, 0xbebfbc70);
A = HH(A,B,C,D, X[13], 4, 0x289b7ec6);
D = HH(D,A,B,C, X[0], 11, 0xeaa127fa);
C = HH(C,D,A,B, X[3], 16, 0xd4ef3085);
B = HH(B,C,D,A, X[6], 23, 0x04881d05);
A = HH(A,B,C,D, X[9], 4, 0xd9d4d039);
D = HH(D,A,B,C, X[12], 11, 0xe6db99e5);
C = HH(C,D,A,B, X[15], 16, 0x1fa27cf8);
B = HH(B,C,D,A, X[2], 23, 0xc4ac5665);
/* Round 4. */
/* Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
/* Do the following 16 operations. */
A = II(A,B,C,D, X[0], 6, 0xf4292244);
D = II(D,A,B,C, X[7], 10, 0x432aff97);
C = II(C,D,A,B, X[14], 15, 0xab9423a7);
B = II(B,C,D,A, X[5], 21, 0xfc93a039);
A = II(A,B,C,D, X[12], 6, 0x655b59c3);
D = II(D,A,B,C, X[3], 10, 0x8f0ccc92);
C = II(C,D,A,B, X[10], 15, 0xffeff47d);
B = II(B,C,D,A, X[1], 21, 0x85845dd1);
A = II(A,B,C,D, X[8], 6, 0x6fa87e4f);
D = II(D,A,B,C, X[15], 10, 0xfe2ce6e0);
C = II(C,D,A,B, X[6], 15, 0xa3014314);
B = II(B,C,D,A, X[13], 21, 0x4e0811a1);
A = II(A,B,C,D, X[4], 6, 0xf7537e82);
D = II(D,A,B,C, X[11], 10, 0xbd3af235);
C = II(C,D,A,B, X[2], 15, 0x2ad7d2bb);
B = II(B,C,D,A, X[9], 21, 0xeb86d391);
/* Then perform the following additions. (That is increment each
of the four registers by the value it had before this block
was started.) */
A = A + AA;
B = B + BB;
C = C + CC;
D = D + DD;
}
}
@@ -0,0 +1,54 @@
/* MD5withRSA.java -- MD5 with RSA encryption signatures.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5withRSA extends RSA
{
// Constructor.
// -------------------------------------------------------------------------
public MD5withRSA() throws NoSuchAlgorithmException
{
super(MessageDigest.getInstance("MD5"), DIGEST_ALGORITHM.getChild(5));
}
}
@@ -0,0 +1,701 @@
/* PKIXCertPathValidatorImpl.java -- PKIX certificate path validator.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.OID;
import gnu.java.security.x509.GnuPKIExtension;
import gnu.java.security.x509.PolicyNodeImpl;
import gnu.java.security.x509.X509CRLSelectorImpl;
import gnu.java.security.x509.X509CertSelectorImpl;
import gnu.java.security.x509.ext.BasicConstraints;
import gnu.java.security.x509.ext.CertificatePolicies;
import gnu.java.security.x509.ext.Extension;
import gnu.java.security.x509.ext.KeyUsage;
import gnu.java.security.x509.ext.PolicyConstraint;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.PublicKey;
import java.security.cert.CRL;
import java.security.cert.CertPath;
import java.security.cert.CertPathParameters;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorResult;
import java.security.cert.CertPathValidatorSpi;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.CertificateException;
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXCertPathValidatorResult;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPublicKey;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* An implementation of the Public Key Infrastructure's X.509
* certificate path validation algorithm.
*
* <p>See <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
* Internet X.509 Public Key Infrastructure Certificate and
* Certificate Revocation List (CRL) Profile</a>.
*
* @author Casey Marshall (rsdio@metastatic.org)
*/
public class PKIXCertPathValidatorImpl extends CertPathValidatorSpi
{
// Constants.
// -------------------------------------------------------------------------
private static final boolean DEBUG = false;
private static void debug (String msg)
{
System.err.print (">> PKIXCertPathValidatorImpl: ");
System.err.println (msg);
}
public static final String ANY_POLICY = "2.5.29.32.0";
// Constructor.
// -------------------------------------------------------------------------
public PKIXCertPathValidatorImpl()
{
super();
}
// Instance methods.
// -------------------------------------------------------------------------
public CertPathValidatorResult engineValidate(CertPath path,
CertPathParameters params)
throws CertPathValidatorException, InvalidAlgorithmParameterException
{
if (!(params instanceof PKIXParameters))
throw new InvalidAlgorithmParameterException("not a PKIXParameters object");
// First check if the certificate path is valid.
//
// This means that:
//
// (a) for all x in {1, ..., n-1}, the subject of certificate x is
// the issuer of certificate x+1;
//
// (b) for all x in {1, ..., n}, the certificate was valid at the
// time in question.
//
// Because this is the X.509 algorithm, we also check if all
// cerificates are of type X509Certificate.
PolicyNodeImpl rootNode = new PolicyNodeImpl();
Set initPolicies = ((PKIXParameters) params).getInitialPolicies();
rootNode.setValidPolicy(ANY_POLICY);
rootNode.setCritical(false);
rootNode.setDepth(0);
if (initPolicies != null)
rootNode.addAllExpectedPolicies(initPolicies);
else
rootNode.addExpectedPolicy(ANY_POLICY);
List checks = ((PKIXParameters) params).getCertPathCheckers();
List l = path.getCertificates();
if (l == null || l.size() == 0)
throw new CertPathValidatorException();
X509Certificate[] p = null;
try
{
p = (X509Certificate[]) l.toArray(new X509Certificate[l.size()]);
}
catch (ClassCastException cce)
{
throw new CertPathValidatorException("invalid certificate path");
}
String sigProvider = ((PKIXParameters) params).getSigProvider();
PublicKey prevKey = null;
Date now = ((PKIXParameters) params).getDate();
if (now == null)
now = new Date();
LinkedList policyConstraints = new LinkedList();
for (int i = p.length - 1; i >= 0; i--)
{
try
{
p[i].checkValidity(now);
}
catch (CertificateException ce)
{
throw new CertPathValidatorException(ce.toString());
}
Set uce = getCritExts(p[i]);
for (Iterator check = checks.iterator(); check.hasNext(); )
{
try
{
((PKIXCertPathChecker) check.next()).check(p[i], uce);
}
catch (Exception x)
{
}
}
PolicyConstraint constr = null;
if (p[i] instanceof GnuPKIExtension)
{
Extension pcx =
((GnuPKIExtension) p[i]).getExtension (PolicyConstraint.ID);
if (pcx != null)
constr = (PolicyConstraint) pcx.getValue();
}
else
{
byte[] pcx = p[i].getExtensionValue (PolicyConstraint.ID.toString());
if (pcx != null)
{
try
{
constr = new PolicyConstraint (pcx);
}
catch (Exception x)
{
}
}
}
if (constr != null && constr.getRequireExplicitPolicy() >= 0)
{
policyConstraints.add (new int[]
{ p.length-i, constr.getRequireExplicitPolicy() });
}
updatePolicyTree(p[i], rootNode, p.length-i, (PKIXParameters) params,
checkExplicitPolicy (p.length-i, policyConstraints));
// The rest of the tests involve this cert's relationship with the
// next in the path. If this cert is the end entity, we can stop.
if (i == 0)
break;
basicSanity(p, i);
PublicKey pubKey = null;
try
{
pubKey = p[i].getPublicKey();
if (pubKey instanceof DSAPublicKey)
{
DSAParams dsa = ((DSAPublicKey) pubKey).getParams();
// If the DSA public key is missing its parameters, use those
// from the previous cert's key.
if (dsa == null || dsa.getP() == null || dsa.getG() == null
|| dsa.getQ() == null)
{
if (prevKey == null)
throw new InvalidKeyException("DSA keys not chainable");
if (!(prevKey instanceof DSAPublicKey))
throw new InvalidKeyException("DSA keys not chainable");
dsa = ((DSAPublicKey) prevKey).getParams();
pubKey = new GnuDSAPublicKey(((DSAPublicKey) pubKey).getY(),
dsa.getP(), dsa.getQ(), dsa.getG());
}
}
if (sigProvider == null)
p[i-1].verify(pubKey);
else
p[i-1].verify(pubKey, sigProvider);
prevKey = pubKey;
}
catch (Exception e)
{
throw new CertPathValidatorException(e.toString());
}
if (!p[i].getSubjectDN().equals(p[i-1].getIssuerDN()))
throw new CertPathValidatorException("issuer DN mismatch");
boolean[] issuerUid = p[i-1].getIssuerUniqueID();
boolean[] subjectUid = p[i].getSubjectUniqueID();
if (issuerUid != null && subjectUid != null)
if (!Arrays.equals(issuerUid, subjectUid))
throw new CertPathValidatorException("UID mismatch");
// Check the certificate against the revocation lists.
if (((PKIXParameters) params).isRevocationEnabled())
{
X509CRLSelectorImpl selector = new X509CRLSelectorImpl();
try
{
selector.addIssuerName(p[i].getSubjectDN());
}
catch (IOException ioe)
{
throw new CertPathValidatorException("error selecting CRLs");
}
List certStores = ((PKIXParameters) params).getCertStores();
List crls = new LinkedList();
for (Iterator it = certStores.iterator(); it.hasNext(); )
{
CertStore cs = (CertStore) it.next();
try
{
Collection c = cs.getCRLs(selector);
crls.addAll(c);
}
catch (CertStoreException cse)
{
}
}
if (crls.isEmpty())
throw new CertPathValidatorException("no CRLs for issuer");
boolean certOk = false;
for (Iterator it = crls.iterator(); it.hasNext(); )
{
CRL crl = (CRL) it.next();
if (!(crl instanceof X509CRL))
continue;
X509CRL xcrl = (X509CRL) crl;
if (!checkCRL(xcrl, p, now, p[i], pubKey, certStores))
continue;
if (xcrl.isRevoked(p[i-1]))
throw new CertPathValidatorException("certificate is revoked");
else
certOk = true;
}
if (!certOk)
throw new CertPathValidatorException("certificate's validity could not be determined");
}
}
rootNode.setReadOnly();
// Now ensure that the first certificate in the chain was issued
// by a trust anchor.
Exception cause = null;
Set anchors = ((PKIXParameters) params).getTrustAnchors();
for (Iterator i = anchors.iterator(); i.hasNext(); )
{
TrustAnchor anchor = (TrustAnchor) i.next();
X509Certificate anchorCert = null;
PublicKey anchorKey = null;
if (anchor.getTrustedCert() != null)
{
anchorCert = anchor.getTrustedCert();
anchorKey = anchorCert.getPublicKey();
}
else
anchorKey = anchor.getCAPublicKey();
if (anchorKey == null)
continue;
try
{
if (anchorCert == null)
anchorCert.checkValidity(now);
p[p.length-1].verify(anchorKey);
if (anchorCert != null && anchorCert.getBasicConstraints() >= 0
&& anchorCert.getBasicConstraints() < p.length)
continue;
if (((PKIXParameters) params).isRevocationEnabled())
{
X509CRLSelectorImpl selector = new X509CRLSelectorImpl();
if (anchorCert != null)
try
{
selector.addIssuerName(anchorCert.getSubjectDN());
}
catch (IOException ioe)
{
}
else
selector.addIssuerName(anchor.getCAName());
List certStores = ((PKIXParameters) params).getCertStores();
List crls = new LinkedList();
for (Iterator it = certStores.iterator(); it.hasNext(); )
{
CertStore cs = (CertStore) it.next();
try
{
Collection c = cs.getCRLs(selector);
crls.addAll(c);
}
catch (CertStoreException cse)
{
}
}
if (crls.isEmpty())
continue;
for (Iterator it = crls.iterator(); it.hasNext(); )
{
CRL crl = (CRL) it.next();
if (!(crl instanceof X509CRL))
continue;
X509CRL xcrl = (X509CRL) crl;
try
{
xcrl.verify(anchorKey);
}
catch (Exception x)
{
continue;
}
Date nextUpdate = xcrl.getNextUpdate();
if (nextUpdate != null && nextUpdate.compareTo(now) < 0)
continue;
if (xcrl.isRevoked(p[p.length-1]))
throw new CertPathValidatorException("certificate is revoked");
}
}
// The chain is valid; return the result.
return new PKIXCertPathValidatorResult(anchor, rootNode,
p[0].getPublicKey());
}
catch (Exception ignored)
{
cause = ignored;
continue;
}
}
// The path is not valid.
CertPathValidatorException cpve =
new CertPathValidatorException("path validation failed");
if (cause != null)
cpve.initCause (cause);
throw cpve;
}
// Own methods.
// -------------------------------------------------------------------------
/**
* Check if a given CRL is acceptable for checking the revocation status
* of certificates in the path being checked.
*
* <p>The CRL is accepted iff:</p>
*
* <ol>
* <li>The <i>nextUpdate</i> field (if present) is in the future.</li>
* <li>The CRL does not contain any unsupported critical extensions.</li>
* <li>The CRL is signed by one of the certificates in the path, or,</li>
* <li>The CRL is signed by the given public key and was issued by the
* public key's subject, or,</li>
* <li>The CRL is signed by a certificate in the given cert stores, and
* that cert is signed by one of the certificates in the path.</li>
* </ol>
*
* @param crl The CRL being checked.
* @param path The path this CRL is being checked against.
* @param now The value to use as 'now'.
* @param pubKeySubject The subject of the public key.
* @param pubKey The public key to check.
* @return True if the CRL is acceptable.
*/
private static boolean checkCRL(X509CRL crl, X509Certificate[] path, Date now,
X509Certificate pubKeyCert, PublicKey pubKey,
List certStores)
{
Date nextUpdate = crl.getNextUpdate();
if (nextUpdate != null && nextUpdate.compareTo(now) < 0)
return false;
if (crl.hasUnsupportedCriticalExtension())
return false;
for (int i = 0; i < path.length; i++)
{
if (!path[i].getSubjectDN().equals(crl.getIssuerDN()))
continue;
boolean[] keyUsage = path[i].getKeyUsage();
if (keyUsage != null)
{
if (!keyUsage[KeyUsage.CRL_SIGN])
continue;
}
try
{
crl.verify(path[i].getPublicKey());
return true;
}
catch (Exception x)
{
}
}
if (crl.getIssuerDN().equals(pubKeyCert.getSubjectDN()))
{
try
{
boolean[] keyUsage = pubKeyCert.getKeyUsage();
if (keyUsage != null)
{
if (!keyUsage[KeyUsage.CRL_SIGN])
throw new Exception();
}
crl.verify(pubKey);
return true;
}
catch (Exception x)
{
}
}
try
{
X509CertSelectorImpl select = new X509CertSelectorImpl();
select.addSubjectName(crl.getIssuerDN());
List certs = new LinkedList();
for (Iterator it = certStores.iterator(); it.hasNext(); )
{
CertStore cs = (CertStore) it.next();
try
{
certs.addAll(cs.getCertificates(select));
}
catch (CertStoreException cse)
{
}
}
for (Iterator it = certs.iterator(); it.hasNext(); )
{
X509Certificate c = (X509Certificate) it.next();
for (int i = 0; i < path.length; i++)
{
if (!c.getIssuerDN().equals(path[i].getSubjectDN()))
continue;
boolean[] keyUsage = c.getKeyUsage();
if (keyUsage != null)
{
if (!keyUsage[KeyUsage.CRL_SIGN])
continue;
}
try
{
c.verify(path[i].getPublicKey());
crl.verify(c.getPublicKey());
return true;
}
catch (Exception x)
{
}
}
if (c.getIssuerDN().equals(pubKeyCert.getSubjectDN()))
{
c.verify(pubKey);
crl.verify(c.getPublicKey());
}
}
}
catch (Exception x)
{
}
return false;
}
private static Set getCritExts(X509Certificate cert)
{
HashSet s = new HashSet();
if (cert instanceof GnuPKIExtension)
{
Collection exts = ((GnuPKIExtension) cert).getExtensions();
for (Iterator it = exts.iterator(); it.hasNext(); )
{
Extension ext = (Extension) it.next();
if (ext.isCritical() && !ext.isSupported())
s.add(ext.getOid().toString());
}
}
else
s.addAll(cert.getCriticalExtensionOIDs());
return s;
}
/**
* Perform a basic sanity check on the CA certificate at <code>index</code>.
*/
private static void basicSanity(X509Certificate[] path, int index)
throws CertPathValidatorException
{
X509Certificate cert = path[index];
int pathLen = 0;
for (int i = index - 1; i > 0; i--)
{
if (!path[i].getIssuerDN().equals(path[i].getSubjectDN()))
pathLen++;
}
Extension e = null;
if (cert instanceof GnuPKIExtension)
{
e = ((GnuPKIExtension) cert).getExtension(BasicConstraints.ID);
}
else
{
try
{
e = new Extension(cert.getExtensionValue(BasicConstraints.ID.toString()));
}
catch (Exception x)
{
}
}
if (e == null)
throw new CertPathValidatorException("no basicConstraints");
BasicConstraints bc = (BasicConstraints) e.getValue();
if (!bc.isCA())
throw new CertPathValidatorException("certificate cannot be used to verify signatures");
if (bc.getPathLengthConstraint() >= 0 && bc.getPathLengthConstraint() < pathLen)
throw new CertPathValidatorException("path is too long");
boolean[] keyUsage = cert.getKeyUsage();
if (keyUsage != null)
{
if (!keyUsage[KeyUsage.KEY_CERT_SIGN])
throw new CertPathValidatorException("certificate cannot be used to sign certificates");
}
}
private static void updatePolicyTree(X509Certificate cert, PolicyNodeImpl root,
int depth, PKIXParameters params,
boolean explicitPolicy)
throws CertPathValidatorException
{
if (DEBUG) debug("updatePolicyTree depth == " + depth);
Set nodes = new HashSet();
LinkedList stack = new LinkedList();
Iterator current = null;
stack.addLast(Collections.singleton(root).iterator());
do
{
current = (Iterator) stack.removeLast();
while (current.hasNext())
{
PolicyNodeImpl p = (PolicyNodeImpl) current.next();
if (DEBUG) debug("visiting node == " + p);
if (p.getDepth() == depth - 1)
{
if (DEBUG) debug("added node");
nodes.add(p);
}
else
{
if (DEBUG) debug("skipped node");
stack.addLast(current);
current = p.getChildren();
}
}
}
while (!stack.isEmpty());
Extension e = null;
CertificatePolicies policies = null;
List qualifierInfos = null;
if (cert instanceof GnuPKIExtension)
{
e = ((GnuPKIExtension) cert).getExtension(CertificatePolicies.ID);
if (e != null)
policies = (CertificatePolicies) e.getValue();
}
List cp = null;
if (policies != null)
cp = policies.getPolicies();
else
cp = Collections.EMPTY_LIST;
boolean match = false;
if (DEBUG) debug("nodes are == " + nodes);
if (DEBUG) debug("cert policies are == " + cp);
for (Iterator it = nodes.iterator(); it.hasNext(); )
{
PolicyNodeImpl parent = (PolicyNodeImpl) it.next();
if (DEBUG) debug("adding policies to " + parent);
for (Iterator it2 = cp.iterator(); it2.hasNext(); )
{
OID policy = (OID) it2.next();
if (DEBUG) debug("trying to add policy == " + policy);
if (policy.toString().equals(ANY_POLICY) &&
params.isAnyPolicyInhibited())
continue;
PolicyNodeImpl child = new PolicyNodeImpl();
child.setValidPolicy(policy.toString());
child.addExpectedPolicy(policy.toString());
if (parent.getExpectedPolicies().contains(policy.toString()))
{
parent.addChild(child);
match = true;
}
else if (parent.getExpectedPolicies().contains(ANY_POLICY))
{
parent.addChild(child);
match = true;
}
else if (ANY_POLICY.equals (policy.toString()))
{
parent.addChild (child);
match = true;
}
if (match && policies != null)
{
List qualifiers = policies.getPolicyQualifierInfos (policy);
if (qualifiers != null)
child.addAllPolicyQualifiers (qualifiers);
}
}
}
if (!match && (params.isExplicitPolicyRequired() || explicitPolicy))
throw new CertPathValidatorException("policy tree building failed");
}
private boolean checkExplicitPolicy (int depth, List explicitPolicies)
{
if (DEBUG) debug ("checkExplicitPolicy depth=" + depth);
for (Iterator it = explicitPolicies.iterator(); it.hasNext(); )
{
int[] i = (int[]) it.next();
int caDepth = i[0];
int limit = i[1];
if (DEBUG) debug (" caDepth=" + caDepth + " limit=" + limit);
if (depth - caDepth >= limit)
return true;
}
return false;
}
}
@@ -0,0 +1,311 @@
/* RSA.java -- RSA PKCS#1 signatures.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.der.DERWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.SignatureException;
import java.security.SignatureSpi;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.ArrayList;
public abstract class RSA extends SignatureSpi implements Cloneable
{
// Constants and fields.
// -------------------------------------------------------------------------
/**
* digestAlgorithm OBJECT IDENTIFIER ::=
* { iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) }
*/
protected static final OID DIGEST_ALGORITHM = new OID("1.2.840.113549.2");
protected final OID digestAlgorithm;
protected final MessageDigest md;
protected RSAPrivateKey signerKey;
protected RSAPublicKey verifierKey;
// Constructor.
// -------------------------------------------------------------------------
protected RSA(MessageDigest md, OID digestAlgorithm)
{
super();
this.md = md;
this.digestAlgorithm = digestAlgorithm;
}
// Instance methods.
// -------------------------------------------------------------------------
public Object clone() throws CloneNotSupportedException
{
return super.clone();
}
protected Object engineGetParameter(String param)
{
throw new UnsupportedOperationException("deprecated");
}
protected void engineSetParameter(String param, Object value)
{
throw new UnsupportedOperationException("deprecated");
}
protected void engineInitSign(PrivateKey privateKey)
throws InvalidKeyException
{
if (!(privateKey instanceof RSAPrivateKey))
throw new InvalidKeyException();
verifierKey = null;
signerKey = (RSAPrivateKey) privateKey;
}
protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
throws InvalidKeyException
{
// This class does not need random bytes.
engineInitSign(privateKey);
}
protected void engineInitVerify(PublicKey publicKey)
throws InvalidKeyException
{
if (!(publicKey instanceof RSAPublicKey))
throw new InvalidKeyException();
signerKey = null;
verifierKey = (RSAPublicKey) publicKey;
}
protected void engineUpdate(byte b) throws SignatureException
{
if (signerKey == null && verifierKey == null)
throw new SignatureException("not initialized");
md.update(b);
}
protected void engineUpdate(byte[] buf, int off, int len)
throws SignatureException
{
if (signerKey == null && verifierKey == null)
throw new SignatureException("not initialized");
md.update(buf, off, len);
}
protected byte[] engineSign() throws SignatureException
{
if (signerKey == null)
throw new SignatureException("not initialized for signing");
//
// The signature will be the RSA encrypted BER representation of
// the following:
//
// DigestInfo ::= SEQUENCE {
// digestAlgorithm DigestAlgorithmIdentifier,
// digest Digest }
//
// DigestAlgorithmIdentifier ::= AlgorithmIdentifier
//
// Digest ::= OCTET STRING
//
ArrayList digestAlg = new ArrayList(2);
digestAlg.add(new DERValue(DER.OBJECT_IDENTIFIER, digestAlgorithm));
digestAlg.add(new DERValue(DER.NULL, null));
ArrayList digestInfo = new ArrayList(2);
digestInfo.add(new DERValue(DER.SEQUENCE, digestAlg));
digestInfo.add(new DERValue(DER.OCTET_STRING, md.digest()));
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
DERWriter.write(out, new DERValue(DER.SEQUENCE, digestInfo));
}
catch (IOException ioe)
{
throw new SignatureException(ioe.toString());
}
byte[] buf = out.toByteArray();
md.reset();
// k = octect length of the modulus.
int k = signerKey.getModulus().bitLength();
k = (k >>> 3) + ((k & 7) == 0 ? 0 : 1);
if (buf.length < k - 3)
{
throw new SignatureException("RSA modulus too small");
}
byte[] d = new byte[k];
// Padding type 1:
// 00 | 01 | FF | ... | FF | 00 | D
d[1] = 0x01;
for (int i = 2; i < k - buf.length - 1; i++)
d[i] = (byte) 0xFF;
System.arraycopy(buf, 0, d, k - buf.length, buf.length);
BigInteger eb = new BigInteger(d);
byte[] ed = eb.modPow(signerKey.getPrivateExponent(),
signerKey.getModulus()).toByteArray();
// Ensure output is k octets long.
if (ed.length < k)
{
byte[] b = new byte[k];
System.arraycopy(eb, 0, b, k - ed.length, ed.length);
ed = b;
}
else if (ed.length > k)
{
if (ed.length != k + 1)
{
throw new SignatureException("modPow result is larger than the modulus");
}
// Maybe an extra 00 octect.
byte[] b = new byte[k];
System.arraycopy(ed, 1, b, 0, k);
ed = b;
}
return ed;
}
protected int engineSign(byte[] out, int off, int len)
throws SignatureException
{
if (out == null || off < 0 || len < 0 || off+len > out.length)
throw new SignatureException("illegal output argument");
byte[] result = engineSign();
if (result.length > len)
throw new SignatureException("not enough space for signature");
System.arraycopy(result, 0, out, off, result.length);
return result.length;
}
protected boolean engineVerify(byte[] sig) throws SignatureException
{
if (verifierKey == null)
throw new SignatureException("not initialized for verifying");
if (sig == null)
throw new SignatureException("no signature specified");
int k = verifierKey.getModulus().bitLength();
k = (k >>> 3) + ((k & 7) == 0 ? 0 : 1);
if (sig.length != k)
throw new SignatureException("signature is the wrong size (expecting "
+ k + " bytes, got " + sig.length + ")");
BigInteger ed = new BigInteger(1, sig);
byte[] eb = ed.modPow(verifierKey.getPublicExponent(),
verifierKey.getModulus()).toByteArray();
int i = 0;
if (eb[0] == 0x00)
{
for (i = 1; i < eb.length && eb[i] == 0x00; i++);
if (i == 1)
throw new SignatureException("wrong RSA padding");
i--;
}
else if (eb[0] == 0x01)
{
for (i = 1; i < eb.length && eb[i] != 0x00; i++)
if (eb[i] != (byte) 0xFF)
throw new IllegalArgumentException("wrong RSA padding");
}
else
throw new SignatureException("wrong RSA padding type");
byte[] d = new byte[eb.length-i-1];
System.arraycopy(eb, i+1, d, 0, eb.length-i-1);
DERReader der = new DERReader(d);
try
{
DERValue val = der.read();
if (val.getTag() != DER.SEQUENCE)
throw new SignatureException("failed to parse DigestInfo");
val = der.read();
if (val.getTag() != DER.SEQUENCE)
throw new SignatureException("failed to parse DigestAlgorithmIdentifier");
boolean sequenceIsBer = val.getLength() == 0;
val = der.read();
if (val.getTag() != DER.OBJECT_IDENTIFIER)
throw new SignatureException("failed to parse object identifier");
if (!val.getValue().equals(digestAlgorithm))
throw new SignatureException("digest algorithms do not match");
val = der.read();
// We should never see parameters here, since they are never used.
if (val.getTag() != DER.NULL)
throw new SignatureException("cannot handle digest parameters");
if (sequenceIsBer)
der.skip(1); // end-of-sequence byte.
val = der.read();
if (val.getTag() != DER.OCTET_STRING)
throw new SignatureException("failed to parse Digest");
return MessageDigest.isEqual(md.digest(), (byte[]) val.getValue());
}
catch (IOException ioe)
{
throw new SignatureException(ioe.toString());
}
}
protected boolean engineVerify(byte[] sig, int off, int len)
throws SignatureException
{
if (sig == null || off < 0 || len < 0 || off+len > sig.length)
throw new SignatureException("illegal parameter");
byte[] buf = new byte[len];
System.arraycopy(sig, off, buf, 0, len);
return engineVerify(buf);
}
}
@@ -0,0 +1,181 @@
/* RSAKeyFactory.java -- RSA key factory.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactorySpi;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSAKeyFactory extends KeyFactorySpi
{
// Default constructor.
// -------------------------------------------------------------------------
// Instance methods.
// -------------------------------------------------------------------------
protected PrivateKey engineGeneratePrivate(KeySpec spec)
throws InvalidKeySpecException
{
if (spec instanceof RSAPrivateCrtKeySpec)
{
return new GnuRSAPrivateKey((RSAPrivateCrtKeySpec) spec);
}
if (spec instanceof RSAPrivateKeySpec)
{
return new GnuRSAPrivateKey(new RSAPrivateCrtKeySpec(
((RSAPrivateKeySpec) spec).getModulus(), null,
((RSAPrivateKeySpec) spec).getPrivateExponent(), null,
null, null, null, null));
}
if (spec instanceof PKCS8EncodedKeySpec)
{
EncodedKeyFactory ekf = new EncodedKeyFactory();
PrivateKey pk = ekf.engineGeneratePrivate(spec);
if (pk instanceof RSAPrivateKey)
return pk;
}
throw new InvalidKeySpecException();
}
protected PublicKey engineGeneratePublic(KeySpec spec)
throws InvalidKeySpecException
{
if (spec instanceof RSAPublicKeySpec)
{
return new GnuRSAPublicKey((RSAPublicKeySpec) spec);
}
if (spec instanceof X509EncodedKeySpec)
{
EncodedKeyFactory ekf = new EncodedKeyFactory();
PublicKey pk = ekf.engineGeneratePublic(spec);
if (pk instanceof RSAPublicKey)
return pk;
}
throw new InvalidKeySpecException();
}
protected KeySpec engineGetKeySpec(Key key, Class keySpec)
throws InvalidKeySpecException
{
if (keySpec.isAssignableFrom(RSAPrivateCrtKeySpec.class)
&& (key instanceof RSAPrivateCrtKey))
{
return new RSAPrivateCrtKeySpec(
((RSAPrivateCrtKey) key).getModulus(),
((RSAPrivateCrtKey) key).getPublicExponent(),
((RSAPrivateCrtKey) key).getPrivateExponent(),
((RSAPrivateCrtKey) key).getPrimeP(),
((RSAPrivateCrtKey) key).getPrimeQ(),
((RSAPrivateCrtKey) key).getPrimeExponentP(),
((RSAPrivateCrtKey) key).getPrimeExponentQ(),
((RSAPrivateCrtKey) key).getCrtCoefficient());
}
if (keySpec.isAssignableFrom(RSAPrivateKeySpec.class)
&& (key instanceof RSAPrivateKey))
{
return new RSAPrivateKeySpec(
((RSAPrivateCrtKey) key).getModulus(),
((RSAPrivateCrtKey) key).getPrivateExponent());
}
if (keySpec.isAssignableFrom(RSAPublicKeySpec.class)
&& (key instanceof RSAPublicKey))
{
return new RSAPublicKeySpec(
((RSAPrivateCrtKey) key).getModulus(),
((RSAPrivateCrtKey) key).getPublicExponent());
}
if (keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class)
&& key.getFormat().equalsIgnoreCase("PKCS#8"))
{
return new PKCS8EncodedKeySpec(key.getEncoded());
}
if (keySpec.isAssignableFrom(X509EncodedKeySpec.class)
&& key.getFormat().equalsIgnoreCase("X.509"))
{
return new X509EncodedKeySpec(key.getEncoded());
}
throw new InvalidKeySpecException();
}
protected Key engineTranslateKey(Key key) throws InvalidKeyException
{
if (key instanceof RSAPrivateCrtKey)
{
return new GnuRSAPrivateKey(new RSAPrivateCrtKeySpec(
((RSAPrivateCrtKey) key).getModulus(),
((RSAPrivateCrtKey) key).getPublicExponent(),
((RSAPrivateCrtKey) key).getPrivateExponent(),
((RSAPrivateCrtKey) key).getPrimeP(),
((RSAPrivateCrtKey) key).getPrimeQ(),
((RSAPrivateCrtKey) key).getPrimeExponentP(),
((RSAPrivateCrtKey) key).getPrimeExponentQ(),
((RSAPrivateCrtKey) key).getCrtCoefficient()));
}
if (key instanceof RSAPrivateKey)
{
return new GnuRSAPrivateKey(new RSAPrivateCrtKeySpec(
((RSAPrivateKey) key).getModulus(), null,
((RSAPrivateKey) key).getPrivateExponent(), null,
null, null, null, null));
}
if (key instanceof RSAPublicKey)
{
return new GnuRSAPublicKey(new RSAPublicKeySpec(
((RSAPrivateCrtKey) key).getModulus(),
((RSAPrivateCrtKey) key).getPublicExponent()));
}
throw new InvalidKeyException();
}
}
@@ -0,0 +1,242 @@
/* SHA.java -- Class implementing the SHA-1 algorithm as specified in [1].
Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.security.MessageDigest;
/**
This class implements the SHA-1 algorithm as described in [1].
[1] Federal Information Processing Standards Publication 180-1.
Specifications for the Secure Hash Standard. April 17, 1995.
@see java.security.MessageDigest
*/
public class SHA extends MessageDigest implements Cloneable
{
public SHA ()
{
super("SHA");
engineReset ();
}
public int engineGetDigestLength()
{
return 20;
}
public void engineUpdate (byte b)
{
int i = ((int)bytecount) & 0x3f; //wgs
int shift = (3 - i % 4) << 3;
int idx = i / 4;
i = (int)b;
W[idx] = (W[idx] & ~(0xff << shift)) | ((i & 0xff) << shift);
// if we've filled up a block, then process it
if (((++bytecount) & 0x3f) == 0)
munch ();
}
// This could be optimized.
public void engineUpdate (byte bytes[], int off, int len)
{
if (len < 0)
throw new ArrayIndexOutOfBoundsException ();
int end = off + len;
while (off < end)
engineUpdate (bytes[off++]);
}
public void engineReset ()
{
bytecount = 0;
// magic numbers from [1] p. 10.
H0 = 0x67452301;
H1 = 0xefcdab89;
H2 = 0x98badcfe;
H3 = 0x10325476;
H4 = 0xc3d2e1f0;
}
public byte[] engineDigest ()
{
long bitcount = bytecount << 3;
engineUpdate ((byte)0x80); // 10000000 in binary; the start of the padding
// add the rest of the padding to fill this block out, but leave 8
// bytes to put in the original bytecount
while ((bytecount & 0x3f) != 56)
engineUpdate ((byte)0);
// add the length of the original, unpadded block to the end of
// the padding
W[14] = (int)(bitcount >>> 32);
W[15] = (int)bitcount;
bytecount += 8;
// digest the fully padded block
munch ();
byte[] result
= new byte[] {(byte)(H0 >>> 24), (byte)(H0 >>> 16),
(byte)(H0 >>> 8), (byte)H0,
(byte)(H1 >>> 24), (byte)(H1 >>> 16),
(byte)(H1 >>> 8), (byte)H1,
(byte)(H2 >>> 24), (byte)(H2 >>> 16),
(byte)(H2 >>> 8), (byte)H2,
(byte)(H3 >>> 24), (byte)(H3 >>> 16),
(byte)(H3 >>> 8), (byte)H3,
(byte)(H4 >>> 24), (byte)(H4 >>> 16),
(byte)(H4 >>> 8), (byte)H4};
engineReset ();
return result;
}
// Process a single block. This is pretty much copied verbatim from
// [1] pp. 9, 10.
private void munch ()
{
for (int t = 16; t < 80; ++ t)
{
int Wt = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
W[t] = Wt << 1 | Wt >>> 31;
}
int A = H0;
int B = H1;
int C = H2;
int D = H3;
int E = H4;
for (int t = 0; t < 20; ++ t)
{
int TEMP = (A << 5 | A >>> 27) // S^5(A)
+ ((B & C) | (~B & D)) // f_t(B,C,D)
+ E + W[t]
+ 0x5a827999; // K_t
E = D;
D = C;
C = B << 30 | B >>> 2; // S^30(B)
B = A;
A = TEMP;
}
for (int t = 20; t < 40; ++ t)
{
int TEMP = (A << 5 | A >>> 27) // S^5(A)
+ (B ^ C ^ D) // f_t(B,C,D)
+ E + W[t]
+ 0x6ed9eba1; // K_t
E = D;
D = C;
C = B << 30 | B >>> 2; // S^30(B)
B = A;
A = TEMP;
}
for (int t = 40; t < 60; ++ t)
{
int TEMP = (A << 5 | A >>> 27) // S^5(A)
+ (B & C | B & D | C & D) // f_t(B,C,D)
+ E + W[t]
+ 0x8f1bbcdc; // K_t
E = D;
D = C;
C = B << 30 | B >>> 2; // S^30(B)
B = A;
A = TEMP;
}
for (int t = 60; t < 80; ++ t)
{
int TEMP = (A << 5 | A >>> 27) // S^5(A)
+ (B ^ C ^ D) // f_t(B,C,D)
+ E + W[t]
+ 0xca62c1d6; // K_t
E = D;
D = C;
C = B << 30 | B >>> 2; // S^30(B)
B = A;
A = TEMP;
}
H0 += A;
H1 += B;
H2 += C;
H3 += D;
H4 += E;
// Reset W by clearing it.
for (int t = 0; t < 80; ++ t)
W[t] = 0;
}
public Object clone ()
{
return new SHA (this);
}
private SHA (SHA copy)
{
this ();
bytecount = copy.bytecount;
H0 = copy.H0;
H1 = copy.H1;
H2 = copy.H2;
H3 = copy.H3;
H4 = copy.H4;
System.arraycopy (copy.W, 0, W, 0, 80);
}
private final int W[] = new int[80];
private long bytecount;
private int H0;
private int H1;
private int H2;
private int H3;
private int H4;
}
@@ -0,0 +1,137 @@
/* SHA1PRNG.java --- Secure Random SPI SHA1PRNG
Copyright (C) 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandomSpi;
import java.util.Random;
public class SHA1PRNG extends SecureRandomSpi implements Serializable
{
MessageDigest digest;
byte seed[];
byte data[];
int seedpos;
int datapos;
private boolean seeded = false; // set to true when we seed this
/**
* The size of seed.
*/
private static final int SEED_SIZE = 20;
/**
* The size of data.
*/
private static final int DATA_SIZE = 40;
/**
* Create a new SHA-1 pseudo-random number generator.
*/
public SHA1PRNG()
{
try {
digest = MessageDigest.getInstance("SHA");
} catch ( NoSuchAlgorithmException nsae) {
// System.out.println("Failed to find SHA Message Digest: " + nsae);
// nsae.printStackTrace();
throw new InternalError ("no SHA implementation found");
}
seed = new byte[SEED_SIZE];
seedpos = 0;
data = new byte[DATA_SIZE];
datapos = SEED_SIZE; // try to force hashing a first block
}
public void engineSetSeed(byte[] seed)
{
for(int i = 0; i < seed.length; i++)
this.seed[seedpos++ % SEED_SIZE] ^= seed[i];
seedpos %= SEED_SIZE;
}
public void engineNextBytes(byte[] bytes)
{
ensureIsSeeded ();
int loc = 0;
while (loc < bytes.length)
{
int copy = Math.min (bytes.length - loc, SEED_SIZE - datapos);
if (copy > 0)
{
System.arraycopy (data, datapos, bytes, loc, copy);
datapos += copy;
loc += copy;
}
else
{
// No data ready for copying, so refill our buffer.
System.arraycopy( seed, 0, data, SEED_SIZE, SEED_SIZE);
byte[] digestdata = digest.digest( data );
System.arraycopy( digestdata, 0, data, 0, SEED_SIZE);
datapos = 0;
}
}
}
public byte[] engineGenerateSeed(int numBytes)
{
byte tmp[] = new byte[numBytes];
engineNextBytes( tmp );
return tmp;
}
private void ensureIsSeeded()
{
if (!seeded)
{
new Random(0L).nextBytes(seed);
byte[] digestdata = digest.digest(data);
System.arraycopy(digestdata, 0, data, 0, SEED_SIZE);
seeded = true;
}
}
}
@@ -0,0 +1,61 @@
/* SHA1withRSA.java -- SHA-1 with RSA encryption signatures.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.OID;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SHA1withRSA extends RSA
{
// Constant.
// -------------------------------------------------------------------------
private static final OID SHA1 = new OID("1.3.14.3.2.26");
// Constructor.
// -------------------------------------------------------------------------
public SHA1withRSA() throws NoSuchAlgorithmException
{
super(MessageDigest.getInstance("SHA-160"), SHA1);
}
}
@@ -0,0 +1,305 @@
/* X509CertificateFactory.java -- generates X.509 certificates.
Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.io.Base64InputStream;
import gnu.java.security.x509.X509CRL;
import gnu.java.security.x509.X509CertPath;
import gnu.java.security.x509.X509Certificate;
import java.io.BufferedInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.CRL;
import java.security.cert.CRLException;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactorySpi;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class X509CertificateFactory extends CertificateFactorySpi
{
// Constants.
// ------------------------------------------------------------------------
public static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----";
public static final String END_CERTIFICATE = "-----END CERTIFICATE-----";
public static final String BEGIN_X509_CRL = "-----BEGIN X509 CRL-----";
public static final String END_X509_CRL = "-----END X509 CRL-----";
// Constructors.
// ------------------------------------------------------------------------
public X509CertificateFactory()
{
super();
}
// Instance methods.
// ------------------------------------------------------------------------
public Certificate engineGenerateCertificate(InputStream inStream)
throws CertificateException
{
try
{
return generateCert(inStream);
}
catch (IOException ioe)
{
CertificateException ce = new CertificateException(ioe.getMessage());
ce.initCause (ioe);
throw ce;
}
}
public Collection engineGenerateCertificates(InputStream inStream)
throws CertificateException
{
LinkedList certs = new LinkedList();
while (true)
{
try
{
certs.add(generateCert(inStream));
}
catch (EOFException eof)
{
break;
}
catch (IOException ioe)
{
CertificateException ce = new CertificateException(ioe.getMessage());
ce.initCause (ioe);
throw ce;
}
}
return certs;
}
public CRL engineGenerateCRL(InputStream inStream) throws CRLException
{
try
{
return generateCRL(inStream);
}
catch (IOException ioe)
{
CRLException crle = new CRLException(ioe.getMessage());
crle.initCause (ioe);
throw crle;
}
}
public Collection engineGenerateCRLs(InputStream inStream)
throws CRLException
{
LinkedList crls = new LinkedList();
while (true)
{
try
{
crls.add(generateCRL(inStream));
}
catch (EOFException eof)
{
break;
}
catch (IOException ioe)
{
CRLException crle = new CRLException(ioe.getMessage());
crle.initCause (ioe);
throw crle;
}
}
return crls;
}
public CertPath engineGenerateCertPath(List certs)
{
return new X509CertPath(certs);
}
public CertPath engineGenerateCertPath(InputStream in)
throws CertificateEncodingException
{
return new X509CertPath(in);
}
public CertPath engineGenerateCertPath(InputStream in, String encoding)
throws CertificateEncodingException
{
return new X509CertPath(in, encoding);
}
public Iterator engineGetCertPathEncodings()
{
return X509CertPath.ENCODINGS.iterator();
}
// Own methods.
// ------------------------------------------------------------------------
private X509Certificate generateCert(InputStream inStream)
throws IOException, CertificateException
{
if (inStream == null)
throw new CertificateException("missing input stream");
if (!inStream.markSupported())
inStream = new BufferedInputStream(inStream, 8192);
inStream.mark(20);
int i = inStream.read();
if (i == -1)
throw new EOFException();
// If the input is in binary DER format, the first byte MUST be
// 0x30, which stands for the ASN.1 [UNIVERSAL 16], which is the
// UNIVERSAL SEQUENCE, with the CONSTRUCTED bit (0x20) set.
//
// So if we do not see 0x30 here we will assume it is in Base-64.
if (i != 0x30)
{
inStream.reset();
StringBuffer line = new StringBuffer(80);
do
{
line.setLength(0);
do
{
i = inStream.read();
if (i == -1)
throw new EOFException();
if (i != '\n' && i != '\r')
line.append((char) i);
}
while (i != '\n' && i != '\r');
}
while (!line.toString().equals(BEGIN_CERTIFICATE));
X509Certificate ret = new X509Certificate(
new BufferedInputStream(new Base64InputStream(inStream), 8192));
line.setLength(0);
line.append('-'); // Base64InputStream will eat this.
do
{
i = inStream.read();
if (i == -1)
throw new EOFException();
if (i != '\n' && i != '\r')
line.append((char) i);
}
while (i != '\n' && i != '\r');
// XXX ???
if (!line.toString().equals(END_CERTIFICATE))
throw new CertificateException("no end-of-certificate marker");
return ret;
}
else
{
inStream.reset();
return new X509Certificate(inStream);
}
}
private X509CRL generateCRL(InputStream inStream)
throws IOException, CRLException
{
if (inStream == null)
throw new CRLException("missing input stream");
if (!inStream.markSupported())
inStream = new BufferedInputStream(inStream, 8192);
inStream.mark(20);
int i = inStream.read();
if (i == -1)
throw new EOFException();
// If the input is in binary DER format, the first byte MUST be
// 0x30, which stands for the ASN.1 [UNIVERSAL 16], which is the
// UNIVERSAL SEQUENCE, with the CONSTRUCTED bit (0x20) set.
//
// So if we do not see 0x30 here we will assume it is in Base-64.
if (i != 0x30)
{
inStream.reset();
StringBuffer line = new StringBuffer(80);
do
{
line.setLength(0);
do
{
i = inStream.read();
if (i == -1)
throw new EOFException();
if (i != '\n' && i != '\r')
line.append((char) i);
}
while (i != '\n' && i != '\r');
}
while (!line.toString().startsWith(BEGIN_X509_CRL));
X509CRL ret = new X509CRL(
new BufferedInputStream(new Base64InputStream(inStream), 8192));
line.setLength(0);
line.append('-'); // Base64InputStream will eat this.
do
{
i = inStream.read();
if (i == -1)
throw new EOFException();
if (i != '\n' && i != '\r')
line.append((char) i);
}
while (i != '\n' && i != '\r');
// XXX ???
if (!line.toString().startsWith(END_X509_CRL))
throw new CRLException("no end-of-CRL marker");
return ret;
}
else
{
inStream.reset();
return new X509CRL(inStream);
}
}
}
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in gnu.java.security.provider package.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - gnu.java.security.provider</title></head>
<body>
<p></p>
</body>
</html>
@@ -0,0 +1,164 @@
/* Prime.java --- Prime number generation utilities
Copyright (C) 1999, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.util;
import java.math.BigInteger;
import java.util.Random;
//import java.security.SecureRandom;
public final class Prime
{
/*
See IEEE P1363 A.15.4 (10/05/98 Draft)
*/
public static BigInteger generateRandomPrime( int pmin, int pmax, BigInteger f )
{
BigInteger d;
//Step 1 - generate prime
BigInteger p = new BigInteger( (pmax + pmin)/2, new Random() );
if( p.compareTo( BigInteger.valueOf( 1 ).shiftLeft( pmin ) ) <= 0 )
{
p = p.add( BigInteger.valueOf( 1 ).shiftLeft( pmin ).subtract( p ) );
}
//Step 2 - test for even
if( p.mod( BigInteger.valueOf(2) ).compareTo( BigInteger.valueOf( 0 )) == 0)
p = p.add( BigInteger.valueOf( 1 ) );
for(;;)
{
//Step 3
if( p.compareTo( BigInteger.valueOf( 1 ).shiftLeft( pmax)) > 0)
{
//Step 3.1
p = p.subtract( BigInteger.valueOf( 1 ).shiftLeft( pmax) );
p = p.add( BigInteger.valueOf( 1 ).shiftLeft( pmin) );
p = p.subtract( BigInteger.valueOf( 1 ) );
//Step 3.2
// put step 2 code here so looping code is cleaner
//Step 2 - test for even
if( p.mod( BigInteger.valueOf(2) ).compareTo( BigInteger.valueOf( 0 )) == 0)
p = p.add( BigInteger.valueOf( 1 ) );
continue;
}
//Step 4 - compute GCD
d = p.subtract( BigInteger.valueOf(1) );
d = d.gcd( f );
//Step 5 - test d
if( d.compareTo( BigInteger.valueOf( 1 ) ) == 0)
{
//Step 5.1 - test primality
if( p.isProbablePrime( 1 ) == true )
{
//Step 5.2;
return p;
}
}
//Step 6
p = p.add( BigInteger.valueOf( 2 ) );
//Step 7
}
}
/*
See IEEE P1363 A.15.5 (10/05/98 Draft)
*/
public static BigInteger generateRandomPrime( BigInteger r, BigInteger a, int pmin, int pmax, BigInteger f )
{
BigInteger d, w;
//Step 1 - generate prime
BigInteger p = new BigInteger( (pmax + pmin)/2, new Random() );
steptwo:{ //Step 2
w = p.mod( r.multiply( BigInteger.valueOf(2) ));
//Step 3
p = p.add( r.multiply( BigInteger.valueOf(2) ) );
p = p.subtract( w );
p = p.add(a);
//Step 4 - test for even
if( p.mod( BigInteger.valueOf(2) ).compareTo( BigInteger.valueOf( 0 )) == 0)
p = p.add( r );
for(;;)
{
//Step 5
if( p.compareTo( BigInteger.valueOf( 1 ).shiftLeft( pmax)) > 0)
{
//Step 5.1
p = p.subtract( BigInteger.valueOf( 1 ).shiftLeft( pmax) );
p = p.add( BigInteger.valueOf( 1 ).shiftLeft( pmin) );
p = p.subtract( BigInteger.valueOf( 1 ) );
//Step 5.2 - goto to Step 2
break steptwo;
}
//Step 6
d = p.subtract( BigInteger.valueOf(1) );
d = d.gcd( f );
//Step 7 - test d
if( d.compareTo( BigInteger.valueOf( 1 ) ) == 0)
{
//Step 7.1 - test primality
if( p.isProbablePrime( 1 ) == true )
{
//Step 7.2;
return p;
}
}
//Step 8
p = p.add( r.multiply( BigInteger.valueOf(2) ) );
//Step 9
}
}
//Should never reach here but makes the compiler happy
return BigInteger.valueOf(0);
}
}
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in gnu.java.security.util package.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - gnu.java.security.util</title></head>
<body>
<p></p>
</body>
</html>
@@ -0,0 +1,59 @@
/* GnuPKIExtension.java -- interface for GNU PKI extensions.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509;
import gnu.java.security.OID;
import gnu.java.security.x509.ext.Extension;
import java.security.cert.X509Extension;
import java.util.Collection;
public interface GnuPKIExtension extends X509Extension
{
/**
* Returns the extension object for the given object identifier.
*
* @param oid The OID of the extension to get.
* @return The extension, or null if there is no such extension.
*/
Extension getExtension(OID oid);
Collection getExtensions();
}
@@ -0,0 +1,214 @@
/* PolicyNodeImpl.java -- An implementation of a policy tree node.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509;
import java.security.cert.PolicyNode;
import java.security.cert.PolicyQualifierInfo;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public final class PolicyNodeImpl implements PolicyNode
{
// Fields.
// -------------------------------------------------------------------------
private String policy;
private final Set expectedPolicies;
private final Set qualifiers;
private final Set children;
private PolicyNodeImpl parent;
private int depth;
private boolean critical;
private boolean readOnly;
// Constructors.
// -------------------------------------------------------------------------
public PolicyNodeImpl()
{
expectedPolicies = new HashSet();
qualifiers = new HashSet();
children = new HashSet();
readOnly = false;
critical = false;
}
// Instance methods.
// -------------------------------------------------------------------------
public void addChild(PolicyNodeImpl node)
{
if (readOnly)
throw new IllegalStateException("read only");
if (node.getParent() != null)
throw new IllegalStateException("already a child node");
node.parent = this;
node.setDepth(depth + 1);
children.add(node);
}
public Iterator getChildren()
{
return Collections.unmodifiableSet(children).iterator();
}
public int getDepth()
{
return depth;
}
public void setDepth(int depth)
{
if (readOnly)
throw new IllegalStateException("read only");
this.depth = depth;
}
public void addAllExpectedPolicies(Set policies)
{
if (readOnly)
throw new IllegalStateException("read only");
expectedPolicies.addAll(policies);
}
public void addExpectedPolicy(String policy)
{
if (readOnly)
throw new IllegalStateException("read only");
expectedPolicies.add(policy);
}
public Set getExpectedPolicies()
{
return Collections.unmodifiableSet(expectedPolicies);
}
public PolicyNode getParent()
{
return parent;
}
public void addAllPolicyQualifiers (Collection qualifiers)
{
for (Iterator it = qualifiers.iterator(); it.hasNext(); )
{
if (!(it.next() instanceof PolicyQualifierInfo))
throw new IllegalArgumentException ("can only add PolicyQualifierInfos");
}
qualifiers.addAll (qualifiers);
}
public void addPolicyQualifier (PolicyQualifierInfo qualifier)
{
if (readOnly)
throw new IllegalStateException("read only");
qualifiers.add(qualifier);
}
public Set getPolicyQualifiers()
{
return Collections.unmodifiableSet(qualifiers);
}
public String getValidPolicy()
{
return policy;
}
public void setValidPolicy(String policy)
{
if (readOnly)
throw new IllegalStateException("read only");
this.policy = policy;
}
public boolean isCritical()
{
return critical;
}
public void setCritical(boolean critical)
{
if (readOnly)
throw new IllegalStateException("read only");
this.critical = critical;
}
public void setReadOnly()
{
if (readOnly)
return;
readOnly = true;
for (Iterator it = getChildren(); it.hasNext(); )
((PolicyNodeImpl) it.next()).setReadOnly();
}
public String toString()
{
StringBuffer buf = new StringBuffer();
for (int i = 0; i < depth; i++)
buf.append(" ");
buf.append("(");
buf.append(PolicyNodeImpl.class.getName());
buf.append(" (oid ");
buf.append(policy);
buf.append(") (depth ");
buf.append(depth);
buf.append(") (qualifiers ");
buf.append(qualifiers);
buf.append(") (critical ");
buf.append(critical);
buf.append(") (expectedPolicies ");
buf.append(expectedPolicies);
buf.append(") (children (");
final String nl = System.getProperty("line.separator");
for (Iterator it = getChildren(); it.hasNext(); )
{
buf.append(nl);
buf.append(it.next().toString());
}
buf.append(")))");
return buf.toString();
}
}
@@ -0,0 +1,202 @@
/* Util.java -- Miscellaneous utility methods.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509;
/**
* A collection of useful class methods.
*
* @author Casey Marshall (rsdio@metastatic.org)
*/
public final class Util
{
// Constants.
// -------------------------------------------------------------------------
public static final String HEX = "0123456789abcdef";
// Class methods.
// -------------------------------------------------------------------------
/**
* Convert a byte array to a hexadecimal string, as though it were a
* big-endian arbitrarily-sized integer.
*
* @param buf The bytes to format.
* @param off The offset to start at.
* @param len The number of bytes to format.
* @return A hexadecimal representation of the specified bytes.
*/
public static String toHexString(byte[] buf, int off, int len)
{
StringBuffer str = new StringBuffer();
for (int i = 0; i < len; i++)
{
str.append(HEX.charAt(buf[i+off] >>> 4 & 0x0F));
str.append(HEX.charAt(buf[i+off] & 0x0F));
}
return str.toString();
}
/**
* See {@link #toHexString(byte[],int,int)}.
*/
public static String toHexString(byte[] buf)
{
return Util.toHexString(buf, 0, buf.length);
}
/**
* Convert a byte array to a hexadecimal string, separating octets
* with the given character.
*
* @param buf The bytes to format.
* @param off The offset to start at.
* @param len The number of bytes to format.
* @param sep The character to insert between octets.
* @return A hexadecimal representation of the specified bytes.
*/
public static String toHexString(byte[] buf, int off, int len, char sep)
{
StringBuffer str = new StringBuffer();
for (int i = 0; i < len; i++)
{
str.append(HEX.charAt(buf[i+off] >>> 4 & 0x0F));
str.append(HEX.charAt(buf[i+off] & 0x0F));
if (i < len - 1)
str.append(sep);
}
return str.toString();
}
/**
* See {@link #toHexString(byte[],int,int,char)}.
*/
public static String toHexString(byte[] buf, char sep)
{
return Util.toHexString(buf, 0, buf.length, sep);
}
/**
* Create a representation of the given byte array similar to the
* output of `hexdump -C', which is
*
* <p><pre>OFFSET SIXTEEN-BYTES-IN-HEX PRINTABLE-BYTES</pre>
*
* <p>The printable bytes show up as-is if they are printable and
* not a newline character, otherwise showing as '.'.
*
* @param buf The bytes to format.
* @param off The offset to start at.
* @param len The number of bytes to encode.
* @return The formatted string.
*/
public static String hexDump(byte[] buf, int off, int len, String prefix)
{
String nl = System.getProperty("line.separator");
StringBuffer str = new StringBuffer();
int i = 0;
while (i < len)
{
str.append(prefix);
str.append(Util.formatInt(i+off, 16, 8));
str.append(" ");
String s = Util.toHexString(buf, i+off, Math.min(16, len-i), ' ');
str.append(s);
for (int j = 56 - (56 - s.length()); j < 56; j++)
str.append(" ");
for (int j = 0; j < Math.min(16, len - i); j++)
{
if ((buf[i+off+j] & 0xFF) < 0x20 || (buf[i+off+j] & 0xFF) > 0x7E)
str.append('.');
else
str.append((char) (buf[i+off+j] & 0xFF));
}
str.append(nl);
i += 16;
}
return str.toString();
}
/**
* See {@link #hexDump(byte[],int,int)}.
*/
public static String hexDump(byte[] buf, String prefix)
{
return hexDump(buf, 0, buf.length, prefix);
}
/**
* Format an integer into the specified radix, zero-filled.
*
* @param i The integer to format.
* @param radix The radix to encode to.
* @param len The target length of the string. The string is
* zero-padded to this length, but may be longer.
* @return The formatted integer.
*/
public static String formatInt(int i, int radix, int len)
{
String s = Integer.toString(i, radix);
StringBuffer buf = new StringBuffer();
for (int j = 0; j < len - s.length(); j++)
buf.append("0");
buf.append(s);
return buf.toString();
}
/**
* Convert a hexadecimal string into its byte representation.
*
* @param hex The hexadecimal string.
* @return The converted bytes.
*/
public static byte[] toByteArray(String hex)
{
hex = hex.toLowerCase();
byte[] buf = new byte[hex.length() / 2];
int j = 0;
for (int i = 0; i < buf.length; i++)
{
buf[i] = (byte) ((Character.digit(hex.charAt(j++), 16) << 4) |
Character.digit(hex.charAt(j++), 16));
}
return buf;
}
}
@@ -0,0 +1,548 @@
/* X500DistinguishedName.java -- X.500 distinguished name.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class X500DistinguishedName implements Principal
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID CN = new OID("2.5.4.3");
public static final OID C = new OID("2.5.4.6");
public static final OID L = new OID("2.5.4.7");
public static final OID ST = new OID("2.5.4.8");
public static final OID STREET = new OID("2.5.4.9");
public static final OID O = new OID("2.5.4.10");
public static final OID OU = new OID("2.5.4.11");
public static final OID T = new OID("2.5.4.12");
public static final OID DNQ = new OID("2.5.4.46");
public static final OID NAME = new OID("2.5.4.41");
public static final OID GIVENNAME = new OID("2.5.4.42");
public static final OID INITIALS = new OID("2.5.4.43");
public static final OID GENERATION = new OID("2.5.4.44");
public static final OID EMAIL = new OID("1.2.840.113549.1.9.1");
public static final OID DC = new OID("0.9.2342.19200300.100.1.25");
public static final OID UID = new OID("0.9.2342.19200300.100.1.1");
private List components;
private Map currentRdn;
private boolean fixed;
private String stringRep;
private byte[] encoded;
// Constructors.
// -------------------------------------------------------------------------
public X500DistinguishedName()
{
components = new LinkedList();
currentRdn = new LinkedHashMap();
components.add(currentRdn);
}
public X500DistinguishedName(String name)
{
this();
try
{
parseString(name);
}
catch (IOException ioe)
{
throw new IllegalArgumentException(ioe.toString());
}
}
public X500DistinguishedName(byte[] encoded) throws IOException
{
this();
parseDer(new DERReader(encoded));
}
public X500DistinguishedName(InputStream encoded) throws IOException
{
this();
parseDer(new DERReader(encoded));
}
// Instance methods.
// -------------------------------------------------------------------------
public String getName()
{
return toString();
}
public void newRelativeDistinguishedName()
{
if (fixed || currentRdn.isEmpty()) return;
currentRdn = new LinkedHashMap();
components.add(currentRdn);
}
public int size()
{
return components.size();
}
public int countComponents()
{
int count = 0;
for (Iterator it = components.iterator(); it.hasNext(); )
{
count += ((Map) it.next()).size();
}
return count;
}
public boolean containsComponent(OID oid, String value)
{
for (Iterator it = components.iterator(); it.hasNext(); )
{
Map rdn = (Map) it.next();
String s = (String) rdn.get(oid);
if (s == null)
continue;
if (compressWS(value).equalsIgnoreCase(compressWS(s)))
return true;
}
return false;
}
public String getComponent(OID oid)
{
for (Iterator it = components.iterator(); it.hasNext(); )
{
Map rdn = (Map) it.next();
if (rdn.containsKey(oid))
return (String) rdn.get(oid);
}
return null;
}
public String getComponent(OID oid, int rdn)
{
if (rdn >= size())
return null;
return (String) ((Map) components.get(rdn)).get(oid);
}
public void putComponent(OID oid, String value)
{
currentRdn.put(oid, value);
}
public void putComponent(String name, String value)
{
name = name.trim().toLowerCase();
if (name.equals("cn"))
putComponent(CN, value);
else if (name.equals("c"))
putComponent(C, value);
else if (name.equals("l"))
putComponent(L, value);
else if (name.equals("street"))
putComponent(STREET, value);
else if (name.equals("st"))
putComponent(ST, value);
else if (name.equals("t"))
putComponent(T, value);
else if (name.equals("dnq"))
putComponent(DNQ, value);
else if (name.equals("name"))
putComponent(NAME, value);
else if (name.equals("givenname"))
putComponent(GIVENNAME, value);
else if (name.equals("initials"))
putComponent(INITIALS, value);
else if (name.equals("generation"))
putComponent(GENERATION, value);
else if (name.equals("email"))
putComponent(EMAIL, value);
else if (name.equals("dc"))
putComponent(DC, value);
else if (name.equals("uid"))
putComponent(UID, value);
else
putComponent(new OID(name), value);
}
public void setUnmodifiable()
{
if (fixed) return;
fixed = true;
List newComps = new ArrayList(components.size());
for (Iterator it = components.iterator(); it.hasNext(); )
{
Map rdn = (Map) it.next();
rdn = Collections.unmodifiableMap(rdn);
newComps.add(rdn);
}
components = Collections.unmodifiableList(newComps);
currentRdn = Collections.EMPTY_MAP;
}
public int hashCode()
{
int sum = 0;
for (Iterator it = components.iterator(); it.hasNext(); )
{
Map m = (Map) it.next();
for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); )
{
Map.Entry e = (Map.Entry) it2.next();
sum += e.getKey().hashCode();
sum += e.getValue().hashCode();
}
}
return sum;
}
public boolean equals(Object o)
{
if (!(o instanceof X500DistinguishedName))
return false;
if (size() != ((X500DistinguishedName) o).size())
return false;
for (int i = 0; i < size(); i++)
{
Map m = (Map) components.get(i);
for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); )
{
Map.Entry e = (Map.Entry) it2.next();
OID oid = (OID) e.getKey();
String v1 = (String) e.getValue();
String v2 = ((X500DistinguishedName) o).getComponent(oid, i);
if (!compressWS(v1).equalsIgnoreCase(compressWS(v2)))
return false;
}
}
return true;
}
public String toString()
{
if (fixed && stringRep != null)
return stringRep;
StringBuffer str = new StringBuffer();
for (Iterator it = components.iterator(); it.hasNext(); )
{
Map m = (Map) it.next();
for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); )
{
Map.Entry entry = (Map.Entry) it2.next();
OID oid = (OID) entry.getKey();
String value = (String) entry.getValue();
if (oid.equals(CN))
str.append("CN");
else if (oid.equals(C))
str.append("C");
else if (oid.equals(L))
str.append("L");
else if (oid.equals(ST))
str.append("ST");
else if (oid.equals(STREET))
str.append("STREET");
else if (oid.equals(O))
str.append("O");
else if (oid.equals(OU))
str.append("OU");
else if (oid.equals(T))
str.append("T");
else if (oid.equals(DNQ))
str.append("DNQ");
else if (oid.equals(NAME))
str.append("NAME");
else
str.append(oid.toString());
str.append('=');
str.append(value);
if (it2.hasNext())
str.append("+");
}
if (it.hasNext())
str.append(',');
}
return (stringRep = str.toString());
}
public byte[] getDer()
{
if (fixed && encoded != null)
return (byte[]) encoded.clone();
ArrayList name = new ArrayList(components.size());
for (Iterator it = components.iterator(); it.hasNext(); )
{
Map m = (Map) it.next();
if (m.isEmpty())
continue;
Set rdn = new HashSet();
for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); )
{
Map.Entry e = (Map.Entry) it.next();
ArrayList atav = new ArrayList(2);
atav.add(new DERValue(DER.OBJECT_IDENTIFIER, e.getKey()));
atav.add(new DERValue(DER.UTF8_STRING, e.getValue()));
rdn.add(new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, atav));
}
name.add(new DERValue(DER.SET|DER.CONSTRUCTED, rdn));
}
DERValue val = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, name);
return (byte[]) (encoded = val.getEncoded()).clone();
}
// Own methods.
// -------------------------------------------------------------------------
private int sep;
private void parseString(String str) throws IOException
{
Reader in = new StringReader(str);
while (true)
{
String key = readAttributeType(in);
if (key == null)
break;
String value = readAttributeValue(in);
putComponent(key, value);
if (sep == ',')
newRelativeDistinguishedName();
}
setUnmodifiable();
}
private String readAttributeType(Reader in) throws IOException
{
StringBuffer buf = new StringBuffer();
int ch;
while ((ch = in.read()) != '=')
{
if (ch == -1)
{
if (buf.length() > 0)
throw new EOFException();
return null;
}
if (ch > 127)
throw new IOException("Invalid char: " + (char) ch);
if (Character.isLetterOrDigit((char) ch) || ch == '-' || ch == '.')
buf.append((char) ch);
else
throw new IOException("Invalid char: " + (char) ch);
}
return buf.toString();
}
private String readAttributeValue(Reader in) throws IOException
{
StringBuffer buf = new StringBuffer();
int ch = in.read();
if (ch == '#')
{
while (true)
{
ch = in.read();
if (('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
|| Character.isDigit((char) ch))
buf.append((char) ch);
else if (ch == '+' || ch == ',')
{
sep = ch;
String hex = buf.toString();
return new String(Util.toByteArray(hex));
}
else
throw new IOException("illegal character: " + (char) ch);
}
}
else if (ch == '"')
{
while (true)
{
ch = in.read();
if (ch == '"')
break;
else if (ch == '\\')
{
ch = in.read();
if (ch == -1)
throw new EOFException();
if (('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
|| Character.isDigit((char) ch))
{
int i = Character.digit((char) ch, 16) << 4;
ch = in.read();
if (!(('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
|| Character.isDigit((char) ch)))
throw new IOException("illegal hex char");
i |= Character.digit((char) ch, 16);
buf.append((char) i);
}
else
buf.append((char) ch);
}
else
buf.append((char) ch);
}
sep = in.read();
if (sep != '+' || sep != ',')
throw new IOException("illegal character: " + (char) ch);
return buf.toString();
}
else
{
while (true)
{
switch (ch)
{
case '+':
case ',':
sep = ch;
return buf.toString();
case '\\':
ch = in.read();
if (ch == -1)
throw new EOFException();
if (('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
|| Character.isDigit((char) ch))
{
int i = Character.digit((char) ch, 16) << 4;
ch = in.read();
if (!(('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
|| Character.isDigit((char) ch)))
throw new IOException("illegal hex char");
i |= Character.digit((char) ch, 16);
buf.append((char) i);
}
else
buf.append((char) ch);
break;
case '=':
case '<':
case '>':
case '#':
case ';':
throw new IOException("illegal character: " + (char) ch);
case -1:
throw new EOFException();
default:
buf.append((char) ch);
}
}
}
}
private void parseDer(DERReader der) throws IOException
{
DERValue name = der.read();
if (!name.isConstructed())
throw new IOException("malformed Name");
encoded = name.getEncoded();
int len = 0;
while (len < name.getLength())
{
DERValue rdn = der.read();
if (!rdn.isConstructed())
throw new IOException("badly formed RDNSequence");
int len2 = 0;
while (len2 < rdn.getLength())
{
DERValue atav = der.read();
if (!atav.isConstructed())
throw new IOException("badly formed AttributeTypeAndValue");
DERValue val = der.read();
if (val.getTag() != DER.OBJECT_IDENTIFIER)
throw new IOException("badly formed AttributeTypeAndValue");
OID oid = (OID) val.getValue();
val = der.read();
if (!(val.getValue() instanceof String))
throw new IOException("badly formed AttributeTypeAndValue");
String value = (String) val.getValue();
putComponent(oid, value);
len2 += atav.getEncodedLength();
}
len += rdn.getEncodedLength();
if (len < name.getLength())
newRelativeDistinguishedName();
}
setUnmodifiable();
}
private static String compressWS(String str)
{
StringBuffer buf = new StringBuffer();
char lastChar = 0;
for (int i = 0; i < str.length(); i++)
{
char c = str.charAt(i);
if (Character.isWhitespace(c))
{
if (!Character.isWhitespace(lastChar))
buf.append(' ');
}
else
buf.append(c);
lastChar = c;
}
return buf.toString().trim();
}
}
@@ -0,0 +1,476 @@
/* X509CRL.java -- X.509 certificate revocation list.
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509;
import gnu.java.security.OID;
import gnu.java.security.der.BitString;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.x509.ext.Extension;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CRLException;
import java.security.cert.Certificate;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.security.auth.x500.X500Principal;
/**
* X.509 certificate revocation lists.
*
* @author Casey Marshall (rsdio@metastatic.org)
*/
public class X509CRL extends java.security.cert.X509CRL
implements GnuPKIExtension
{
// Constants and fields.
// ------------------------------------------------------------------------
private static final boolean DEBUG = false;
private static void debug(String msg)
{
if (DEBUG)
{
System.err.print(">> X509CRL: ");
System.err.println(msg);
}
}
private static final OID ID_DSA = new OID("1.2.840.10040.4.1");
private static final OID ID_DSA_WITH_SHA1 = new OID("1.2.840.10040.4.3");
private static final OID ID_RSA = new OID("1.2.840.113549.1.1.1");
private static final OID ID_RSA_WITH_MD2 = new OID("1.2.840.113549.1.1.2");
private static final OID ID_RSA_WITH_MD5 = new OID("1.2.840.113549.1.1.4");
private static final OID ID_RSA_WITH_SHA1 = new OID("1.2.840.113549.1.1.5");
private byte[] encoded;
private byte[] tbsCRLBytes;
private int version;
private OID algId;
private byte[] algParams;
private Date thisUpdate;
private Date nextUpdate;
private X500DistinguishedName issuerDN;
private HashMap revokedCerts;
private HashMap extensions;
private OID sigAlg;
private byte[] sigAlgParams;
private byte[] rawSig;
private byte[] signature;
// Constructors.
// ------------------------------------------------------------------------
/**
* Create a new X.509 CRL.
*
* @param encoded The DER encoded CRL.
* @throws CRLException If the input bytes are incorrect.
* @throws IOException If the input bytes cannot be read.
*/
public X509CRL(InputStream encoded) throws CRLException, IOException
{
super();
revokedCerts = new HashMap();
extensions = new HashMap();
try
{
parse(encoded);
}
catch (IOException ioe)
{
ioe.printStackTrace();
throw ioe;
}
catch (Exception x)
{
x.printStackTrace();
throw new CRLException(x.toString());
}
}
// X509CRL methods.
// ------------------------------------------------------------------------
public boolean equals(Object o)
{
if (!(o instanceof X509CRL))
return false;
return ((X509CRL) o).getRevokedCertificates().equals(revokedCerts.values());
}
public int hashCode()
{
return revokedCerts.hashCode();
}
public byte[] getEncoded() throws CRLException
{
return (byte[]) encoded.clone();
}
public void verify(PublicKey key)
throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, SignatureException
{
Signature sig = Signature.getInstance(sigAlg.toString());
doVerify(sig, key);
}
public void verify(PublicKey key, String provider)
throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, SignatureException
{
Signature sig = Signature.getInstance(sigAlg.toString(), provider);
doVerify(sig, key);
}
public int getVersion()
{
return version;
}
public Principal getIssuerDN()
{
return issuerDN;
}
public X500Principal getIssuerX500Principal()
{
return new X500Principal(issuerDN.getDer());
}
public Date getThisUpdate()
{
return (Date) thisUpdate.clone();
}
public Date getNextUpdate()
{
if (nextUpdate != null)
return (Date) nextUpdate.clone();
return null;
}
public java.security.cert.X509CRLEntry getRevokedCertificate(BigInteger serialNo)
{
return (java.security.cert.X509CRLEntry) revokedCerts.get(serialNo);
}
public Set getRevokedCertificates()
{
return Collections.unmodifiableSet(new HashSet(revokedCerts.values()));
}
public byte[] getTBSCertList() throws CRLException
{
return (byte[]) tbsCRLBytes.clone();
}
public byte[] getSignature()
{
return (byte[]) rawSig.clone();
}
public String getSigAlgName()
{
if (sigAlg.equals(ID_DSA_WITH_SHA1))
return "SHA1withDSA";
if (sigAlg.equals(ID_RSA_WITH_MD2))
return "MD2withRSA";
if (sigAlg.equals(ID_RSA_WITH_MD5))
return "MD5withRSA";
if (sigAlg.equals(ID_RSA_WITH_SHA1))
return "SHA1withRSA";
return "unknown";
}
public String getSigAlgOID()
{
return sigAlg.toString();
}
public byte[] getSigAlgParams()
{
if (sigAlgParams != null)
return (byte[]) sigAlgParams.clone();
return null;
}
// X509Extension methods.
// ------------------------------------------------------------------------
public boolean hasUnsupportedCriticalExtension()
{
for (Iterator it = extensions.values().iterator(); it.hasNext(); )
{
Extension e = (Extension) it.next();
if (e.isCritical() && !e.isSupported())
return true;
}
return false;
}
public Set getCriticalExtensionOIDs()
{
HashSet s = new HashSet();
for (Iterator it = extensions.values().iterator(); it.hasNext(); )
{
Extension e = (Extension) it.next();
if (e.isCritical())
s.add(e.getOid().toString());
}
return Collections.unmodifiableSet(s);
}
public Set getNonCriticalExtensionOIDs()
{
HashSet s = new HashSet();
for (Iterator it = extensions.values().iterator(); it.hasNext(); )
{
Extension e = (Extension) it.next();
if (!e.isCritical())
s.add(e.getOid().toString());
}
return Collections.unmodifiableSet(s);
}
public byte[] getExtensionValue(String oid)
{
Extension e = getExtension(new OID(oid));
if (e != null)
{
return e.getValue().getEncoded();
}
return null;
}
// GnuPKIExtension method.
// -------------------------------------------------------------------------
public Extension getExtension(OID oid)
{
return (Extension) extensions.get(oid);
}
public Collection getExtensions()
{
return extensions.values();
}
// CRL methods.
// -------------------------------------------------------------------------
public String toString()
{
return X509CRL.class.getName();
}
public boolean isRevoked(Certificate cert)
{
if (!(cert instanceof java.security.cert.X509Certificate))
throw new IllegalArgumentException("not a X.509 certificate");
BigInteger certSerial =
((java.security.cert.X509Certificate) cert).getSerialNumber();
X509CRLEntry ent = (X509CRLEntry) revokedCerts.get(certSerial);
if (ent == null)
return false;
return ent.getRevocationDate().compareTo(new Date()) < 0;
}
// Own methods.
// ------------------------------------------------------------------------
private void doVerify(Signature sig, PublicKey key)
throws CRLException, InvalidKeyException, SignatureException
{
sig.initVerify(key);
sig.update(tbsCRLBytes);
if (!sig.verify(signature))
throw new CRLException("signature not verified");
}
private void parse(InputStream in) throws Exception
{
// CertificateList ::= SEQUENCE {
DERReader der = new DERReader(in);
DERValue val = der.read();
debug("start CertificateList len == " + val.getLength());
if (!val.isConstructed())
throw new IOException("malformed CertificateList");
encoded = val.getEncoded();
// tbsCertList ::= SEQUENCE { -- TBSCertList
val = der.read();
if (!val.isConstructed())
throw new IOException("malformed TBSCertList");
debug("start tbsCertList len == " + val.getLength());
tbsCRLBytes = val.getEncoded();
// version Version OPTIONAL,
// -- If present must be v2
val = der.read();
if (val.getValue() instanceof BigInteger)
{
version = ((BigInteger) val.getValue()).intValue() + 1;
val = der.read();
}
else
version = 1;
debug("read version == " + version);
// signature AlgorithmIdentifier,
debug("start AlgorithmIdentifier len == " + val.getLength());
if (!val.isConstructed())
throw new IOException("malformed AlgorithmIdentifier");
DERValue algIdVal = der.read();
algId = (OID) algIdVal.getValue();
debug("read object identifier == " + algId);
if (val.getLength() > algIdVal.getEncodedLength())
{
val = der.read();
debug("read parameters len == " + val.getEncodedLength());
algParams = val.getEncoded();
if (val.isConstructed())
in.skip(val.getLength());
}
// issuer Name,
val = der.read();
issuerDN = new X500DistinguishedName(val.getEncoded());
der.skip(val.getLength());
debug("read issuer == " + issuerDN);
// thisUpdate Time,
thisUpdate = (Date) der.read().getValue();
debug("read thisUpdate == " + thisUpdate);
// nextUpdate Time OPTIONAL,
val = der.read();
if (val.getValue() instanceof Date)
{
nextUpdate = (Date) val.getValue();
debug("read nextUpdate == " + nextUpdate);
val = der.read();
}
// revokedCertificates SEQUENCE OF SEQUENCE {
// -- X509CRLEntry objects...
// } OPTIONAL,
if (val.getTag() != 0)
{
int len = 0;
while (len < val.getLength())
{
X509CRLEntry entry = new X509CRLEntry(version, der);
revokedCerts.put(entry.getSerialNumber(), entry);
len += entry.getEncoded().length;
}
val = der.read();
}
// crlExtensions [0] EXPLICIT Extensions OPTIONAL
// -- if present MUST be v2
if (val.getTagClass() != DER.UNIVERSAL && val.getTag() == 0)
{
if (version < 2)
throw new IOException("extra data in CRL");
DERValue exts = der.read();
if (!exts.isConstructed())
throw new IOException("malformed Extensions");
debug("start Extensions len == " + exts.getLength());
int len = 0;
while (len < exts.getLength())
{
DERValue ext = der.read();
if (!ext.isConstructed())
throw new IOException("malformed Extension");
Extension e = new Extension(ext.getEncoded());
extensions.put(e.getOid(), e);
der.skip(ext.getLength());
len += ext.getEncodedLength();
debug("current count == " + len);
}
val = der.read();
}
debug("read tag == " + val.getTag());
if (!val.isConstructed())
throw new IOException("malformed AlgorithmIdentifier");
debug("start AlgorithmIdentifier len == " + val.getLength());
DERValue sigAlgVal = der.read();
debug("read tag == " + sigAlgVal.getTag());
if (sigAlgVal.getTag() != DER.OBJECT_IDENTIFIER)
throw new IOException("malformed AlgorithmIdentifier");
sigAlg = (OID) sigAlgVal.getValue();
debug("signature id == " + sigAlg);
debug("sigAlgVal length == " + sigAlgVal.getEncodedLength());
if (val.getLength() > sigAlgVal.getEncodedLength())
{
val = der.read();
debug("sig params tag = " + val.getTag() + " len == " + val.getEncodedLength());
sigAlgParams = (byte[]) val.getEncoded();
if (val.isConstructed())
in.skip(val.getLength());
}
val = der.read();
debug("read tag = " + val.getTag());
rawSig = val.getEncoded();
signature = ((BitString) val.getValue()).toByteArray();
}
}
@@ -0,0 +1,278 @@
/* X509CRLEntry.java -- an entry in a X.509 CRL.
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509;
import gnu.java.security.OID;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.x509.ext.Extension;
import java.io.IOException;
import java.math.BigInteger;
import java.security.cert.CRLException;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* A single entry in a X.509 certificate revocation list.
*
* @see X509CRL
* @author Casey Marshall
*/
class X509CRLEntry extends java.security.cert.X509CRLEntry
implements GnuPKIExtension
{
// Constants and fields.
// ------------------------------------------------------------------------
private static final boolean DEBUG = false;
private static void debug(String msg)
{
if (DEBUG)
{
System.err.print(">> X509CRLEntry: ");
System.err.println(msg);
}
}
/** The DER encoded form of this CRL entry. */
private byte[] encoded;
/** The revoked certificate's serial number. */
private BigInteger serialNo;
/** The date the certificate was revoked. */
private Date revocationDate;
/** The CRL entry extensions. */
private HashMap extensions;
// Constructor.
// ------------------------------------------------------------------------
/**
* Create a new X.509 certificate revocation list entry from the given
* input stream and CRL version number.
*
* @param version The CRL version.
* @param encoded The stream of DER bytes.
* @throws CRLException If the ASN.1 structure is invalid.
* @throws IOException If the bytes cannot be read.
*/
X509CRLEntry(int version, DERReader encoded)
throws CRLException, IOException
{
super();
extensions = new HashMap();
try
{
parse(version, encoded);
}
catch (IOException ioe)
{
throw ioe;
}
catch (Exception x)
{
throw new CRLException(x.toString());
}
}
// X509CRLEntry methods.
// ------------------------------------------------------------------------
public boolean equals(Object o)
{
if (!(o instanceof X509CRLEntry))
return false;
return ((X509CRLEntry) o).getSerialNumber().equals(serialNo) &&
((X509CRLEntry) o).getRevocationDate().equals(revocationDate);
}
public int hashCode()
{
return serialNo.hashCode();
}
public byte[] getEncoded() throws CRLException
{
return (byte[]) encoded.clone();
}
public BigInteger getSerialNumber()
{
return serialNo;
}
public Date getRevocationDate()
{
return (Date) revocationDate.clone();
}
public boolean hasExtensions()
{
return ! extensions.isEmpty();
}
public String toString()
{
return "X509CRLEntry serial=" + serialNo + " revocation date="
+ revocationDate + " ext=" + extensions;
}
// X509Extension methods.
// -------------------------------------------------------------------------
public boolean hasUnsupportedCriticalExtension()
{
for (Iterator it = extensions.values().iterator(); it.hasNext(); )
{
Extension e = (Extension) it.next();
if (e.isCritical() && !e.isSupported())
return true;
}
return false;
}
public Set getCriticalExtensionOIDs()
{
HashSet s = new HashSet();
for (Iterator it = extensions.values().iterator(); it.hasNext(); )
{
Extension e = (Extension) it.next();
if (e.isCritical())
s.add(e.getOid().toString());
}
return Collections.unmodifiableSet(s);
}
public Set getNonCriticalExtensionOIDs()
{
HashSet s = new HashSet();
for (Iterator it = extensions.values().iterator(); it.hasNext(); )
{
Extension e = (Extension) it.next();
if (!e.isCritical())
s.add(e.getOid().toString());
}
return Collections.unmodifiableSet(s);
}
public byte[] getExtensionValue(String oid)
{
Extension e = getExtension(new OID(oid));
if (e != null)
{
return e.getValue().getEncoded();
}
return null;
}
// GnuPKIExtension method.
// -------------------------------------------------------------------------
public Extension getExtension(OID oid)
{
return (Extension) extensions.get(oid);
}
public Collection getExtensions()
{
return extensions.values();
}
// Own methods.
// -------------------------------------------------------------------------
private void parse(int version, DERReader der) throws Exception
{
// RevokedCertificate ::= SEQUENCE {
DERValue entry = der.read();
debug("start CRL entry len == " + entry.getLength());
if (!entry.isConstructed())
throw new IOException("malformed revokedCertificate");
encoded = entry.getEncoded();
int len = 0;
debug("encoded entry:\n" + Util.hexDump(encoded, ">>>> "));
// userCertificate CertificateSerialNumber,
DERValue val = der.read();
serialNo = (BigInteger) val.getValue();
len += val.getEncodedLength();
debug("userCertificate == " + serialNo + " current count == " + len);
// revocationDate Time,
val = der.read();
revocationDate = (Date) val.getValue();
len += val.getEncodedLength();
debug("revocationDate == " + revocationDate + " current count == " + len);
// crlEntryExtensions Extensions OPTIONAL
// -- if present MUST be v2
if (len < entry.getLength())
{
if (version < 2)
throw new IOException("extra data in CRL entry");
DERValue exts = der.read();
if (!exts.isConstructed())
throw new IOException("malformed Extensions");
debug("start Extensions len == " + exts.getLength());
len = 0;
while (len < exts.getLength())
{
val = der.read();
if (!val.isConstructed())
throw new IOException("malformed Extension");
debug("start Extension len == " + val.getLength());
Extension e = new Extension(val.getEncoded());
extensions.put(e.getOid(), e);
der.skip(val.getLength());
len += val.getEncodedLength();
debug("current count == " + len);
}
}
}
}
@@ -0,0 +1,138 @@
/* X509CRLSelectorImpl.java -- implementation of an X509CRLSelector.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509;
import java.io.IOException;
import java.security.Principal;
import java.security.cert.CRL;
import java.security.cert.CRLSelector;
import java.security.cert.X509CRL;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.security.auth.x500.X500Principal;
/**
* Sun's implementation of X509CRLSelector sucks. This one tries to work
* better.
*/
public class X509CRLSelectorImpl implements CRLSelector
{
// Fields.
// -------------------------------------------------------------------------
private Set issuerNames;
// Constructor.
// -------------------------------------------------------------------------
public X509CRLSelectorImpl()
{
issuerNames = new HashSet();
}
// Instance methods.
// -------------------------------------------------------------------------
public void addIssuerName(byte[] issuerName) throws IOException
{
issuerNames.add(new X500DistinguishedName(issuerName));
}
public void addIssuerName(String issuerName)
{
issuerNames.add(new X500DistinguishedName(issuerName));
}
public void addIssuerName(Principal issuerName) throws IOException
{
if (issuerName instanceof X500DistinguishedName)
issuerNames.add(issuerName);
else if (issuerName instanceof X500Principal)
issuerNames.add(new X500DistinguishedName(((X500Principal) issuerName).getEncoded()));
else
issuerNames.add(new X500DistinguishedName(issuerName.getName()));
}
public Collection getIssuerNames()
{
return Collections.unmodifiableSet(issuerNames);
}
public Object clone()
{
X509CRLSelectorImpl copy = new X509CRLSelectorImpl();
copy.issuerNames.addAll(issuerNames);
return copy;
}
public boolean match(CRL crl)
{
if (!(crl instanceof X509CRL))
return false;
try
{
Principal p = ((X509CRL) crl).getIssuerDN();
X500DistinguishedName thisName = null;
if (p instanceof X500DistinguishedName)
thisName = (X500DistinguishedName) p;
else if (p instanceof X500Principal)
thisName = new X500DistinguishedName(((X500Principal) p).getEncoded());
else
thisName = new X500DistinguishedName(p.getName());
for (Iterator it = issuerNames.iterator(); it.hasNext(); )
{
X500DistinguishedName name = (X500DistinguishedName) it.next();
if (thisName.equals(name))
return true;
}
}
catch (Exception x)
{
}
return false;
}
}
@@ -0,0 +1,303 @@
/* X509CertPath.java -- an X.509 certificate path.
Copyright (C) 2004 Free Software Fonudation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DEREncodingException;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* A certificate path (or certificate chain) of X509Certificates.
*
* @author Casey Marshall (rsdio@metastatic.org)
*/
public class X509CertPath extends CertPath
{
// Fields.
// -------------------------------------------------------------------------
public static final List ENCODINGS = Collections.unmodifiableList(
Arrays.asList(new String[] { "PkiPath", "PKCS7" }));
private static final OID PKCS7_SIGNED_DATA = new OID("1.2.840.113549.1.7.2");
private static final OID PKCS7_DATA = new OID("1.2.840.113549.1.7.1");
/** The certificate path. */
private List path;
/** The cached PKCS #7 encoded bytes. */
private byte[] pkcs_encoded;
/** The cached PkiPath encoded bytes. */
private byte[] pki_encoded;
// Constructor.
// -------------------------------------------------------------------------
public X509CertPath(List path)
{
super("X.509");
this.path = Collections.unmodifiableList(path);
}
public X509CertPath(InputStream in) throws CertificateEncodingException
{
this(in, (String) ENCODINGS.get(0));
}
public X509CertPath(InputStream in, String encoding)
throws CertificateEncodingException
{
super("X.509");
try
{
parse(in, encoding);
}
catch (IOException ioe)
{
throw new CertificateEncodingException();
}
}
// Instance methods.
// -------------------------------------------------------------------------
public List getCertificates()
{
return path; // already unmodifiable
}
public byte[] getEncoded() throws CertificateEncodingException
{
return getEncoded((String) ENCODINGS.get(0));
}
public byte[] getEncoded(String encoding) throws CertificateEncodingException
{
if (encoding.equalsIgnoreCase("PkiPath"))
{
if (pki_encoded == null)
{
try
{
pki_encoded = encodePki();
}
catch (IOException ioe)
{
throw new CertificateEncodingException();
}
}
return (byte[]) pki_encoded.clone();
}
else if (encoding.equalsIgnoreCase("PKCS7"))
{
if (pkcs_encoded == null)
{
try
{
pkcs_encoded = encodePKCS();
}
catch (IOException ioe)
{
throw new CertificateEncodingException();
}
}
return (byte[]) pkcs_encoded.clone();
}
else
throw new CertificateEncodingException("unknown encoding: " + encoding);
}
public Iterator getEncodings()
{
return ENCODINGS.iterator(); // already unmodifiable
}
// Own methods.
// -------------------------------------------------------------------------
private void parse(InputStream in, String encoding)
throws CertificateEncodingException, IOException
{
DERReader der = new DERReader(in);
DERValue path = null;
if (encoding.equalsIgnoreCase("PkiPath"))
{
// PKI encoding is just a SEQUENCE of X.509 certificates.
path = der.read();
if (!path.isConstructed())
throw new DEREncodingException("malformed PkiPath");
}
else if (encoding.equalsIgnoreCase("PKCS7"))
{
// PKCS #7 encoding means that the certificates are contained in a
// SignedData PKCS #7 type.
//
// ContentInfo ::= SEQUENCE {
// contentType ::= ContentType,
// content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
//
// ContentType ::= OBJECT IDENTIFIER
//
// SignedData ::= SEQUENCE {
// version Version,
// digestAlgorithms DigestAlgorithmIdentifiers,
// contentInfo ContentInfo,
// certificates [0] IMPLICIT ExtendedCertificatesAndCertificates
// OPTIONAL,
// crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
// signerInfos SignerInfos }
//
// Version ::= INTEGER
//
DERValue value = der.read();
if (!value.isConstructed())
throw new DEREncodingException("malformed ContentInfo");
value = der.read();
if (!(value.getValue() instanceof OID) ||
((OID) value.getValue()).equals(PKCS7_SIGNED_DATA))
throw new DEREncodingException("not a SignedData");
value = der.read();
if (!value.isConstructed() || value.getTag() != 0)
throw new DEREncodingException("malformed content");
value = der.read();
if (value.getTag() != DER.INTEGER)
throw new DEREncodingException("malformed Version");
value = der.read();
if (!value.isConstructed() || value.getTag() != DER.SET)
throw new DEREncodingException("malformed DigestAlgorithmIdentifiers");
der.skip(value.getLength());
value = der.read();
if (!value.isConstructed())
throw new DEREncodingException("malformed ContentInfo");
der.skip(value.getLength());
path = der.read();
if (!path.isConstructed() || path.getTag() != 0)
throw new DEREncodingException("no certificates");
}
else
throw new CertificateEncodingException("unknown encoding: " + encoding);
LinkedList certs = new LinkedList();
int len = 0;
while (len < path.getLength())
{
DERValue cert = der.read();
try
{
certs.add(new X509Certificate(new ByteArrayInputStream(cert.getEncoded())));
}
catch (CertificateException ce)
{
throw new CertificateEncodingException(ce.getMessage());
}
len += cert.getEncodedLength();
der.skip(cert.getLength());
}
this.path = Collections.unmodifiableList(certs);
}
private byte[] encodePki()
throws CertificateEncodingException, IOException
{
synchronized (path)
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (Iterator i = path.iterator(); i.hasNext(); )
{
out.write(((Certificate) i.next()).getEncoded());
}
byte[] b = out.toByteArray();
DERValue val = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
b.length, b, null);
return val.getEncoded();
}
}
private byte[] encodePKCS()
throws CertificateEncodingException, IOException
{
synchronized (path)
{
ArrayList signedData = new ArrayList(5);
signedData.add(new DERValue(DER.INTEGER, BigInteger.ONE));
signedData.add(new DERValue(DER.CONSTRUCTED | DER.SET,
Collections.EMPTY_SET));
signedData.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
Collections.singletonList(
new DERValue(DER.OBJECT_IDENTIFIER, PKCS7_DATA))));
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (Iterator i = path.iterator(); i.hasNext(); )
{
out.write(((Certificate) i.next()).getEncoded());
}
byte[] b = out.toByteArray();
signedData.add(new DERValue(DER.CONSTRUCTED | DER.CONTEXT,
b.length, b, null));
DERValue sdValue = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
signedData);
ArrayList contentInfo = new ArrayList(2);
contentInfo.add(new DERValue(DER.OBJECT_IDENTIFIER, PKCS7_SIGNED_DATA));
contentInfo.add(new DERValue(DER.CONSTRUCTED | DER.CONTEXT, sdValue));
return new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
contentInfo).getEncoded();
}
}
}
@@ -0,0 +1,197 @@
/* X509CertSelectorImpl.java -- implementation of an X509CertSelector.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509;
import java.io.IOException;
import java.security.Principal;
import java.security.cert.CertSelector;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.security.auth.x500.X500Principal;
/**
* Sun's implementation of X509CertSelector sucks. This one tries to work
* better.
*/
public class X509CertSelectorImpl implements CertSelector
{
// Fields.
// -------------------------------------------------------------------------
private Set issuerNames;
private Set subjectNames;
// Constructor.
// -------------------------------------------------------------------------
public X509CertSelectorImpl()
{
issuerNames = new HashSet();
subjectNames = new HashSet();
}
// Instance methods.
// -------------------------------------------------------------------------
public void addIssuerName(byte[] issuerName) throws IOException
{
issuerNames.add(new X500DistinguishedName(issuerName));
}
public void addIssuerName(String issuerName)
{
issuerNames.add(new X500DistinguishedName(issuerName));
}
public void addIssuerName(Principal issuerName) throws IOException
{
if (issuerName instanceof X500DistinguishedName)
issuerNames.add(issuerName);
else if (issuerName instanceof X500Principal)
issuerNames.add(new X500DistinguishedName(((X500Principal) issuerName).getEncoded()));
else
issuerNames.add(new X500DistinguishedName(issuerName.getName()));
}
public Collection getIssuerNames()
{
return Collections.unmodifiableSet(issuerNames);
}
public void addSubjectName(byte[] subjectName) throws IOException
{
subjectNames.add(new X500DistinguishedName(subjectName));
}
public void addSubjectName(String subjectName) throws IOException
{
subjectNames.add(new X500DistinguishedName(subjectName));
}
public void addSubjectName(Principal subjectName) throws IOException
{
if (subjectName instanceof X500DistinguishedName)
subjectNames.add(subjectName);
else if (subjectName instanceof X500Principal)
subjectNames.add(new X500DistinguishedName(((X500Principal) subjectName).getEncoded()));
else
subjectNames.add(new X500DistinguishedName(subjectName.getName()));
}
public Collection getSubjectNames()
{
return Collections.unmodifiableSet(subjectNames);
}
public Object clone()
{
X509CertSelectorImpl copy = new X509CertSelectorImpl();
copy.issuerNames.addAll(issuerNames);
copy.subjectNames.addAll(subjectNames);
return copy;
}
public boolean match(Certificate cert)
{
if (!(cert instanceof X509Certificate))
return false;
boolean matchIssuer = false;
boolean matchSubject = false;
try
{
Principal p = ((X509Certificate) cert).getIssuerDN();
X500DistinguishedName thisName = null;
if (p instanceof X500DistinguishedName)
thisName = (X500DistinguishedName) p;
else if (p instanceof X500Principal)
thisName = new X500DistinguishedName(((X500Principal) p).getEncoded());
else
thisName = new X500DistinguishedName(p.getName());
if (issuerNames.isEmpty())
matchIssuer = true;
else
{
for (Iterator it = issuerNames.iterator(); it.hasNext(); )
{
X500DistinguishedName name = (X500DistinguishedName) it.next();
if (thisName.equals(name))
{
matchIssuer = true;
break;
}
}
}
p = ((X509Certificate) cert).getSubjectDN();
thisName = null;
if (p instanceof X500DistinguishedName)
thisName = (X500DistinguishedName) p;
else if (p instanceof X500Principal)
thisName = new X500DistinguishedName(((X500Principal) p).getEncoded());
else
thisName = new X500DistinguishedName(p.getName());
if (subjectNames.isEmpty())
matchSubject = true;
else
{
for (Iterator it = subjectNames.iterator(); it.hasNext(); )
{
X500DistinguishedName name = (X500DistinguishedName) it.next();
if (thisName.equals(name))
{
matchSubject = true;
break;
}
}
}
}
catch (Exception x)
{
}
return matchIssuer && matchSubject;
}
}
@@ -0,0 +1,745 @@
/* X509Certificate.java -- X.509 certificate.
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509;
import gnu.classpath.debug.Component;
import gnu.classpath.debug.SystemLogger;
import gnu.java.security.OID;
import gnu.java.security.der.BitString;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.x509.ext.BasicConstraints;
import gnu.java.security.x509.ext.ExtendedKeyUsage;
import gnu.java.security.x509.ext.Extension;
import gnu.java.security.x509.ext.IssuerAlternativeNames;
import gnu.java.security.x509.ext.KeyUsage;
import gnu.java.security.x509.ext.SubjectAlternativeNames;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.math.BigInteger;
import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateParsingException;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.DSAParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.x500.X500Principal;
/**
* An implementation of X.509 certificates.
*
* @author Casey Marshall (rsdio@metastatic.org)
*/
public class X509Certificate extends java.security.cert.X509Certificate
implements Serializable, GnuPKIExtension
{
// Constants and fields.
// ------------------------------------------------------------------------
private static final Logger logger = SystemLogger.SYSTEM;
protected static final OID ID_DSA = new OID ("1.2.840.10040.4.1");
protected static final OID ID_DSA_WITH_SHA1 = new OID ("1.2.840.10040.4.3");
protected static final OID ID_RSA = new OID ("1.2.840.113549.1.1.1");
protected static final OID ID_RSA_WITH_MD2 = new OID ("1.2.840.113549.1.1.2");
protected static final OID ID_RSA_WITH_MD5 = new OID ("1.2.840.113549.1.1.4");
protected static final OID ID_RSA_WITH_SHA1 = new OID ("1.2.840.113549.1.1.5");
protected static final OID ID_ECDSA_WITH_SHA1 = new OID ("1.2.840.10045.4.1");
// This object SHOULD be serialized with an instance of
// java.security.cert.Certificate.CertificateRep, thus all fields are
// transient.
// The encoded certificate.
protected transient byte[] encoded;
// TBSCertificate part.
protected transient byte[] tbsCertBytes;
protected transient int version;
protected transient BigInteger serialNo;
protected transient OID algId;
protected transient byte[] algVal;
protected transient X500DistinguishedName issuer;
protected transient Date notBefore;
protected transient Date notAfter;
protected transient X500DistinguishedName subject;
protected transient PublicKey subjectKey;
protected transient BitString issuerUniqueId;
protected transient BitString subjectUniqueId;
protected transient Map extensions;
// Signature.
protected transient OID sigAlgId;
protected transient byte[] sigAlgVal;
protected transient byte[] signature;
// Constructors.
// ------------------------------------------------------------------------
/**
* Create a new X.509 certificate from the encoded data. The input
* data are expected to be the ASN.1 DER encoding of the certificate.
*
* @param encoded The encoded certificate data.
* @throws IOException If the certificate cannot be read, possibly
* from a formatting error.
* @throws CertificateException If the data read is not an X.509
* certificate.
*/
public X509Certificate(InputStream encoded)
throws CertificateException, IOException
{
super();
extensions = new HashMap();
try
{
parse(encoded);
}
catch (IOException ioe)
{
logger.log (Component.X509, "", ioe);
throw ioe;
}
catch (Exception e)
{
logger.log (Component.X509, "", e);
CertificateException ce = new CertificateException(e.getMessage());
ce.initCause (e);
throw ce;
}
}
protected X509Certificate()
{
extensions = new HashMap();
}
// X509Certificate methods.
// ------------------------------------------------------------------------
public void checkValidity()
throws CertificateExpiredException, CertificateNotYetValidException
{
checkValidity(new Date());
}
public void checkValidity(Date date)
throws CertificateExpiredException, CertificateNotYetValidException
{
if (date.compareTo(notBefore) < 0)
{
throw new CertificateNotYetValidException();
}
if (date.compareTo(notAfter) > 0)
{
throw new CertificateExpiredException();
}
}
public int getVersion()
{
return version;
}
public BigInteger getSerialNumber()
{
return serialNo;
}
public Principal getIssuerDN()
{
return issuer;
}
public X500Principal getIssuerX500Principal()
{
return new X500Principal(issuer.getDer());
}
public Principal getSubjectDN()
{
return subject;
}
public X500Principal getSubjectX500Principal()
{
return new X500Principal(subject.getDer());
}
public Date getNotBefore()
{
return (Date) notBefore.clone();
}
public Date getNotAfter()
{
return (Date) notAfter.clone();
}
public byte[] getTBSCertificate() throws CertificateEncodingException
{
return (byte[]) tbsCertBytes.clone();
}
public byte[] getSignature()
{
return (byte[]) signature.clone();
}
public String getSigAlgName()
{
if (sigAlgId.equals(ID_DSA_WITH_SHA1))
{
return "SHA1withDSA";
}
if (sigAlgId.equals(ID_RSA_WITH_MD2))
{
return "MD2withRSA";
}
if (sigAlgId.equals(ID_RSA_WITH_MD5))
{
return "MD5withRSA";
}
if (sigAlgId.equals(ID_RSA_WITH_SHA1))
{
return "SHA1withRSA";
}
return "unknown";
}
public String getSigAlgOID()
{
return sigAlgId.toString();
}
public byte[] getSigAlgParams()
{
return (byte[]) sigAlgVal.clone();
}
public boolean[] getIssuerUniqueID()
{
if (issuerUniqueId != null)
{
return issuerUniqueId.toBooleanArray();
}
return null;
}
public boolean[] getSubjectUniqueID()
{
if (subjectUniqueId != null)
{
return subjectUniqueId.toBooleanArray();
}
return null;
}
public boolean[] getKeyUsage()
{
Extension e = getExtension(KeyUsage.ID);
if (e != null)
{
KeyUsage ku = (KeyUsage) e.getValue();
boolean[] result = new boolean[9];
boolean[] b = ku.getKeyUsage().toBooleanArray();
System.arraycopy(b, 0, result, 0, b.length);
return result;
}
return null;
}
public List getExtendedKeyUsage() throws CertificateParsingException
{
Extension e = getExtension(ExtendedKeyUsage.ID);
if (e != null)
{
List a = ((ExtendedKeyUsage) e.getValue()).getPurposeIds();
List b = new ArrayList(a.size());
for (Iterator it = a.iterator(); it.hasNext(); )
{
b.add(it.next().toString());
}
return Collections.unmodifiableList(b);
}
return null;
}
public int getBasicConstraints()
{
Extension e = getExtension(BasicConstraints.ID);
if (e != null)
{
return ((BasicConstraints) e.getValue()).getPathLengthConstraint();
}
return -1;
}
public Collection getSubjectAlternativeNames()
throws CertificateParsingException
{
Extension e = getExtension(SubjectAlternativeNames.ID);
if (e != null)
{
return ((SubjectAlternativeNames) e.getValue()).getNames();
}
return null;
}
public Collection getIssuerAlternativeNames()
throws CertificateParsingException
{
Extension e = getExtension(IssuerAlternativeNames.ID);
if (e != null)
{
return ((IssuerAlternativeNames) e.getValue()).getNames();
}
return null;
}
// X509Extension methods.
// ------------------------------------------------------------------------
public boolean hasUnsupportedCriticalExtension()
{
for (Iterator it = extensions.values().iterator(); it.hasNext(); )
{
Extension e = (Extension) it.next();
if (e.isCritical() && !e.isSupported())
return true;
}
return false;
}
public Set getCriticalExtensionOIDs()
{
HashSet s = new HashSet();
for (Iterator it = extensions.values().iterator(); it.hasNext(); )
{
Extension e = (Extension) it.next();
if (e.isCritical())
s.add(e.getOid().toString());
}
return Collections.unmodifiableSet(s);
}
public Set getNonCriticalExtensionOIDs()
{
HashSet s = new HashSet();
for (Iterator it = extensions.values().iterator(); it.hasNext(); )
{
Extension e = (Extension) it.next();
if (!e.isCritical())
s.add(e.getOid().toString());
}
return Collections.unmodifiableSet(s);
}
public byte[] getExtensionValue(String oid)
{
Extension e = getExtension(new OID(oid));
if (e != null)
{
return e.getValue().getEncoded();
}
return null;
}
// GnuPKIExtension method.
// -------------------------------------------------------------------------
public Extension getExtension(OID oid)
{
return (Extension) extensions.get(oid);
}
public Collection getExtensions()
{
return extensions.values();
}
// Certificate methods.
// -------------------------------------------------------------------------
public byte[] getEncoded() throws CertificateEncodingException
{
return (byte[]) encoded.clone();
}
public void verify(PublicKey key)
throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException, SignatureException
{
Signature sig = Signature.getInstance(sigAlgId.toString());
doVerify(sig, key);
}
public void verify(PublicKey key, String provider)
throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException, SignatureException
{
Signature sig = Signature.getInstance(sigAlgId.toString(), provider);
doVerify(sig, key);
}
public String toString()
{
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
out.println(X509Certificate.class.getName() + " {");
out.println(" TBSCertificate {");
out.println(" version = " + version + ";");
out.println(" serialNo = " + serialNo + ";");
out.println(" signature = {");
out.println(" algorithm = " + getSigAlgName() + ";");
out.print(" parameters =");
if (sigAlgVal != null)
{
out.println();
out.print(Util.hexDump(sigAlgVal, " "));
}
else
{
out.println(" null;");
}
out.println(" }");
out.println(" issuer = " + issuer.getName() + ";");
out.println(" validity = {");
out.println(" notBefore = " + notBefore + ";");
out.println(" notAfter = " + notAfter + ";");
out.println(" }");
out.println(" subject = " + subject.getName() + ";");
out.println(" subjectPublicKeyInfo = {");
out.println(" algorithm = " + subjectKey.getAlgorithm());
out.println(" key =");
out.print(Util.hexDump(subjectKey.getEncoded(), " "));
out.println(" };");
out.println(" issuerUniqueId = " + issuerUniqueId + ";");
out.println(" subjectUniqueId = " + subjectUniqueId + ";");
out.println(" extensions = {");
for (Iterator it = extensions.values().iterator(); it.hasNext(); )
{
out.println(" " + it.next());
}
out.println(" }");
out.println(" }");
out.println(" signatureAlgorithm = " + getSigAlgName() + ";");
out.println(" signatureValue =");
out.print(Util.hexDump(signature, " "));
out.println("}");
return str.toString();
}
public PublicKey getPublicKey()
{
return subjectKey;
}
public boolean equals(Object other)
{
if (!(other instanceof X509Certificate))
return false;
try
{
if (other instanceof X509Certificate)
return Arrays.equals(encoded, ((X509Certificate) other).encoded);
byte[] enc = ((X509Certificate) other).getEncoded();
if (enc == null)
return false;
return Arrays.equals(encoded, enc);
}
catch (CertificateEncodingException cee)
{
return false;
}
}
// Own methods.
// ------------------------------------------------------------------------
/**
* Verify this certificate's signature.
*/
private void doVerify(Signature sig, PublicKey key)
throws CertificateException, InvalidKeyException, SignatureException
{
logger.log (Component.X509, "verifying sig={0} key={1}",
new Object[] { sig, key });
sig.initVerify(key);
sig.update(tbsCertBytes);
if (!sig.verify(signature))
{
throw new CertificateException("signature not validated");
}
}
/**
* Parse a DER stream into an X.509 certificate.
*
* @param encoded The encoded bytes.
*/
private void parse(InputStream encoded) throws Exception
{
DERReader der = new DERReader(encoded);
// Certificate ::= SEQUENCE {
DERValue cert = der.read();
logger.log (Component.X509, "start Certificate len == {0}",
new Integer (cert.getLength()));
this.encoded = cert.getEncoded();
if (!cert.isConstructed())
{
throw new IOException("malformed Certificate");
}
// TBSCertificate ::= SEQUENCE {
DERValue tbsCert = der.read();
if (tbsCert.getValue() != DER.CONSTRUCTED_VALUE)
{
throw new IOException("malformed TBSCertificate");
}
tbsCertBytes = tbsCert.getEncoded();
logger.log (Component.X509, "start TBSCertificate len == {0}",
new Integer (tbsCert.getLength()));
// Version ::= INTEGER [0] { v1(0), v2(1), v3(2) }
DERValue val = der.read();
if (val.getTagClass() == DER.CONTEXT && val.getTag() == 0)
{
version = ((BigInteger) der.read().getValue()).intValue() + 1;
val = der.read();
}
else
{
version = 1;
}
logger.log (Component.X509, "read version == {0}",
new Integer (version));
// SerialNumber ::= INTEGER
serialNo = (BigInteger) val.getValue();
logger.log (Component.X509, "read serial number == {0}", serialNo);
// AlgorithmIdentifier ::= SEQUENCE {
val = der.read();
if (!val.isConstructed())
{
throw new IOException("malformed AlgorithmIdentifier");
}
int certAlgLen = val.getLength();
logger.log (Component.X509, "start AlgorithmIdentifier len == {0}",
new Integer (certAlgLen));
val = der.read();
// algorithm OBJECT IDENTIFIER,
algId = (OID) val.getValue();
logger.log (Component.X509, "read algorithm ID == {0}", algId);
// parameters ANY DEFINED BY algorithm OPTIONAL }
if (certAlgLen > val.getEncodedLength())
{
val = der.read();
if (val == null)
{
algVal = null;
}
else
{
algVal = val.getEncoded();
if (val.isConstructed())
encoded.skip(val.getLength());
}
logger.log (Component.X509, "read algorithm parameters == {0}", algVal);
}
// issuer Name,
val = der.read();
issuer = new X500DistinguishedName(val.getEncoded());
der.skip(val.getLength());
logger.log (Component.X509, "read issuer == {0}", issuer);
// Validity ::= SEQUENCE {
// notBefore Time,
// notAfter Time }
if (!der.read().isConstructed())
{
throw new IOException("malformed Validity");
}
notBefore = (Date) der.read().getValue();
logger.log (Component.X509, "read notBefore == {0}", notBefore);
notAfter = (Date) der.read().getValue();
logger.log (Component.X509, "read notAfter == {0}", notAfter);
// subject Name,
val = der.read();
subject = new X500DistinguishedName(val.getEncoded());
der.skip(val.getLength());
logger.log (Component.X509, "read subject == {0}", subject);
// SubjectPublicKeyInfo ::= SEQUENCE {
// algorithm AlgorithmIdentifier,
// subjectPublicKey BIT STRING }
DERValue spki = der.read();
if (!spki.isConstructed())
{
throw new IOException("malformed SubjectPublicKeyInfo");
}
KeyFactory spkFac = KeyFactory.getInstance("X.509");
subjectKey = spkFac.generatePublic(new X509EncodedKeySpec(spki.getEncoded()));
der.skip(spki.getLength());
logger.log (Component.X509, "read subjectPublicKey == {0}", subjectKey);
if (version > 1)
{
val = der.read();
}
if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 1)
{
byte[] b = (byte[]) val.getValue();
issuerUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
logger.log (Component.X509, "read issuerUniqueId == {0}", issuerUniqueId);
val = der.read();
}
if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 2)
{
byte[] b = (byte[]) val.getValue();
subjectUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
logger.log (Component.X509, "read subjectUniqueId == {0}", subjectUniqueId);
val = der.read();
}
if (version >= 3 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 3)
{
val = der.read();
logger.log (Component.X509, "start Extensions len == {0}",
new Integer (val.getLength()));
int len = 0;
while (len < val.getLength())
{
DERValue ext = der.read();
logger.log (Component.X509, "start extension len == {0}",
new Integer (ext.getLength()));
Extension e = new Extension(ext.getEncoded());
extensions.put(e.getOid(), e);
der.skip(ext.getLength());
len += ext.getEncodedLength();
logger.log (Component.X509, "read extension {0} == {1}",
new Object[] { e.getOid (), e });
logger.log (Component.X509, "count == {0}", new Integer (len));
}
val = der.read ();
}
logger.log (Component.X509, "read value {0}", val);
if (!val.isConstructed())
{
throw new CertificateException ("malformed AlgorithmIdentifier");
}
int sigAlgLen = val.getLength();
logger.log (Component.X509, "start AlgorithmIdentifier len == {0}",
new Integer (sigAlgLen));
val = der.read();
sigAlgId = (OID) val.getValue();
logger.log (Component.X509, "read algorithm id == {0}", sigAlgId);
if (sigAlgLen > val.getEncodedLength())
{
val = der.read();
if (val.getValue() == null)
{
if (subjectKey instanceof DSAPublicKey)
{
AlgorithmParameters params =
AlgorithmParameters.getInstance("DSA");
DSAParams dsap = ((DSAPublicKey) subjectKey).getParams();
DSAParameterSpec spec =
new DSAParameterSpec(dsap.getP(), dsap.getQ(), dsap.getG());
params.init(spec);
sigAlgVal = params.getEncoded();
}
}
else
{
sigAlgVal = (byte[]) val.getEncoded();
}
if (val.isConstructed())
{
encoded.skip(val.getLength());
}
logger.log (Component.X509, "read parameters == {0}", sigAlgVal);
}
signature = ((BitString) der.read().getValue()).toByteArray();
logger.log (Component.X509, "read signature ==\n{0}", Util.hexDump(signature, ">>>> "));
}
}
@@ -0,0 +1,133 @@
/* AuthorityKeyIdentifier.java -- Authority key identifier extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.x509.Util;
import java.io.IOException;
import java.math.BigInteger;
public class AuthorityKeyIdentifier extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.35");
private final byte[] keyIdentifier;
private final GeneralNames authorityCertIssuer;
private final BigInteger authorityCertSerialNumber;
// Contstructor.
// -------------------------------------------------------------------------
public AuthorityKeyIdentifier(final byte[] encoded) throws IOException
{
super(encoded);
DERReader der = new DERReader(encoded);
// AuthorityKeyIdentifier ::= SEQUENCE {
DERValue val = der.read();
if (!val.isConstructed())
throw new IOException("malformed AuthorityKeyIdentifier");
if (val.getLength() > 0)
val = der.read();
// keyIdentifier [0] KeyIdentifier OPTIONAL,
// KeyIdentifier ::= OCTET STRING
if (val.getTagClass() == DER.APPLICATION && val.getTag() == 0)
{
keyIdentifier = (byte[]) val.getValue();
val = der.read();
}
else
keyIdentifier = null;
// authorityCertIssuer [1] GeneralNames OPTIONAL,
if (val.getTagClass() == DER.APPLICATION && val.getTag() == 1)
{
byte[] b = val.getEncoded();
b[0] = (byte) (DER.CONSTRUCTED|DER.SEQUENCE);
authorityCertIssuer = new GeneralNames(b);
der.skip(val.getLength());
val = der.read();
}
else
authorityCertIssuer = null;
// authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
if (val.getTagClass() == DER.APPLICATION && val.getTag() == 2)
{
authorityCertSerialNumber = new BigInteger((byte[]) val.getValue());
}
else
authorityCertSerialNumber = null;
}
// Instance methods.
// -------------------------------------------------------------------------
public byte[] getKeyIdentifier()
{
return keyIdentifier != null ? (byte[]) keyIdentifier.clone() : null;
}
public GeneralNames getAuthorityCertIssuer()
{
return authorityCertIssuer;
}
public BigInteger getAuthorityCertSerialNumber()
{
return authorityCertSerialNumber;
}
public String toString()
{
return AuthorityKeyIdentifier.class.getName() + " [ keyId=" +
(keyIdentifier != null ? Util.toHexString (keyIdentifier, ':') : "nil") +
" authorityCertIssuer=" + authorityCertIssuer +
" authorityCertSerialNumbe=" + authorityCertSerialNumber + " ]";
}
}
@@ -0,0 +1,129 @@
/* BasicConstraints.java -- the basic constraints extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
public class BasicConstraints extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.19");
private final boolean ca;
private final int pathLenConstraint;
// Constructor.
// -------------------------------------------------------------------------
public BasicConstraints(final byte[] encoded) throws IOException
{
super(encoded);
DERReader der = new DERReader(encoded);
DERValue bc = der.read();
if (!bc.isConstructed())
throw new IOException("malformed BasicConstraints");
DERValue val = bc;
if (bc.getLength() > 0)
val = der.read();
if (val.getTag() == DER.BOOLEAN)
{
ca = ((Boolean) val.getValue()).booleanValue();
if (val.getEncodedLength() < bc.getLength())
val = der.read();
}
else
ca = false;
if (val.getTag() == DER.INTEGER)
{
pathLenConstraint = ((BigInteger) val.getValue()).intValue();
}
else
pathLenConstraint = -1;
}
public BasicConstraints (final boolean ca, final int pathLenConstraint)
{
this.ca = ca;
this.pathLenConstraint = pathLenConstraint;
}
// Instance methods.
// -------------------------------------------------------------------------
public boolean isCA()
{
return ca;
}
public int getPathLengthConstraint()
{
return pathLenConstraint;
}
public byte[] getEncoded()
{
if (encoded == null)
{
List bc = new ArrayList (2);
bc.add (new DERValue (DER.BOOLEAN, new Boolean (ca)));
if (pathLenConstraint >= 0)
bc.add (new DERValue (DER.INTEGER,
BigInteger.valueOf ((long) pathLenConstraint)));
encoded = new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, bc).getEncoded();
}
return (byte[]) encoded.clone();
}
public String toString()
{
return BasicConstraints.class.getName() + " [ isCA=" + ca +
" pathLen=" + pathLenConstraint + " ]";
}
}
@@ -0,0 +1,97 @@
/* CRLNumber.java -- CRL number extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.IOException;
import java.math.BigInteger;
public class CRLNumber extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.20");
private final BigInteger number;
// Constructor.
// -------------------------------------------------------------------------
public CRLNumber(final byte[] encoded) throws IOException
{
super(encoded);
DERValue val = DERReader.read(encoded);
if (val.getTag() != DER.INTEGER)
throw new IOException("malformed CRLNumber");
number = (BigInteger) val.getValue();
}
public CRLNumber (final BigInteger number)
{
this.number = number;
}
// Instance method.
// -------------------------------------------------------------------------
public BigInteger getNumber()
{
return number;
}
public byte[] getEncoded()
{
if (encoded == null)
{
encoded = new DERValue (DER.INTEGER, number).getEncoded();
}
return (byte[]) encoded.clone();
}
public String toString()
{
return CRLNumber.class.getName() + " [ " + number + " ]";
}
}
@@ -0,0 +1,189 @@
/* CertificatePolicies.java -- certificate policy extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.IOException;
import java.security.cert.PolicyQualifierInfo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class CertificatePolicies extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.32");
private final List policies;
private final Map policyQualifierInfos;
// Constructor.
// -------------------------------------------------------------------------
public CertificatePolicies(final byte[] encoded) throws IOException
{
super(encoded);
DERReader der = new DERReader(encoded);
DERValue pol = der.read();
if (!pol.isConstructed())
throw new IOException("malformed CertificatePolicies");
int len = 0;
LinkedList policyList = new LinkedList();
HashMap qualifierMap = new HashMap();
while (len < pol.getLength())
{
DERValue policyInfo = der.read();
if (!policyInfo.isConstructed())
throw new IOException("malformed PolicyInformation");
DERValue val = der.read();
if (val.getTag() != DER.OBJECT_IDENTIFIER)
throw new IOException("malformed CertPolicyId");
OID policyId = (OID) val.getValue();
policyList.add(policyId);
if (val.getEncodedLength() < policyInfo.getLength())
{
DERValue qual = der.read();
int len2 = 0;
LinkedList quals = new LinkedList();
while (len2 < qual.getLength())
{
val = der.read();
quals.add(new PolicyQualifierInfo(val.getEncoded()));
der.skip(val.getLength());
len2 += val.getEncodedLength();
}
qualifierMap.put(policyId, quals);
}
len += policyInfo.getEncodedLength();
}
policies = Collections.unmodifiableList(policyList);
policyQualifierInfos = Collections.unmodifiableMap(qualifierMap);
}
public CertificatePolicies (final List policies,
final Map policyQualifierInfos)
{
for (Iterator it = policies.iterator(); it.hasNext(); )
if (!(it.next() instanceof OID))
throw new IllegalArgumentException ("policies must be OIDs");
for (Iterator it = policyQualifierInfos.entrySet().iterator(); it.hasNext();)
{
Map.Entry e = (Map.Entry) it.next();
if (!(e.getKey() instanceof OID) || !policies.contains (e.getKey()))
throw new IllegalArgumentException
("policyQualifierInfos keys must be OIDs");
if (!(e.getValue() instanceof List))
throw new IllegalArgumentException
("policyQualifierInfos values must be Lists of PolicyQualifierInfos");
for (Iterator it2 = ((List) e.getValue()).iterator(); it.hasNext(); )
if (!(it2.next() instanceof PolicyQualifierInfo))
throw new IllegalArgumentException
("policyQualifierInfos values must be Lists of PolicyQualifierInfos");
}
this.policies = Collections.unmodifiableList (new ArrayList (policies));
this.policyQualifierInfos = Collections.unmodifiableMap
(new HashMap (policyQualifierInfos));
}
// Instance methods.
// -------------------------------------------------------------------------
public List getPolicies()
{
return policies;
}
public List getPolicyQualifierInfos(OID oid)
{
return (List) policyQualifierInfos.get(oid);
}
public byte[] getEncoded()
{
if (encoded == null)
{
List pol = new ArrayList (policies.size());
for (Iterator it = policies.iterator(); it.hasNext(); )
{
OID policy = (OID) it.next();
List qualifiers = getPolicyQualifierInfos (policy);
List l = new ArrayList (qualifiers == null ? 1 : 2);
l.add (new DERValue (DER.OBJECT_IDENTIFIER, policy));
if (qualifiers != null)
{
List ll = new ArrayList (qualifiers.size());
for (Iterator it2 = qualifiers.iterator(); it.hasNext(); )
{
PolicyQualifierInfo info = (PolicyQualifierInfo) it2.next();
try
{
ll.add (DERReader.read (info.getEncoded()));
}
catch (IOException ioe)
{
}
}
l.add (new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, ll));
}
pol.add (new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, l));
}
encoded = new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, pol).getEncoded();
}
return (byte[]) encoded.clone();
}
public String toString()
{
return CertificatePolicies.class.getName() + " [ policies=" + policies +
" policyQualifierInfos=" + policyQualifierInfos + " ]";
}
}
@@ -0,0 +1,95 @@
/* ExtendedKeyUsage.java -- the extended key usage extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class ExtendedKeyUsage extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.37");
private final List purposeIds;
// Constructor.
// -------------------------------------------------------------------------
public ExtendedKeyUsage(final byte[] encoded) throws IOException
{
super(encoded);
DERReader der = new DERReader(encoded);
DERValue usageList = der.read();
if (!usageList.isConstructed())
throw new IOException("malformed ExtKeyUsageSyntax");
int len = 0;
purposeIds = new LinkedList();
while (len < usageList.getLength())
{
DERValue val = der.read();
if (val.getTag() != DER.OBJECT_IDENTIFIER)
throw new IOException("malformed KeyPurposeId");
purposeIds.add(val.getValue());
len += val.getEncodedLength();
}
}
// Instance method.
// -------------------------------------------------------------------------
public List getPurposeIds()
{
return Collections.unmodifiableList(purposeIds);
}
public String toString()
{
return ExtendedKeyUsage.class.getName() + " [ " + purposeIds + " ]";
}
}
@@ -0,0 +1,289 @@
/* Extension.java -- an X.509 certificate or CRL extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.x509.Util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Extension
{
// Fields.
// -------------------------------------------------------------------------
private static final boolean DEBUG = false;
private static void debug(String msg)
{
System.err.print(">> Extension: ");
System.err.println(msg);
}
/**
* This extension's object identifier.
*/
protected final OID oid;
/**
* The criticality flag.
*/
protected final boolean critical;
/**
* Whether or not this extension is locally supported.
*/
protected boolean isSupported;
/**
* The extension value.
*/
protected final Value value;
/**
* The DER encoded form.
*/
protected byte[] encoded;
// Constructors.
// -------------------------------------------------------------------------
public Extension(byte[] encoded) throws IOException
{
this.encoded = (byte[]) encoded.clone();
DERReader der = new DERReader(encoded);
// Extension ::= SEQUENCE {
DERValue val = der.read();
if (DEBUG) debug("read val tag == " + val.getTag() + " len == " + val.getLength());
if (!val.isConstructed())
throw new IOException("malformed Extension");
// extnID OBJECT IDENTIFIER,
val = der.read();
if (val.getTag() != DER.OBJECT_IDENTIFIER)
throw new IOException("expecting OBJECT IDENTIFIER");
oid = (OID) val.getValue();
if (DEBUG) debug("read oid == " + oid);
// critical BOOLEAN DEFAULT FALSE,
val = der.read();
if (val.getTag() == DER.BOOLEAN)
{
critical = ((Boolean) val.getValue()).booleanValue();
val = der.read();
}
else
critical = false;
if (DEBUG) debug("is critical == " + critical);
// extnValue OCTET STRING }
if (val.getTag() != DER.OCTET_STRING)
throw new IOException("expecting OCTET STRING");
byte[] encval = (byte[]) val.getValue();
isSupported = true;
if (oid.equals(AuthorityKeyIdentifier.ID))
{
value = new AuthorityKeyIdentifier(encval);
}
else if (oid.equals(SubjectKeyIdentifier.ID))
{
value = new SubjectKeyIdentifier(encval);
}
else if (oid.equals(KeyUsage.ID))
{
value = new KeyUsage(encval);
}
else if (oid.equals(PrivateKeyUsagePeriod.ID))
{
value = new PrivateKeyUsagePeriod(encval);
}
else if (oid.equals(CertificatePolicies.ID))
{
value = new CertificatePolicies(encval);
}
else if (oid.equals (PolicyConstraint.ID))
{
value = new PolicyConstraint (encval);
}
else if (oid.equals(PolicyMappings.ID))
{
value = new PolicyMappings(encval);
}
else if (oid.equals(SubjectAlternativeNames.ID))
{
value = new SubjectAlternativeNames(encval);
}
else if (oid.equals(IssuerAlternativeNames.ID))
{
value = new IssuerAlternativeNames(encval);
}
else if (oid.equals(BasicConstraints.ID))
{
value = new BasicConstraints(encval);
}
else if (oid.equals(ExtendedKeyUsage.ID))
{
value = new ExtendedKeyUsage(encval);
}
else if (oid.equals(CRLNumber.ID))
{
value = new CRLNumber(encval);
}
else if (oid.equals(ReasonCode.ID))
{
value = new ReasonCode(encval);
}
else
{
value = new Value(encval);
isSupported = false;
}
if (DEBUG) debug("read value == " + value);
}
public Extension (final OID oid, final Value value, final boolean critical)
{
this.oid = oid;
this.value = value;
this.critical = critical;
isSupported = true;
}
// Instance methods.
// -------------------------------------------------------------------------
public OID getOid()
{
return oid;
}
public boolean isCritical()
{
return critical;
}
public boolean isSupported()
{
return isSupported;
}
public Value getValue()
{
return value;
}
public byte[] getEncoded()
{
if (encoded == null)
encode();
return (byte[]) encoded.clone();
}
public String toString()
{
return Extension.class.getName() + " [ id=" + oid + " critical=" +
critical + " value=" + value + " ]";
}
public DERValue getDerValue()
{
List ext = new ArrayList (3);
ext.add (new DERValue (DER.OBJECT_IDENTIFIER, oid));
ext.add (new DERValue (DER.BOOLEAN, new Boolean (critical)));
ext.add (new DERValue (DER.OCTET_STRING, value.getEncoded()));
return new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, ext);
}
// Own methods.
// -------------------------------------------------------------------------
private void encode()
{
encoded = getDerValue().getEncoded();
}
// Inner class.
// -------------------------------------------------------------------------
public static class Value
{
// Fields.
// -----------------------------------------------------------------------
protected byte[] encoded;
// Constructor.
// -----------------------------------------------------------------------
public Value(byte[] encoded)
{
this.encoded = (byte[]) encoded.clone();
}
protected Value() { }
// Instance methods.
// -----------------------------------------------------------------------
public byte[] getEncoded()
{
return (byte[]) encoded;
}
public boolean equals(Object o)
{
if (!(o instanceof Value))
return false;
return Arrays.equals(encoded, ((Value) o).encoded);
}
public String toString()
{
return Util.toHexString(encoded, ':');
}
}
}
@@ -0,0 +1,155 @@
/* GeneralNames.java -- the GeneralNames object
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.x509.X500DistinguishedName;
import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class GeneralNames
{
// Instance methods.
// -------------------------------------------------------------------------
public static final int OTHER_NAME = 0;
public static final int RFC822_NAME = 1;
public static final int DNS_NAME = 2;
public static final int X400_ADDRESS = 3;
public static final int DIRECTORY_NAME = 4;
public static final int EDI_PARTY_NAME = 5;
public static final int URI = 6;
public static final int IP_ADDRESS = 7;
public static final int REGISTERED_ID = 8;
private List names;
// Constructor.
// -------------------------------------------------------------------------
public GeneralNames(final byte[] encoded) throws IOException
{
names = new LinkedList();
DERReader der = new DERReader(encoded);
DERValue nameList = der.read();
if (!nameList.isConstructed())
throw new IOException("malformed GeneralNames");
int len = 0;
while (len < nameList.getLength())
{
DERValue name = der.read();
List namePair = new ArrayList(2);
if (name.getTagClass() != DER.APPLICATION)
throw new IOException("malformed GeneralName");
namePair.add(new Integer(name.getTag()));
DERValue val = null;
switch (name.getTag())
{
case RFC822_NAME:
case DNS_NAME:
case X400_ADDRESS:
case URI:
namePair.add(new String((byte[]) name.getValue()));
break;
case OTHER_NAME:
case EDI_PARTY_NAME:
namePair.add(name.getValue());
break;
case DIRECTORY_NAME:
byte[] b = name.getEncoded();
b[0] = (byte) (DER.CONSTRUCTED|DER.SEQUENCE);
namePair.add(new X500DistinguishedName(b).toString());
break;
case IP_ADDRESS:
namePair.add(InetAddress.getByAddress((byte[]) name.getValue())
.getHostAddress());
break;
case REGISTERED_ID:
byte[] bb = name.getEncoded();
bb[0] = (byte) DER.OBJECT_IDENTIFIER;
namePair.add(new OID(bb).toString());
break;
default:
throw new IOException("unknown tag " + name.getTag());
}
names.add(namePair);
len += name.getEncodedLength();
}
}
// Instance methods.
// -------------------------------------------------------------------------
public List getNames()
{
List l = new ArrayList(names.size());
for (Iterator it = names.iterator(); it.hasNext(); )
{
List ll = (List) it.next();
List pair = new ArrayList(2);
pair.add(ll.get(0));
if (ll.get(1) instanceof byte[])
pair.add(((byte[]) ll.get(1)).clone());
else
pair.add(ll.get(1));
l.add(Collections.unmodifiableList(pair));
}
return Collections.unmodifiableList(l);
}
public String toString()
{
return GeneralNames.class.getName() + " [ " + names + " ]";
}
}
@@ -0,0 +1,77 @@
/* IssuerAlternatuveNames.java -- issuer alternative names extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import java.io.IOException;
import java.util.List;
public class IssuerAlternativeNames extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.18");
private final GeneralNames names;
// Constructor.
// -------------------------------------------------------------------------
public IssuerAlternativeNames(final byte[] encoded) throws IOException
{
super(encoded);
names = new GeneralNames(encoded);
}
// Instance method.
// -------------------------------------------------------------------------
public List getNames()
{
return names.getNames();
}
public String toString()
{
return IssuerAlternativeNames.class.getName() + " [ " + names + " ]";
}
}
@@ -0,0 +1,92 @@
/* KeyUsage.java -- the key usage extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.BitString;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.IOException;
public class KeyUsage extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.15");
public static final int DIGITAL_SIGNATURE = 0;
public static final int NON_REPUDIATION = 1;
public static final int KEY_ENCIPHERMENT = 2;
public static final int DATA_ENCIPHERMENT = 3;
public static final int KEY_AGREEMENT = 4;
public static final int KEY_CERT_SIGN = 5;
public static final int CRL_SIGN = 6;
public static final int ENCIPHER_ONLY = 7;
public static final int DECIPHER_ONLY = 8;
private final BitString keyUsage;
// Constructor.
// -------------------------------------------------------------------------
public KeyUsage(final byte[] encoded) throws IOException
{
super(encoded);
DERValue val = DERReader.read(encoded);
if (val.getTag() != DER.BIT_STRING)
throw new IOException("malformed KeyUsage");
keyUsage = (BitString) val.getValue();
}
// Instance methods.
// -------------------------------------------------------------------------
public BitString getKeyUsage()
{
return keyUsage;
}
public String toString()
{
return KeyUsage.class.getName() + " [ " + keyUsage + " ]";
}
}
@@ -0,0 +1,107 @@
/* PolicyConstraint.java -- policyConstraint extension
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.IOException;
import java.math.BigInteger;
public class PolicyConstraint extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID ("2.5.29.36");
private final int requireExplicitPolicy;
private final int inhibitPolicyMapping;
// Constructors.
// -------------------------------------------------------------------------
public PolicyConstraint (final byte[] encoded) throws IOException
{
super (encoded);
int rpc = -1, ipm = -1;
DERReader der = new DERReader(encoded);
DERValue pc = der.read();
if (!pc.isConstructed())
throw new IOException("malformed PolicyConstraints");
DERValue val;
int len = pc.getLength();
while (len > 0)
{
val = der.read();
if (val.getTag() == 0)
rpc = new BigInteger ((byte[]) val.getValue()).intValue();
else if (val.getTag() == 1)
ipm = new BigInteger ((byte[]) val.getValue()).intValue();
else
throw new IOException ("invalid policy constraint");
len -= val.getEncodedLength();
}
requireExplicitPolicy = rpc;
inhibitPolicyMapping = ipm;
}
// Instance methods.
// -------------------------------------------------------------------------
public int getRequireExplicitPolicy()
{
return requireExplicitPolicy;
}
public int getInhibitPolicyMapping()
{
return inhibitPolicyMapping;
}
public String toString()
{
return PolicyConstraint.class.getName() + " [ requireExplicitPolicy=" +
requireExplicitPolicy + " inhibitPolicyMapping=" + inhibitPolicyMapping
+ " ]";
}
}
@@ -0,0 +1,104 @@
/* PolicyMappings.java -- policy mappings extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class PolicyMappings extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.33");
private final Map mappings;
// Constructor.
// -------------------------------------------------------------------------
public PolicyMappings(final byte[] encoded) throws IOException
{
super(encoded);
DERReader der = new DERReader(encoded);
DERValue maps = der.read();
if (!maps.isConstructed())
throw new IOException("malformed PolicyMappings");
int len = 0;
HashMap _mappings = new HashMap();
while (len < maps.getLength())
{
DERValue map = der.read();
if (!map.isConstructed())
throw new IOException("malformed PolicyMapping");
DERValue val = der.read();
if (val.getTag() != DER.OBJECT_IDENTIFIER)
throw new IOException("malformed PolicyMapping");
OID issuerPolicy = (OID) val.getValue();
val = der.read();
if (val.getTag() != DER.OBJECT_IDENTIFIER)
throw new IOException("malformed PolicyMapping");
OID subjectPolicy = (OID) val.getValue();
_mappings.put(issuerPolicy, subjectPolicy);
len += map.getEncodedLength();
}
mappings = Collections.unmodifiableMap(_mappings);
}
// Instance methods.
// -------------------------------------------------------------------------
public OID getSubjectDomainPolicy(OID issuerDomainPolicy)
{
return (OID) mappings.get(issuerDomainPolicy);
}
public String toString()
{
return PolicyMappings.class.getName() + " [ " + mappings + " ]";
}
}
@@ -0,0 +1,105 @@
/* PrivateKeyUsagePeriod.java -- private key usage period extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.IOException;
import java.util.Date;
public class PrivateKeyUsagePeriod extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.16");
private final Date notBefore;
private final Date notAfter;
// Constructor.
// -------------------------------------------------------------------------
public PrivateKeyUsagePeriod(final byte[] encoded) throws IOException
{
super(encoded);
DERReader der = new DERReader(encoded);
DERValue val = der.read();
if (!val.isConstructed())
throw new IOException("malformed PrivateKeyUsagePeriod");
if (val.getLength() > 0)
val = der.read();
if (val.getTagClass() == DER.APPLICATION || val.getTag() == 0)
{
notBefore = (Date) val.getValueAs (DER.GENERALIZED_TIME);
val = der.read();
}
else
notBefore = null;
if (val.getTagClass() == DER.APPLICATION || val.getTag() == 1)
{
notAfter = (Date) val.getValueAs (DER.GENERALIZED_TIME);
}
else
notAfter = null;
}
// Instance methods.
// -------------------------------------------------------------------------
public Date getNotBefore()
{
return notBefore != null ? (Date) notBefore.clone() : null;
}
public Date getNotAfter()
{
return notAfter != null ? (Date) notAfter.clone() : null;
}
public String toString()
{
return PrivateKeyUsagePeriod.class.getName() + " [ notBefore=" + notBefore
+ " notAfter=" + notAfter + " ]";
}
}
@@ -0,0 +1,85 @@
/* ReasonCode.java -- a reason code for a certificate revocation.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.IOException;
import java.math.BigInteger;
public class ReasonCode extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.21");
public final int reason;
// Constructor.
// -------------------------------------------------------------------------
public ReasonCode(final byte[] encoded) throws IOException
{
super(encoded);
DERValue val = DERReader.read(encoded);
if (val.getTag() != DER.ENUMERATED)
throw new IOException("malformed CRLReason");
reason = ((BigInteger) val.getValue()).intValue();
if (reason < 0 || reason == 7 || reason > 10)
throw new IOException("illegal reason: " + reason);
}
// Instance method.
// -------------------------------------------------------------------------
public int getReasonCode()
{
return reason;
}
public String toString()
{
return ReasonCode.class.getName() + " [ " + reason + " ]";
}
}
@@ -0,0 +1,77 @@
/* SubjectAlternatuveNames.java -- subject alternative names extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import java.io.IOException;
import java.util.List;
public class SubjectAlternativeNames extends Extension.Value
{
// Constants and fields.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.17");
private final GeneralNames names;
// Constructor.
// -------------------------------------------------------------------------
public SubjectAlternativeNames(final byte[] encoded) throws IOException
{
super(encoded);
names = new GeneralNames(encoded);
}
// Instance method.
// -------------------------------------------------------------------------
public List getNames()
{
return names.getNames();
}
public String toString()
{
return SubjectAlternativeNames.class.getName() + " [ " + names + " ]";
}
}
@@ -0,0 +1,84 @@
/* SubjectKeyIdentifier.java -- subject key identifier extension.
Copyright (C) 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.security.x509.ext;
import gnu.java.security.OID;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.x509.Util;
import java.io.IOException;
public class SubjectKeyIdentifier extends Extension.Value
{
// Constant.
// -------------------------------------------------------------------------
public static final OID ID = new OID("2.5.29.14");
private final byte[] keyIdentifier;
// Constructor.
// -------------------------------------------------------------------------
public SubjectKeyIdentifier(final byte[] encoded) throws IOException
{
super(encoded);
DERValue val = DERReader.read(encoded);
if (val.getTag() != DER.OCTET_STRING)
throw new IOException("malformed SubjectKeyIdentifier");
keyIdentifier = (byte[]) val.getValue();
}
// Instance methods.
// -------------------------------------------------------------------------
public byte[] getKeyIdentifier()
{
return (byte[]) keyIdentifier.clone();
}
public String toString()
{
return SubjectKeyIdentifier.class.getName() + " [ " +
Util.toHexString (keyIdentifier, ':') + " ]";
}
}
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in gnu.java.security.x509.ext package.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - gnu.java.security.x509.ext</title></head>
<body>
<p></p>
</body>
</html>
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in gnu.java.security.x509 package.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - gnu.java.security.x509</title></head>
<body>
<p></p>
</body>
</html>