Replace NtruSign with GMSS which uses smaller public keys and inspires more confidence security-wise

This commit is contained in:
HungryHobo
2011-03-24 04:38:21 +00:00
parent 63dc3ea208
commit d532c6117d
172 changed files with 34829 additions and 177 deletions

View File

@@ -63,7 +63,7 @@
<div class="main">
<h2><ib:message key="Please wait..."/></h2>
<img src="images/wait.gif"/>
<ib:message key="The Email Identity is being generated."/>
<ib:message key="The Email Identity is being generated. This can take several minutes."/>
</div>
</c:when>
<%-- This is where the actual identity generation takes place --%>

View File

@@ -124,6 +124,7 @@
<lib file="${lib}/i2pbote.jar"/>
<lib file="${lib}/mailapi.jar"/>
<lib file="${lib}/bcprov-ecc-jdk16-145.jar"/>
<lib file="ant_build/lib/flexi-gmss-1.7p1.jar"/>
<zipfileset dir="WebContent/images" prefix="images"/>
</war>
@@ -133,10 +134,17 @@
</exec>
</target>
<target name="jar" depends="compile,precompilejsp,bundle">
<target name="flexijar" depends="compile">
<mkdir dir="ant_build/lib"/>
<jar destfile="ant_build/lib/flexi-gmss-1.7p1.jar">
<fileset dir="ant_build/classes" includes="de/flexiprovider/** codec/**"/>
</jar>
</target>
<target name="jar" depends="compile,flexijar,precompilejsp,bundle">
<mkdir dir="ant_build" />
<jar destfile="${lib}/i2pbote.jar">
<fileset dir="ant_build/classes" excludes="i2p/bote/web/** i2p/bote/jsp/** org/apache/jsp/** **/*Test.class"/>
<fileset dir="ant_build/classes" excludes="i2p/bote/web/** i2p/bote/jsp/** org/apache/jsp/** de/flexiprovider/** codec/** **/*Test.class"/>
<fileset dir="src" includes="i2p/bote/network/built-in-peers.txt"/>
</jar>
</target>
@@ -177,6 +185,13 @@
<arg value="plugin/plugin.tmp/lib/bcprov-ecc-jdk16-145.jar.pack"/>
<arg value="${lib}/bcprov-ecc-jdk16-145.jar"/>
</exec>
<exec executable="pack200" failonerror="true">
<arg value="--no-gzip"/>
<arg value="--effort=9"/>
<arg value="--modification-time=latest"/>
<arg value="plugin/plugin.tmp/lib/flexi-gmss-1.7p1.jar.pack"/>
<arg value="ant_build/lib/flexi-gmss-1.7p1.jar"/>
</exec>
<copy file="WebContent/WEB-INF/lib/encrypt.sh" todir="plugin/plugin.tmp/lib"/>
<copy file="WebContent/WEB-INF/lib/decrypt.sh" todir="plugin/plugin.tmp/lib"/>
@@ -220,7 +235,7 @@
</target>
<!-- same as war but without the library jars -->
<target name="pluginwar" depends="compile,precompilejsp,bundle">
<target name="pluginwar" depends="compile,flexijar,precompilejsp,bundle">
<mkdir dir="ant_build" />
<war destfile="i2pbote-plugin.war" webxml="ant_build/web.xml">
<classes dir="ant_build/classes" includes="i2p/bote/web/** i2p/bote/jsp/** org/apache/jsp/**" />

View File

@@ -607,6 +607,11 @@ The file format is:
mailapi.jar Part of JavaMail
src/SevenZip/ An LZMA implementation from http://www.7-zip.org/sdk.html
src/net/sf/ntru An NTRU implementation from http://sf.net/projects/ntru/
de/flexiprovider and codec/ A stripped down and patched version of the FlexiProvider
sources (http://www.flexiprovider.de/), containing only the
classes needed for GMSS.
The patch consists of a modified de.flexiprovider.core.CoreRegistry
so there are no dependencies on classes not related to GMSS.
src/com/lambdaworks/crypto/ An scrypt implementation from https://github.com/wg/scrypt/

View File

@@ -1 +1 @@
webapps.i2pbote.classpath=$I2P/lib/jstl.jar,$I2P/lib/standard.jar,$PLUGIN/lib/i2pbote.jar,$PLUGIN/lib/mailapi.jar,$PLUGIN/lib/bcprov-ecc-jdk16-145.jar
webapps.i2pbote.classpath=$I2P/lib/jstl.jar,$I2P/lib/standard.jar,$PLUGIN/lib/i2pbote.jar,$PLUGIN/lib/mailapi.jar,$PLUGIN/lib/bcprov-ecc-jdk16-145.jar,$PLUGIN/lib/flexi-gmss-1.7p1.jar

View File

@@ -0,0 +1,106 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec;
/**
* Thrown if a code is recognized as being corrupted for instance due to
* transmission errors.
*
* @author Volker Roth
* @version $Id: CorruptedCodeException.java,v 1.3 2005/04/06 09:24:51 flautens
* Exp $
* @see Base64
*/
public class CorruptedCodeException extends Exception {
/**
* Creates an exception instance with no particular message.
*/
public CorruptedCodeException() {
super();
}
/**
* Creates an exception instance with the given message.
*
* @param message
* The message string describing the reason for this
* exception.
*/
public CorruptedCodeException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,162 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec;
/**
* Signals an inconsistent object state. Objects can enter inconsistent states
* for instance if an exception is caught that shouldn't happen. Such exceptions
* can occur due to unexpected exceptions from other code or internal errors.
* <p>
* A typical example is when an application knows that a specific error
* condition cannot occur because the preconditions required for a successful
* completion of a method call are met, but an exception is thrown nevertheless.
* In this case, the exception can be caught and wrapped into an exception of
* this class in order to pass on the original cause of the exception to code
* further up the calling stack.
*
* @author Volker Roth
* @version "$Id: InconsistentStateException.java,v 1.3 2005/04/06 09:33:26
* flautens Exp $"
*/
public class InconsistentStateException extends RuntimeException {
/**
* The wrapped exception
*/
private Exception e_;
/**
* Creates an instance.
*/
public InconsistentStateException() {
}
/**
* Creates an instance with the given message.
*
* @param message
* The message.
*/
public InconsistentStateException(String message) {
super(message);
}
/**
* Creates an exception that wraps around the given exception. The message
* of this exception is set to the one of the given exception. The given
* exception must not be <code>null</code>.
*
* @param e
* The exception that shall be wrapped in this one.
* @throws NullPointerException
* if the given exception is <code>null</code>.
*/
public InconsistentStateException(Exception e) {
super(e.getMessage());
e_ = e;
}
/**
* Returns the wrapped exception or <code>this</code> if no exception is
* wrapped in this one.
*
* @return The wrapped exception or <code>this</code> if there is no
* exception wrapped by this one.
*/
public Exception getException() {
if (e_ == null) {
return this;
}
return e_;
}
/**
* Prints the stack trace of this exception. If this exception has a wrapped
* exception then the stack trace of the wrapped exception is printed
* instead of the one of this exception. Since this exception was created in
* the course of catching the wrapped exception, the location where this
* exception was thrown is included in the stack trace of the wrapped
* exception.
*/
public void printStackTrace() {
if (e_ == null) {
super.printStackTrace();
} else {
e_.printStackTrace();
}
}
}

369
src/codec/asn1/ASN1.java Normal file
View File

@@ -0,0 +1,369 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* Defines various constants used with ASN.1 such as the tag and type class
* identifiers. The classes in this package are modelled along the lines of
* ITU-T Recommendations X.680, X.681, X.682, X.690, and X.691. From now on we
* assume the reader is familiar with ASN.1, BER, and DER.
* <p>
*
* This package defines a number of primitive types as specified by the basic
* syntax in X.680. Based on these primitive types more complex types can be
* created. We refer to these types as <i>compound types</i> or <i> structures</i>.
* Below, we discuss how such types are constructed, encoded and decoded using
* the classes in this package.
* <p>
*
* For instance the type <tt>PrivateKeyInfo</tt> is defined in PKCS#8 as
* follows using ASN.1: <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>
*
* This type can be created as follows based on the classes in this package:
* <blockquote>
*
* <pre>
* public class PrivateKeyInfo extends ASN1Sequence
* {
* public PrivateKeyInfo()
* {
* add(new ASN1Integer());
* add(new AlgorithmIdentifier()); // Detailed below
* add(new ASN1OctetString());
* add(new ASN1TaggedType(
* 0, new ASN1SetOf(Attribute.class), false, true);
* }
* ...
* }
* </pre>
*
* </blockquote> The {@link ASN1TaggedType tagged type} allows to define types
* of the ASN.1 tag class UNIVERSAL, CONTEXT SPECIFIC, APPLICATION, and PRIVATE.
* The constructor shown above is a convenience constructor that assumes the
* class is CONTEXT SPECIFIC. The third parameter specifies that the tagging is
* not EXPLICIT (hence IMPLICIT as required by the definition above), and the
* fourth parameter specifies that <tt>attributes</tt> is OPTIONAL.
* <p>
*
* The interface {@link ASN1Type ASN1Type} specifies a number of methods to
* declare types as OPTIONAL, IMPLICIT or EXPLICIT. In principle, ASN.1
* structures can be modelled almost one to one using the classes in this
* package.
* <p>
*
* Individual types also offer setter methods and constructors that allow to
* preset certain values as the values of the ASN.1 types from native Java types
* such as String, int, byte[] etc.
* <p>
*
* Once, a primitive type or a compound type <tt>x</tt> has been defined and
* initialized it can be encoded in a number of ways. The first step is to
* choose an {@link Encoder encoder}. One example encoder is the
* {@link DEREncoder DEREncoder}. This encoder encodes types according to the
* Distinguished Encoding Rules, a subset of the Basic Encoding Rules defined in
* the ITU-T Recommendations. Encoding to a file is simple, the following code
* snippet shows how to do it: <blockquote>
*
* <pre>
* DEREncoder enc;
* enc = new DEREncoder(new FileOutputStream(&quot;code.der&quot;));
* enc.writeType(x);
* enc.close();
* </pre>
*
* </blockquote> There is nothing more to it. However, only types not declared
* as OPTIONAL are written to the stream. Hence, the type <tt>
* attributes</tt>
* mentioned above is not written.
* <p>
*
* Why then is it declared as OPTIONAL? Answer, by convention in this package
* (and by reason) the default constructor is meant to initialize a type for
* decoding. In a code the <tt>
* attributes</tt> type can be encountered. The
* decoder clears the OPTIONAL flag of types it encounters during decoding so it
* is clear which types were present and which were not. If a type is only used
* for encoding and not for decoding then the OPTIONAL types not required can be
* omitted.
*
* <pre>
* AlgorithmIdentifier ::= SEQUENCE{
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* }
* </pre>
*
* @author Volker Roth
* @version "$Id: ASN1.java,v 1.4 2005/03/22 16:04:37 flautens Exp $"
*/
public final class ASN1 extends Object {
/**
* DOCUMENT ME!
*/
public static final int TAG_EOC = 0;
/**
* DOCUMENT ME!
*/
public static final int TAG_BOOLEAN = 1;
/**
* DOCUMENT ME!
*/
public static final int TAG_INTEGER = 2;
/**
* DOCUMENT ME!
*/
public static final int TAG_BITSTRING = 3;
/**
* DOCUMENT ME!
*/
public static final int TAG_OCTETSTRING = 4;
/**
* DOCUMENT ME!
*/
public static final int TAG_NULL = 5;
/**
* DOCUMENT ME!
*/
public static final int TAG_OID = 6;
/**
* DOCUMENT ME!
*/
public static final int TAG_REAL = 9;
/**
* DOCUMENT ME!
*/
public static final int TAG_ENUMERATED = 10;
/**
* DOCUMENT ME!
*/
public static final int TAG_UTF8STRING = 12;
/**
* DOCUMENT ME!
*/
public static final int TAG_SEQUENCE = 16;
/**
* DOCUMENT ME!
*/
public static final int TAG_SET = 17;
/**
* DOCUMENT ME!
*/
public static final int TAG_NUMERICSTRING = 18;
/**
* DOCUMENT ME!
*/
public static final int TAG_PRINTABLESTRING = 19;
/**
* DOCUMENT ME!
*/
public static final int TAG_T61STRING = 20;
/**
* DOCUMENT ME!
*/
public static final int TAG_VIDEOTEXTSTRING = 21;
/**
* DOCUMENT ME!
*/
public static final int TAG_IA5STRING = 22;
/**
* DOCUMENT ME!
*/
public static final int TAG_UTCTIME = 23;
/**
* DOCUMENT ME!
*/
public static final int TAG_GENERALIZEDTIME = 24;
/**
* DOCUMENT ME!
*/
public static final int TAG_GRAPHICSTRING = 25;
/**
* DOCUMENT ME!
*/
public static final int TAG_VISIBLESTRING = 26;
/**
* DOCUMENT ME!
*/
public static final int TAG_GENERALSTRING = 27;
/**
* DOCUMENT ME!
*/
public static final int TAG_UNIVERSALSTRING = 28;
/**
* DOCUMENT ME!
*/
public static final int TAG_BMPSTRING = 30;
/**
* DOCUMENT ME!
*/
public static final int TAG_MASK = 0x1f;
/**
* DOCUMENT ME!
*/
public static final int TAG_LONGFORM = 0x1f;
/**
* DOCUMENT ME!
*/
public static final int CLASS_UNIVERSAL = 0x00;
/**
* DOCUMENT ME!
*/
public static final int CLASS_APPLICATION = 0x40;
/**
* DOCUMENT ME!
*/
public static final int CLASS_CONTEXT = 0x80;
/**
* DOCUMENT ME!
*/
public static final int CLASS_PRIVATE = 0xc0;
/**
* DOCUMENT ME!
*/
public static final int CLASS_MASK = 0xc0;
/**
* DOCUMENT ME!
*/
public static final int PRIMITIVE = 0x00;
/**
* DOCUMENT ME!
*/
public static final int CONSTRUCTED = 0x20;
/**
* DOCUMENT ME!
*/
public static final int LENGTH_LONGFORM = 0x80;
/**
* DOCUMENT ME!
*/
public static final int LENGTH_MASK = 0x7f;
/**
* No-one can instantiate this class.
*/
private ASN1() {
}
}

View File

@@ -0,0 +1,412 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* Represents an abstract collection of ASN.1 types such as a SEQUENCE or a SET.
* Since this class inherits from the Collection framework class ArrayList,
* ASN.1 types may be added conveniently just as object instances are added to a
* list.
* <p>
*
* Please note that constraints of collections are validated before encoding and
* after decoding. Invalid modification of a collection type can be detected on
* importing and exporting abstract collections. On DER encoding a collection
* its constraint is validated twice since the DER encoding is a two-pass
* process.
*
* @author Volker Roth
* @version "$Id: ASN1AbstractCollection.java,v 1.5 2005/03/22 16:12:45 flautens
* Exp $"
*/
public abstract class ASN1AbstractCollection extends ArrayList implements
ASN1Collection, Cloneable, Externalizable {
/**
* DOCUMENT ME!
*/
private boolean optional_ = false;
/**
* DOCUMENT ME!
*/
private boolean explicit_ = true;
/**
* DOCUMENT ME!
*/
private Constraint constraint_;
/**
* Abstract method declarations.
*
* @return corresponding ASN1 tag
*/
public abstract int getTag();
/**
* Method declarations with default implementation.
*/
public ASN1AbstractCollection() {
super();
}
/**
* Creates an instance with the given capacity.
*
* @param capacity
* The capacity.
*/
public ASN1AbstractCollection(int capacity) {
super(capacity);
}
/**
* Returns the Java type that corresponds to this ASN.1 type.
*
* @return The collection used internally for storing the elements in this
* constructed ASN.1 type.
*/
public Object getValue() {
return this;
}
/**
* Returns the Java type that corresponds to this ASN.1 type.
*
* @return The collection used internally for storing the elements in this
* constructed ASN.1 type.
*/
public Collection getCollection() {
return this;
}
/**
* Optional types may be present in an encoding but they need not be.
*
* @param optional
* <code>true</code> iff this type is optional.
*/
public void setOptional(boolean optional) {
optional_ = optional;
}
/**
* @return <code>true</code> iff this type is optional.
*/
public boolean isOptional() {
return optional_;
}
/**
* This default implementation returns {@link ASN1#CLASS_UNIVERSAL
* UNIVERSAL}.
*
* @return The class of the ASN.1 tag.
*/
public int getTagClass() {
return ASN1.CLASS_UNIVERSAL;
}
/**
* Sets the tagging of this type as either EXPLICIT or IMPLICIT. The default
* is EXPLICIT. Encoders skip the encoding of identifier octets for types
* that are declared as IMPLICIT.
*
* @param explicit
* <code>true</code> if this type shall be tagged EXPLICIT
* and <code>false</code> if it shall be encoded IMPLICIT.
*/
public void setExplicit(boolean explicit) {
explicit_ = explicit;
}
/**
*
* @return <code>true</code> if this type is tagged EXPLICIT and
* <code>false</code> if it is tagged IMPLICIT.
*/
public boolean isExplicit() {
return explicit_;
}
/**
* Sets the {@link Constraint Constraint} of this type. For instance an
* ASN.1 INTEGER might be constrained to a certain range such as INTEGER
* (0..99). <code>null</code> can be passed as a constraint which disables
* constraint checking.
*
* @param constraint
* The {@link Constraint Constraint} of this type.
*/
public void setConstraint(Constraint constraint) {
constraint_ = constraint;
}
/**
* Returns the {@link Constraint Constraint} of this type or
* <code>null</code> if there is none.
*
* @return The Constraint or <code>null</code>.
*/
public Constraint getConstraint() {
return constraint_;
}
/**
* Checks the constraint on this type if it is set. Otherwise this method
* returns silently.
*
* @throws ConstraintException
* if this type is not in the appropriate range of values.
*/
public void checkConstraints() throws ConstraintException {
if (constraint_ != null) {
constraint_.constrain(this);
}
}
/**
* Returns <code>true</code> if the given tag and tag class matches the
* tag and tag class of this instance. This method is used primarily by
* decoders and variable types such as {@link ASN1Choice ASN1Choice} and
* {@link ASN1OpenType ASN1OpenType}. It enables decoders to query a
* variable type whether a decoded type is accepted.
* <p>
*
* This method provides a default implementation that matches the given tag
* and tag class against the values returned by {@link #getTag getTag} and
* {@link #getTagClass getTagClass} respectively.
*
* @param tag
* The tag to compare with.
* @param tagclass
* The tag class to compare with.
* @return <code>true</code> if the given tag and tag class matches this
* type and <code>false</code> otherwise.
*/
public boolean isType(int tag, int tagclass) {
if ((getTag() == tag) && (getTagClass() == tagclass)) {
return true;
}
return false;
}
/**
* Writes this collection to the given {@link Encoder encoder}.
*
* @param enc
* The encoder to write this type to.
*/
public void encode(Encoder enc) throws ASN1Exception, IOException {
checkConstraints();
enc.writeCollection(this);
}
/**
* Reads this collection from the given {@link Decoder Decoder}. This type
* is initialized with the decoded data. The components of the decoded
* collection must match the components of this collection. If they do then
* the components are also initialized with the decoded values. Otherwise an
* exception is thrown.
*
* @param dec
* The decoder to read from.
*/
public void decode(Decoder dec) throws ASN1Exception, IOException {
dec.readCollection(this);
checkConstraints();
}
/**
* Prints this collection. This default implementation derives a descriptive
* name from the name of the fully qualified name of this class (or that of
* the respective subclass). The last component of the class name is
* extracted and a prefix of &quot;ASN1&quot; is removed from it. Then the
* elements contained in this collection are printed.
*
* @return The string representation of this ASN.1 collection.
*/
public String toString() {
StringBuffer buf;
Iterator i;
String s;
s = removePackageName(getClass());
buf = new StringBuffer();
buf.append(s);
if (isOptional()) {
buf.append(" OPTIONAL");
}
if (this instanceof ASN1CollectionOf) {
buf.append(" SEQUENCE OF "
+ removePackageName(((ASN1CollectionOf) this)
.getElementType()));
} else {
buf.append(" SEQUENCE ");
}
buf.append(" {\n");
for (i = iterator(); i.hasNext();) {
buf.append(i.next().toString());
buf.append("\n");
}
buf.append("}");
return buf.toString();
}
/**
* This method removes the package information from the qualified class
* name. If the remaining class name starts with 'ASN1' then this prefix is
* also removed.
*
* @param clazz
* The class to handle
* @return the shortened class name
*/
private String removePackageName(Class clazz) {
String s = clazz.getName();
int n = s.lastIndexOf('.');
if (n < 0) {
n = -1;
}
s = s.substring(n + 1);
if (s.startsWith("ASN1")) {
s = s.substring(4);
}
return s;
}
/**
* The writeExternal and readExternal methods of the Externalizable
* interface are implemented by a class to give the serializable class
* complete control over the format and contents of the stream for an object
* and its supertypes.
*
* @param out -
* the stream to write the object to
* @see java.io.Externalizable
*/
public void writeExternal(ObjectOutput out) throws IOException {
byte[] res = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
encode(new DEREncoder(baos));
res = baos.toByteArray();
baos.close();
out.write(res);
} catch (ASN1Exception e) {
throw new RuntimeException(e.toString());
}
}
/**
* The writeExternal and readExternal methods of the Externalizable
* interface are implemented by a class to give the serializable class
* complete control over the format and contents of the stream for an object
* and its supertypes.
*
* @param in -
* the stream to read data from in order to restore the
* object
* @see java.io.Externalizable
*/
public void readExternal(ObjectInput in) throws IOException {
try {
decode(new DERDecoder((ObjectInputStream) in));
} catch (ASN1Exception e) {
throw new RuntimeException(e.toString());
}
}
}

View File

@@ -0,0 +1,298 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* The root class of all ASN.1 string types including but not limited to
* IA5String, VisibleString, PrintableString, UTCTime, and GeneralizedTime.
* <p>
*
* Each string type is encoded as if it is declared as <tt>[UNIVERSAL </tt><i>x</i><tt>] IMPLICIT OCTET STRING</tt>
* where <i>x</i> is the tag number of the respective string type (see ITU-T
* Rec. X.690, paragraph 8.20.3).
* <p>
*
* There are 8 restructed string types of which 4 do not allow escape sequences,
* namely NumericString, PrintableString, VisibleString (ISO646String) and
* IA5String. TeletexString (T61String), VideotextString, GraphicString, and
* GeneralString allow the use of escape sequences. However, the srings must be
* encoded such as to use the minimum number of octets possible. All these
* strings use 1-octet representations; IA5String uses 2-octet representations
* for special characters.
* <p>
*
* Two unrestricted string types are defined in X.680, namely BMPString and
* UniversalString. BMPString uses a 2-octet representation per character and
* UniversalString uses a 4-octet representation.
* <p>
*
* Each string type represented in this package handles octets to character and
* character to octets conversion according to the general coding scheme of the
* particular string, but not neccessarily restriction to a particular character
* set. This is to be implemented through {@link Constraint constraints} that
* are added to the respective types on creation (in the constructors).
* Restriction of character sets is thus done on the Unicode character set used
* by Java.
* <p>
*
* This class implements plain 1-octet to character conversion by default. Class
* {@link ASN1BMPString ASN1BMPString} handles 2-octet conversion and class
* {@link ASN1UniversalString ASN1UniversalString} handles 4-octets conversion.
* Without reference to ISO defined character encodings these implementations
* assume that the <i>n</i>-octet tuples represent the least significant bits
* of the Unicode characters with the corresponding bits set to zero.
*
*
* @author Volker Roth
* @version "$Id: ASN1AbstractString.java,v 1.4 2004/08/26 15:08:21 pebinger Exp $"
*/
public abstract class ASN1AbstractString extends ASN1AbstractType implements
ASN1String {
private static final String DEFAULT_VALUE = "";
private String value_ = DEFAULT_VALUE;
public ASN1AbstractString() {
super();
}
/**
* Creates an instance with the given string value.
*
* This constructor calls {@link #setString setString} to set the string
* value.
*
* @param s
* The string value.
*/
public ASN1AbstractString(String s) {
setString0(s);
}
/**
* Returns the represented string value.
*
* @return The string value of this type.
*/
public Object getValue() {
return value_;
}
/**
* Returns the represented string value.
*
* @return The string value of this type.
*/
public String getString() {
return value_;
}
/**
* Sets the string value.
*
* @param s
* The string value.
* @throws ConstraintException
* if the given string does not match the constraint set for
* this instance.
*/
public void setString(String s) throws ConstraintException {
setString0(s);
checkConstraints();
}
protected void setString0(String s) {
if (s == null)
throw new NullPointerException("Need a string!");
value_ = s;
}
public void encode(Encoder enc) throws ASN1Exception, IOException {
enc.writeString(this);
}
public void decode(Decoder enc) throws ASN1Exception, IOException {
enc.readString(this);
checkConstraints();
}
/**
* Converts the given byte array to a string by filling up each consecutive
* byte with 0's to the size of the Unicode characters.
*
* @param b
* The byte array to convert.
* @throws ASN1Exception
* never, only for compliance with the {@link ASN1String}
* interface.
*/
public String convert(byte[] b) throws ASN1Exception {
if (b == null)
throw new NullPointerException("Cannot convert null array!");
char[] c = new char[b.length];
for (int i = 0; i < b.length; i++)
c[i] = (char) (b[i] & 0xff);
return String.valueOf(c);
}
/**
* Converts the given string to a byte array by chopping away all but the
* least significant byte of each character.
*
* @param s
* The string to convert.
* @throws ASN1Exception
* never, only for compliance with the {@link ASN1String}
* interface.
*/
public byte[] convert(String s) throws ASN1Exception {
if (s == null)
throw new NullPointerException("Cannot convert null string!");
char[] c = s.toCharArray();
byte[] b = new byte[c.length];
for (int i = 0; i < c.length; i++)
b[i] = (byte) (c[i] & 0xff);
return b;
}
/**
* Returns the number of bytes required to store the converted string.
*
* @param s
* The string.
* @throws ASN1Exception
* never, only for compliance with the {@link ASN1String}
* interface.
*/
public int convertedLength(String s) throws ASN1Exception {
return s.length();
}
public String toString() {
String s;
int n;
s = getClass().getName();
n = s.lastIndexOf('.');
if (n < 0)
n = -1;
s = s.substring(n + 1);
if (s.startsWith("ASN1"))
s = s.substring(4);
return s + " \"" + value_ + "\"";
}
/**
* Indicates whether some other ASN.1 string is "equal to" this one.
*
* @param s
* the reference string with which to compare.
* @return true if this string is the same as the s argument; false
* otherwise.
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object s) {
if (this.getClass().equals(s.getClass())) {
return value_.equals(((ASN1AbstractString) s).getString());
}
return false;
}
/**
* Returns a hash code value for the object calculated from the contained
* <code>String</code>.
*
* @return a hash code value for this object.
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return (this.getClass().hashCode() + value_.hashCode()) / 2;
}
}

View File

@@ -0,0 +1,299 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
/**
* The basic interface for Java objects representing primitive ASN.1 types
* according to ITU-T Recommendation X.680.
*
* @author Volker Roth
* @version "$Id: ASN1AbstractType.java,v 1.4 2005/03/23 12:45:51 flautens Exp $"
*/
public abstract class ASN1AbstractType extends Object implements ASN1Type,
Cloneable, Externalizable {
/**
* Holds the ASN.1 optional state. Optional types may be present in an
* encoding but they need not be.
*/
private boolean optional_ = false;
/**
* This flag defines the tagging variant which should be used by the
* decoder/encoder while processing this type.
*/
private boolean explicit_ = true;
/**
* Holds the constraint which should be checked if the internal value of a
* sub class is modified.
*/
private Constraint constraint_;
/**
* This abstract method should return the value wrapped by the ASN1Type.
*
* @return the internal value
*/
public abstract Object getValue();
/**
* Returns the corresponding ASN.1 tag.
*
* @return the corresponding ASN.1 tag
*/
public abstract int getTag();
public abstract void encode(Encoder enc) throws ASN1Exception, IOException;
public abstract void decode(Decoder dec) throws ASN1Exception, IOException;
/*
* Method declarations with default implementation.
*/
public ASN1AbstractType() {
super();
}
/**
* Optional types may be present in an encoding but they need not be.
*
* @param optional
* <code>true</code> iff this type is optional.
*/
public void setOptional(boolean optional) {
optional_ = optional;
}
/**
* @return <code>true</code> if this type is optional.
*/
public boolean isOptional() {
return optional_;
}
/**
* This default implementation returns {@link ASN1#CLASS_UNIVERSAL
* UNIVERSAL}.
*
* @return The class of the ASN.1 tag.
*/
public int getTagClass() {
return ASN1.CLASS_UNIVERSAL;
}
/**
* Sets the tagging of this type as either EXPLICIT or IMPLICIT. The default
* is EXPLICIT. Encoders skip the encoding of identifier octets for types
* that are declared as IMPLICIT.
*
* @param explicit
* <code>true</code> if this type shall be tagged EXPLICIT
* and <code>false</code> if it shall be encoded IMPLICIT.
*/
public void setExplicit(boolean explicit) {
explicit_ = explicit;
}
/**
* Returns code>true</code> if this type is tagged EXPLICIT and <code>false</code>
* otherwise.
*
* @return <code>true</code> if this type is tagged EXPLICIT and <code>false</code>
* if it is tagged IMPLICIT.
*/
public boolean isExplicit() {
return explicit_;
}
/**
* Returns <code>true</code> if the given tag and tag class matches the
* tag and tag class of this instance. This method is used primarily by
* decoders and variable types such as {@link ASN1Choice ASN1Choice} and
* {@link ASN1OpenType ASN1OpenType}. It enables decoders to query a
* variable type whether a decoded type is accepted.
* <p>
*
* This method provides a default implementation that matches the given tag
* and tag class against the values returned by {@link #getTag getTag} and
* {@link #getTagClass getTagClass} respectively.
*
* @param tag
* The tag to compare with.
* @param tagclass
* The tag class to compare with.
* @return <code>true</code> if the given tag and tag class matches this
* type and <code>false</code> otherwise.
*/
public boolean isType(int tag, int tagclass) {
if ((getTag() == tag) && (getTagClass() == tagclass)) {
return true;
}
return false;
}
/**
* Sets the {@link Constraint Constraint} of this type. For instance an
* ASN.1 INTEGER might be constrained to a certain range such as INTEGER
* (0..99). <code>null</code> can be passed as a constraint which disables
* constraint checking.
*
* @param constraint
* The {@link Constraint Constraint} of this type.
*/
public void setConstraint(Constraint constraint) {
constraint_ = constraint;
}
/**
* Returns the {@link Constraint Constraint} of this type or
* <code>null</code> if there is none.
*
* @return The Constraint or <code>null</code>.
*/
public Constraint getConstraint() {
return constraint_;
}
/**
* Checks the constraint on this type if it is set. Otherwise this method
* returns silently.
*
* @throws ConstraintException
* if this type is not in the appropriate range of values.
*/
public void checkConstraints() throws ConstraintException {
if (constraint_ != null) {
constraint_.constrain(this);
}
}
/**
* The writeExternal and readExternal methods of the Externalizable
* interface are implemented by a class to give the serializable class
* complete control over the format and contents of the stream for an object
* and its supertypes.
*
* @param out -
* the stream to write the object to
* @throws IOException
* if an I/0 error has occured
* @see java.io.Externalizable
*/
public void writeExternal(ObjectOutput out) throws IOException {
byte[] res = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
encode(new DEREncoder(baos));
res = baos.toByteArray();
baos.close();
out.write(res);
} catch (ASN1Exception e) {
throw new RuntimeException(e.toString());
}
}
/**
* The writeExternal and readExternal methods of the Externalizable
* interface are implemented by a class to give the serializable class
* complete control over the format and contents of the stream for an object
* and its supertypes.
*
* @param in -
* the stream to read data from in order to restore the
* object
* @throws IOException
* if an I/0 error has occured
* @see java.io.Externalizable
*/
public void readExternal(ObjectInput in) throws IOException {
try {
decode(new DERDecoder((ObjectInputStream) in));
} catch (ASN1Exception e) {
throw new RuntimeException(e.toString());
}
}
}

View File

@@ -0,0 +1,510 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* Represents an ASN.1 BIT STRING type. The corresponding Java type is
* <code>boolean[]</code>.
* <p>
*
* This class has to modes of initialization which play a crucial role in
* standards compliant DER encoding. One mode initializes instances of this
* class as a representation of &quot;named bits&quot;. The second mode
* initializes it as a plain bitstring.
* <p>
*
* An ASN.1 structure with named bits looks e.g., as follows:
*
* <pre>
* Rights ::= BIT STRING { read(0), write(1), execute(2)}
* </pre>
*
* Such bitstrings have a special canonical encoding. The mode (and defaults)
* are specified in the documentation of the constructors of this class.
* Basically, in named bits mode, trailing zeroes are truncated from the
* internal representation of the bitstring.
*
* @author Volker Roth
* @version "$Id: ASN1BitString.java,v 1.6 2005/03/23 13:01:20 flautens Exp $"
*/
public class ASN1BitString extends ASN1AbstractType {
private static final byte[] DEFAULT_VALUE = new byte[0];
private static final byte[] MASK = { (byte) 0x80, (byte) 0x40, (byte) 0x20,
(byte) 0x10, (byte) 0x08, (byte) 0x04, (byte) 0x02, (byte) 0x01 };
private static final byte[] TRAIL_MASK = { (byte) 0xff, (byte) 0xfe,
(byte) 0xfc, (byte) 0xf8, (byte) 0xf0, (byte) 0xe0, (byte) 0xc0,
(byte) 0x80 };
private int pad_ = 0;
private byte[] value_ = DEFAULT_VALUE;
/**
* Says whether this instance is a &quot;named bits&quot; bitstring. The
* default is <code>false</code>.
*/
private boolean namedBits_ = false;
/**
* Initializes an instance for decoding. This initializes this instance to
* be decoded as a plain bitstring (no named bits). Use this for bitstrings
* with named bits as well. It does not make a difference for the
* application, but it ensures that bitstrings that have been decoded are
* encoded in the same way again.
*/
public ASN1BitString() {
}
/**
* Initializes the instance for encoding with the given bits. The index of
* each bit corresponds to its number in the ASN.1 definition. This
* constructor initializes the instance as a bitstring with named bits. The
* array is not copied into this instance and can be modified subsequently
* without causing side effects.
*
* @param b
* The string of bits to be encoded.
*/
public ASN1BitString(boolean[] b) {
setBits0(b);
}
/**
* Creates an instance with the given contents. Use of this constructor
* copies the given byte array by reference and may cause side effects. The
* mode of this bitstring is plain (no named bits are assumed).
*
* @param b
* The left aligned contents bits.
* @param pad
* The number of pad bits.
*/
public ASN1BitString(byte[] b, int pad) {
setBits0(b, pad);
}
/**
* This method calls {@link #getBits getBits()}.
*
* @return The contents bits as a boolean array.
*/
public Object getValue() {
return getBits();
}
/**
* Returns the contents bits of this instance. No side effects occur when
* the returned array is modified.
*
* @return The contents bits.
*/
public boolean[] getBits() {
int n, i;
boolean[] b;
if (value_.length == 0) {
return new boolean[0];
}
b = new boolean[(value_.length * 8) - pad_];
for (n = 0, i = 0; i < b.length; i++) {
if ((value_[n] & MASK[i & 0x07]) != 0) {
b[i] = true;
} else {
b[i] = false;
}
if ((i & 0x07) == 0x07) {
n++;
}
}
return b;
}
/**
* Sets the contents bits of this instance. This method does not cause side
* effects. It switches to the named bits mode.
*
* @param bits
* The contents bits that are set.
* @throws ConstraintException
* if the given bits violates the specified constraint.
*/
public void setBits(boolean[] bits) throws ConstraintException {
setBits0(bits);
checkConstraints();
}
/**
* Sets the contents bits of this instance. This method does not cause side
* effects. It switches to named bits mode.
*
* @param bits
* The contents bits that are set.
*/
protected void setBits0(boolean[] bits) {
namedBits_ = true;
if ((bits == null) || (bits.length == 0)) {
value_ = DEFAULT_VALUE;
pad_ = 0;
return;
}
int i;
int j;
int n;
int k;
byte m;
byte[] b;
/*
* We skip trailing zero bits. Trailing bits are to the "right" in ASN.1
* terms (bits with high numbers).
*/
for (k = bits.length - 1; k >= 0; k--) {
if (bits[k]) {
break;
}
}
/*
* If all bits are zero then we set the default zero and we are done.
*/
if (k < 0) {
value_ = DEFAULT_VALUE;
pad_ = 0;
return;
}
k++;
/*
* If required we truncate trailing bits. This is compliant to the
* X.690/DER encoding rules and saves us trouble in the encoder.
*/
b = new byte[(k + 7) / 8];
m = 0;
for (n = 0, i = 0; i < k; i++) {
j = i & 0x07;
if (bits[i]) {
m = (byte) (m | MASK[j]);
}
if (j == 7) {
b[n++] = m;
m = 0;
}
}
j = i & 0x07;
if (j != 0) {
b[n] = m;
}
value_ = b;
pad_ = (8 - j) & 0x07;
}
/**
* Sets the bit string from the given byte aray and pad count. Bit 0 is the
* most significant bit in the first byte of the array and bit <i>n</i> is
* bit 7-(<i>n</i><code>&amp;0x07</code>) in byte floor(<i>n</i>/8).
* The length of the bit string is <code>b.length</code>*8-pad. The pad
* value be in the range of [0..7]. In other words the bits in the byte
* array are left aligned.
* <p>
*
* The given byte array may be copied by reference. Subsequent modification
* of it can cause side effects. The mode is set not to represent named
* bits.
*
* @param b
* The bits encoded into a byte array.
* @param pad
* The number of pad bits after the actual bits in the array.
* @throws IllegalArgumentException
* if the pad value is out of range.
* @throws ConstraintException
* if the given bits violates the
*/
public void setBits(byte[] b, int pad) throws ConstraintException {
setBits0(b, pad);
checkConstraints();
}
/**
* Sets the bits and number of trailing pad bits from the given byte array.
* The given instance is copied by reference. Therefor side effects can
* occur if the given byte array is modified subsequently. The
* initialization mode is plain (no named bits).
*
* @param b
* The minimum number of bytes to hold the left aligned
* contents bits. Any unused trailing bits (as defined by the
* pad count) MUST be zero!
* @param p
* The number of trailing padding bits.
*/
protected void setBits0(byte[] b, int p) {
int n;
if ((p < 0) || (p > 7)) {
throw new IllegalArgumentException("Illegal pad value (" + p + ")");
}
namedBits_ = false;
/*
* We first skip all leading zero bytes.
*/
for (n = b.length - 1; n >= 0; n--) {
if (b[n] != 0) {
break;
}
}
/*
* If all bytes are zero then we encode a zero bit string and are done.
*/
if (n < 0) {
if (p != 0) {
throw new IllegalArgumentException(
"Zero length bit strings can't have pad bits!");
}
value_ = DEFAULT_VALUE;
pad_ = 0;
return;
}
/*
* We test whether the trailing pad bits are really zeroes.
*/
if ((b[b.length - 1] & ~TRAIL_MASK[p]) != 0) {
throw new IllegalArgumentException(
"trailing pad bits are not zero!");
}
value_ = b;
pad_ = p;
}
/**
* Returns the contents octets of this instance. The bits are left aligned
* and the most significant bit is a one (or else the bitstring is zero and
* an empty array is returned). The returned byte array is the one used
* internally. Modifying it causes side effects which may result in
* erroneous encoding. So, don't modify it!
* <p>
*
* Please also note that the bits in the bytes are left aligned. In other
* words, the bits are shifted to the left by the amount of pad bits. Bit X
* in the byte array corresponds to the logical bit with the number X minus
* pad count.
*
* @return The bits left aligned in a byte array with no trailing zeroes.
*/
public byte[] getBytes() {
return value_;
}
/**
* @return The number of unused bits in the last byte of the bitstring's
* byte array representation. This number is always in the range
* zero to seven.
*/
public int getPadCount() {
return pad_;
}
/**
* @return The number of bytes of the bitstring's byte array representation.
*/
public int byteCount() {
return value_.length;
}
/**
* Returns the number of bits of the bitstring representation. Bits are
* counted only to the most significant bit that is a one. Trailing zeroes
* are neither present in the internal representation nor are they counted.
*
* @return The number of bits of the bitstring representation.
*/
public int bitCount() {
return (value_.length * 8) - pad_;
}
/**
* @return <code>true</code> iff this instance has named bits.
*/
public boolean isNamedBits() {
return namedBits_;
}
/**
* Returns <code>true</code> if the bit string contains no bits that are
* 1. Otherwise, <code>false</code> is returned. This method is used by
* the {@link DEREncoder DEREncoder} in order to determine cases in which
* special encoding is to be used. If no bits of a BIT STRING are 1 then it
* is encoded as <tt>0x03 0x01 0x00
* </tt> even if the BIT STRING has
* hundreds of bits in length.
*
* @return <code>true</code> if all bits are zero.
*/
public boolean isZero() {
return (value_.length == 0);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public int getTag() {
return ASN1.TAG_BITSTRING;
}
/**
* DOCUMENT ME!
*
* @param enc
* The encoder which is used to encode
*
* @throws ASN1Exception
* DOCUMENT ME!
* @throws IOException
* if an I/O error occures
*/
public void encode(Encoder enc) throws ASN1Exception, IOException {
enc.writeBitString(this);
}
/**
* Decodes this instance. After decoding, this method restores the mode
* (named bits vs no named bits) of this instance to the one it had before
* decoding. This is to maintain the original mode while assuring that
* encoded values are identical to decoded ones even if the encoding.
*
* @param dec
* The decoder which is used to decode
* @throws IOException
* if an I/O error occures
*/
public void decode(Decoder dec) throws ASN1Exception, IOException {
boolean tmp;
tmp = namedBits_;
try {
dec.readBitString(this);
} finally {
namedBits_ = tmp;
}
// Redudant, also called by setBits(byte[], int)
// checkConstraints();
}
/**
* Returns the string representation of this ASN1BitString.
*
* @return the string representation of this ASN1BitString
*/
public String toString() {
StringBuffer buf;
boolean[] bits;
int i;
bits = getBits();
buf = new StringBuffer(12 + bits.length);
buf.append("BitString '");
for (i = 0; i < bits.length; i++) {
if (bits[i]) {
buf.append("1");
} else {
buf.append("0");
}
}
buf.append("'");
return buf.toString();
}
}

View File

@@ -0,0 +1,127 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* Represents an ASN.1 BOOEAN type. The corresponding Java type is
* <code>boolean</code>. This type does not support constraint checking.
*
* @see Constraint
* @author Volker Roth
* @version "$Id: ASN1Boolean.java,v 1.2 2000/12/06 17:47:23 vroth Exp $"
*/
public class ASN1Boolean extends ASN1AbstractType {
private boolean value_ = true;
public ASN1Boolean() {
}
public ASN1Boolean(boolean t) {
setTrue(t);
}
public Object getValue() {
return new Boolean(value_);
}
public boolean isTrue() {
return value_;
}
public void setTrue(boolean b) {
value_ = b;
}
public int getTag() {
return ASN1.TAG_BOOLEAN;
}
public void encode(Encoder enc) throws ASN1Exception, IOException {
enc.writeBoolean(this);
}
public void decode(Decoder dec) throws ASN1Exception, IOException {
dec.readBoolean(this);
}
public String toString() {
return "BOOLEAN " + value_;
}
}

View File

@@ -0,0 +1,420 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
/**
* This type represents the ASN.1 CHOICE type as specified in ITU-T
* Recommendation X.680. On decoding, the decoder must be able to decide
* umambiguously which alternative choice it has to decode. For this reason all
* elements in a CHOICE type must have distinctive tags.
* <p>
*
* This class does not enforce the distinctive tag rule. Instead, the
* alternative with the first matching tag should be chosen by decoders. The
* application that builds the CHOICE type must take care not to produce
* ambiguous sets of alternatives.
* <p>
*
* This class distinguishes alternative choices and an inner type. Upon
* decoding, the inner type is selected from the list of choices based on the
* identifier octets encountered in the encoded stream. This type is then
* {@link #setInnerType set as the inner type} of this instance. Unless an inner
* type is set (either explicitly or by means of decoding) the state of the
* choice is undefined.
* <p>
*
* This instance always mimicks its inner type. The methods
* {@link ASN1Type#getTag getTag}, {@link ASN1Type#getTagClass getTagClass},
* {@link ASN1Type#getValue getValue} all return the appropriate results of the
* corresponding method of the inner type. On encoding an instance of this class
* the inner type is encoded.
* <p>
*
* No nested CHOICE classes are supported. In principle this is easily supported
* but it is not good style to build such structures.
*
* @author Volker Roth
* @version "$Id: ASN1Choice.java,v 1.3 2004/08/06 15:01:20 flautens Exp $"
*/
public class ASN1Choice extends ASN1AbstractType {
private static final String NO_INNER = "No inner type defined!";
private ASN1Type inner_;
private ArrayList choices_;
/**
* Creates an instance with an initial capacity of 2.
*/
public ASN1Choice() {
choices_ = new ArrayList(2);
}
/**
* Creates an instance with the given initial capacity. The capacity
* determines the number of choices to store. This instance is backed by an
* ArrayList, hence the capacity is increased dynamically as required. Use
* the {@link #trimToSize() trimToSize()} method to trim the internal list
* to the number of stored choices in order to reclaim memory.
*
* @param capacity
* The initial capacity for storing choices.
* @throws IllegalArgumentException
* if the capacity is less than 1.
*/
public ASN1Choice(int capacity) {
if (capacity < 1)
throw new IllegalArgumentException(
"capacity must be greater than zero!");
choices_ = new ArrayList(capacity);
}
/**
* Adds the given type as an alternative choice to the collection of
* choices. The caller has to take care that no ambiguous choices are added.
* Each added type must have a distinctive tag.
* <p>
*
* CHOICE elements must neither be OPTIONAL nor tagged IMPLICIT. For safety,
* this method calls {@link ASN1Type#setOptional setOptional}(false) and
* {@link ASN1Type#setExplicit setExplicit}(true) on the given type.
* Callers must not alter this setting after adding a type to this choice.
* However, the CHOICE itself can be declared OPTIONAL.
*
* @param t
* The ASN.1 type to add as a choice.
* @throws NullPointerException
* if the given type is <code>null</code>.
* @throws IllegalArgumentException
* if the given type is a ASN1Choice type.
*/
public void addType(ASN1Type t) {
if (t == null)
throw new NullPointerException("Choice is null!");
if (t instanceof ASN1Choice)
throw new IllegalArgumentException(
"No nested CHOICE types are allowed!");
t.setOptional(false);
t.setExplicit(true);
choices_.add(t);
}
/**
* Returns the choice with the given tag and tagclass if it exists,
* otherwise <code>null</code> is returned. This method is called by the
* decoder in order to determine the appropriate type to decode. The
* returned type is set up as the inner type by the decoder.
*
* @param tag
* The tag of the type encountered in the encoded stream. The
* tags of the various primitive ASN.1 types are defined in
* class {@link ASN1 ASN1}.
* @param tagclass
* The tag class of the type encountered in the encoded
* stream. The tag class identifiers are defined in class
* {@link ASN1 ASN1}. See for instance
* {@link ASN1#CLASS_UNIVERSAL CLASS_UNIVERSAL}.
* @return The choice with matching tag and tag class or <code>null</code>
* if no matching choice is found.
*/
public ASN1Type getType(int tag, int tagclass) {
Iterator i;
ASN1Type t;
for (i = choices_.iterator(); i.hasNext();) {
t = (ASN1Type) i.next();
if (t.getTag() != tag)
continue;
if (t.getTagClass() == tagclass)
return t;
}
return null;
}
public boolean isType(int tag, int tagclass) {
if (getType(tag, tagclass) != null)
return true;
return false;
}
/**
* Trims the internal list of choices to the actual number of choices stored
* in it.
*/
public void trimToSize() {
choices_.trimToSize();
}
/**
* Clears the internal list of choices. The inner type remains unaffected if
* it is already set.
*
* number of choices stored in it.
*/
public void clear() {
choices_.clear();
}
/**
* Returns the inner ASN.1 type.
*
* @return The inner ASN.1 type.
*/
public ASN1Type getInnerType() {
return inner_;
}
/**
* Sets the inner type.
*
* @param t
* The type to set as the inner type.
* @throws NullPointerException
* if the given type is <code>null</code>.
*/
public void setInnerType(ASN1Type t) {
if (t == null)
throw new NullPointerException("No type given!");
inner_ = t;
}
/**
* Returns the tag of the inner type.
*
* @return The tag of the inner type.
* @throws IllegalStateException
* if the inner type is not set.
*/
public int getTag() {
if (inner_ == null)
throw new IllegalStateException(NO_INNER);
return inner_.getTag();
}
/**
* Returns the tag class of the inner type.
*
* @return The tag class of the inner type.
* @throws IllegalStateException
* if the inner type is not set.
*/
public int getTagClass() {
if (inner_ == null)
throw new IllegalStateException(NO_INNER);
return inner_.getTagClass();
}
/**
* Returns the value of the inner type. The default inner type is
* {@link ASN1Null ASN1Null}. This method calls
* {@link ASN1Type#getValue getValue} on the inner type and returns the
* result.
*
* @return The value of the inner type.
* @throws IllegalStateException
* if the inner type is not set.
*/
public Object getValue() {
if (inner_ == null)
throw new IllegalStateException(NO_INNER);
return inner_.getValue();
}
/**
* Sets the tagging of the inner type as either EXPLICIT or IMPLICIT. The
* default is EXPLICIT. Encoders skip the encoding of identifier octets for
* types that are declared as IMPLICIT.
*
* @param explicit
* <code>true</code> if this type shall be tagged EXPLICIT
* and <code>false</code> if it shall be encoded IMPLICIT.
* @throws IllegalStateException
* if the inner type is not set.
*/
public void setExplicit(boolean explicit) {
if (!explicit)
throw new IllegalArgumentException(
"CHOICE types must be tagged EXPLICIT!");
}
/**
* Returns the tagging of the inner type.
*
* @return <code>true</code> if the inner type is tagged EXPLICIT and
* <code>false</code> if it is tagged IMPLICIT.
* @throws IllegalStateException
* if the inner type is not set.
*/
public boolean isExplicit() {
return true;
}
/**
* Sets the {@link Constraint Constraint} of the inner type. For instance an
* ASN.1 INTEGER might be constrained to a certain range such as INTEGER
* (0..99). <code>null</code> can be passed as a constraint which disables
* constraint checking.
*
* @param constraint
* The {@link Constraint Constraint} of this type.
* @throws IllegalStateException
* if the inner type is not set.
*/
public void setConstraint(Constraint constraint) {
if (inner_ == null)
throw new IllegalStateException(NO_INNER);
inner_.setConstraint(constraint);
}
/**
* Checks the constraint on the inner type if it is set. Otherwise this
* method returns silently.
*
* @throws ConstraintException
* if this type is not in the appropriate range of values.
* @throws IllegalStateException
* if the inner type is not set.
*/
public void checkConstraints() throws ConstraintException {
if (inner_ == null)
throw new IllegalStateException(NO_INNER);
inner_.checkConstraints();
}
/**
* Encodes this type to the given encoder. Before this method is called, the
* inner type must be set. Otherwise an IllegalStateException is thrown.
* <p>
*
* If this method is declared OPTIONAL then still an exception is thrown.
* The OPTIONAL flag is checked only by {@link Encoder encoders} and
* {@link Decoder decoders}. Transparent handling of CHOICE types can be
* achieved by calling <code>{@link Encoder#writeType
* writeType}(ASN1Choice choice)</code>
* on the encoder. The encoder's method checks if its argument is OPTIONAL.
*
* @param enc
* The {@link Encoder Encoder} to use for encoding.
* @throws IllegalStateException
* if the inner type is not set.
*/
public void encode(Encoder enc) throws ASN1Exception, IOException {
if (inner_ == null)
throw new IllegalStateException(NO_INNER);
enc.writeType(inner_);
}
/**
* Decodes the inner type to the given {@link Decoder decoder}.
*
* @param dec
* The decoder to decode to.
* @throws IllegalStateException
* if the open type cannot be resolved on runtime.
*/
public void decode(Decoder dec) throws ASN1Exception, IOException {
dec.readChoice(this);
}
/**
* Returns a string representation of this type.
*
* @return The string representation.
*/
public String toString() {
if (inner_ == null)
return "CHOICE <NOT InitializED>";
return "(CHOICE) " + inner_.toString();
}
}

View File

@@ -0,0 +1,98 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.util.Collection;
/**
* The basic interface for Java objects representing a constructed ASN.1 type
* such as a SEQUENCE or SET as specified in ITU-T Recommendation X.680.
*
* @author Volker Roth
* @version "$Id: ASN1Collection.java,v 1.2 2000/12/06 17:47:23 vroth Exp $"
*/
public interface ASN1Collection extends ASN1Type, Collection {
/**
* Returns the Java Collection that is used to maintain the embedded ASN.1
* types.
*
* @return The collection used internally for storing the elements in this
* constructed ASN.1 type.
*/
public Collection getCollection();
}

View File

@@ -0,0 +1,116 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* The basic interface for Java objects representing a constructed ASN.1 type
* such as a SEQUENCE or SET as specified in ITU-T Recommendation X.680.
*
* @author Volker Roth
* @version "$Id: ASN1CollectionOf.java,v 1.2 2000/12/06 17:47:24 vroth Exp $"
*/
public interface ASN1CollectionOf extends ASN1Collection {
/**
* Returns the Java class representing the ASN.1 type of the elements in
* this collection.
*
* @return The ASN.1 type of the elements in this collection.
*/
public Class getElementType();
/**
* Creates and returns a new instance of the class passed to the constructor
* of this instance. The freshly created instance is added to this instance
* automatically.
* <p>
*
* If no new instance can be created then an IllegalStateException is
* thrown.
* <p>
*
* <b>{@link Decoder Decoders} should call this method in order to create
* additional elements on decoding.</b> Subclasses may use this method to
* keep track on elements added to them.
*
* @return A new instance of the element type of this sequence.
* @throws IllegalStateException
* if no new instance could be created.
*/
public ASN1Type newElement();
}

View File

@@ -0,0 +1,93 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
*
*
* @author Volker Roth
* @version "$Id: ASN1Exception.java,v 1.2 2000/12/06 17:47:24 vroth Exp $"
*/
public class ASN1Exception extends Exception {
public ASN1Exception() {
}
public ASN1Exception(String message) {
super(message);
}
}

View File

@@ -0,0 +1,120 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* This class represents an ASN.1 IA5String as described in ITU-T Recommendation
* X.680.
*
* @author Volker Roth
* @version "$Id: ASN1IA5String.java,v 1.3 2004/08/06 15:04:44 flautens Exp $"
*/
public class ASN1IA5String extends ASN1AbstractString {
/**
* Constructor declaration.
*
*/
public ASN1IA5String() {
super();
}
/**
* Creates an instance with the given string value. No constraints can be
* set yet so none are checked.
*
* @param s
* The string value.
*/
public ASN1IA5String(String s) {
super(s);
}
/**
* Method declaration.
*
*
* @return The tag value
*/
public int getTag() {
return ASN1.TAG_IA5STRING;
}
}
/*--- formatting done in "SeMoA Java Convention" style on 05-17-2000 ---*/

View File

@@ -0,0 +1,248 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
import java.math.BigInteger;
/**
* Represents an ASN.1 INTEGER type. The corresponding Java type is
* java.math.BigInteger.
*
* @author Volker Roth
* @version "$Id: ASN1Integer.java,v 1.2 2000/12/06 17:47:24 vroth Exp $"
*/
public class ASN1Integer extends ASN1AbstractType {
/**
* Holds the octets per integer count. This value is computed by means of
* static initializer code below.
*/
private static int opi_;
/**
* The value of this ASN.1 INTEGER.
*/
private BigInteger value_;
/*
* Initializes the opi_ field above.
*/
static {
int n;
int i;
for (n = 1, i = 0; n != 0; n = n << 8) {
i++;
}
opi_ = i;
}
/**
* Creates a new instance ready for parsing. The value of this instance is
* set to 0.
*/
public ASN1Integer() {
value_ = BigInteger.ZERO;
}
/**
* Creates a new instance with the given BigInteger as its initial value.
*
* @param val
* The value.
*/
public ASN1Integer(BigInteger val) {
if (val == null)
throw new NullPointerException("Need a number!");
value_ = val;
}
/**
* Creates an ASN.1 INTEGER from the given string representation.
*
* This method calls the equivalent constructor of class
* {@link java.math.BigInteger java.math.BigInteger}.
*
* @param val
* The string representation of the multiple precision
* integer.
* @throws NumberFormatException
* if the string could not be parsed successfully.
*/
public ASN1Integer(String val) throws NumberFormatException {
value_ = new BigInteger(val);
}
/**
* Creates a new instance from the given byte array. The byte array contains
* the two's-complement binary representation of a BigInteger. The input
* array is assumed to be in <i>big endian</i> byte-order. The most
* significant byte is in the zeroth element.
*
* This method calls the equivalent constructor of class
* {@link java.math.BigInteger java.math.BigInteger}.
*
* @param val
* The two's-complement input number in big endian
* byte-order.
* @throws NumberFormatException
* if val is zero bytes long.
*/
public ASN1Integer(byte[] val) throws NumberFormatException {
value_ = new BigInteger(val);
}
/**
* Translates the sign-magnitude representation of a BigInteger into an
* ASN.1 INTEGER. The sign is represented as an integer signum value: -1 for
* negative, 0 for zero, or 1 for positive. The magnitude is a byte array in
* big-endian byte-order: the most significant byte is in the zeroth
* element. A zero-length magnitude array is permissible, and will result in
* in a BigInteger value of 0, whether signum is -1, 0 or 1.
* <p>
*
* This method calls the equivalent constructor of class
* {@link java.math.BigInteger java.math.BigInteger}.
*
* @param signum
* signum of the number (-1 for negative, 0 for zero, 1 for
* positive).
* @param magnitude
* The big endian binary representation of the magnitude of
* the number.
* @throws NumberFormatException
* signum is not one of the three legal values (-1, 0, and
* 1), or signum is 0 and magnitude contains one or more
* non-zero bytes.
*/
public ASN1Integer(int signum, byte[] magnitude)
throws NumberFormatException {
value_ = new BigInteger(signum, magnitude);
}
/**
* Creates an instance with the given int value.
*
* @param n
* The integer to initialize with.
*/
public ASN1Integer(int n) {
byte[] b;
int i;
int m;
b = new byte[opi_];
m = n;
for (i = opi_ - 1; i >= 0; i--) {
b[i] = (byte) (m & 0xff);
m = m >>> 8;
}
value_ = new BigInteger(b);
}
public Object getValue() {
return value_;
}
public BigInteger getBigInteger() {
return value_;
}
public void setBigInteger(BigInteger n) throws ConstraintException {
value_ = n;
checkConstraints();
}
public int getTag() {
return ASN1.TAG_INTEGER;
}
public void encode(Encoder enc) throws ASN1Exception, IOException {
enc.writeInteger(this);
}
public void decode(Decoder dec) throws ASN1Exception, IOException {
dec.readInteger(this);
checkConstraints();
}
public String toString() {
return "Integer " + value_.toString();
}
}

View File

@@ -0,0 +1,108 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* Represents the ASN.1 NULL type.
*
* @author Volker Roth
* @version "$Id: ASN1Null.java,v 1.2 2000/12/06 17:47:24 vroth Exp $"
*/
public class ASN1Null extends ASN1AbstractType implements Cloneable {
public Object getValue() {
return null;
}
public int getTag() {
return ASN1.TAG_NULL;
}
public void encode(Encoder enc) throws ASN1Exception, IOException {
enc.writeNull(this);
}
public void decode(Decoder dec) throws ASN1Exception, IOException {
dec.readNull(this);
}
public String toString() {
return "NULL";
}
}

View File

@@ -0,0 +1,436 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
import java.util.StringTokenizer;
/**
* Represents an ASN.1 OBJECT IDENTIFIER type. The corresponding Java type is
* <code>int[]</code>. Constraints are checked for this type only at the end
* of method {@link #decode decode}.
*
* @author Volker Roth
* @version "$Id: ASN1ObjectIdentifier.java,v 1.4 2005/03/22 14:57:58 flautens
* Exp $"
*/
public class ASN1ObjectIdentifier extends ASN1AbstractType implements
Cloneable, Comparable {
/**
* holds the int[] representation of the OID
*/
private int[] value_ = new int[2];
/**
* Creates a new ASN1ObjectIdentifier object.
*/
public ASN1ObjectIdentifier() {
super();
}
/**
* Creates an instance with the given array of integers as elements. No
* constraints are checked by this constructor.
*
* @param oid
* The array of consecutive integers of the OID.
* @throws NullPointerException
* if the given <code>oid
* </code> is <code>null</code>.
* @throws IllegalArgumentException
* if the given <code>
* oid</code> is not well-formed. For
* instance, a bad <code>oid</code> might have a value
* greater than 2 as its first element.
*/
public ASN1ObjectIdentifier(int[] oid) {
set0(oid);
}
/**
* Creates an ASN.1 OBJECT IDENTIFIER instance initialized from the given
* OID string representation. The format must be either OID.1.2.3.4,
* oid.1.2.3.4, or 1.2.3.4 for the initiliser to work properly. Trailing
* dots are ignored.
*
* @param s
* string representation of oid
* @throws NumberFormatException
* if some element of the OID string is not an integer
* number.
* @throws IllegalArgumentException
* if the string is not a well-formed OID.
*/
public ASN1ObjectIdentifier(String s) throws NumberFormatException {
int n;
int[] oid;
String t;
StringTokenizer tok;
oid = new int[16];
if (s.startsWith("OID.") || s.startsWith("oid.")) {
s = s.substring(4);
}
tok = new StringTokenizer(s, ".");
if (tok.countTokens() >= oid.length) {
throw new IllegalArgumentException("OID has too many elements!");
}
n = 0;
while (tok.hasMoreTokens()) {
t = tok.nextToken();
oid[n++] = Integer.parseInt(t);
}
int[] buf = new int[n];
System.arraycopy(oid, 0, buf, 0, n);
set0(buf);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public Object getValue() {
return value_.clone();
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public int[] getOID() {
return (int[]) value_.clone();
}
/**
* DOCUMENT ME!
*
* @param oid
* DOCUMENT ME!
*
* @throws ConstraintException
* DOCUMENT ME!
*/
public void setOID(int[] oid) throws ConstraintException {
set0(oid);
checkConstraints();
}
/**
* Checks if the given oid is valid and stores the oid. If the oid is not
* valid the method throws an IllegalArgumentException.
*
* @param oid
* The oid to be checked
*/
private void set0(int[] oid) {
int n;
if (oid == null) {
throw new NullPointerException("Need an OID!");
}
n = oid.length;
if (n < 2) {
throw new IllegalArgumentException(
"OID must have at least 2 elements!");
}
if ((oid[0] < 0) || (oid[0] > 2)) {
throw new IllegalArgumentException("OID[0] must be 0, 1, or 2!");
}
if ((oid[1] < 0) || (oid[1] > 39)) {
throw new IllegalArgumentException(
"OID[1] must be in the range 0,..,39!");
}
value_ = new int[n];
System.arraycopy(oid, 0, value_, 0, n);
}
/**
* Returns the number of elements of the oid.
*
* @return the number of elements
*/
public int elementCount() {
return value_.length;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public int getTag() {
return ASN1.TAG_OID;
}
/**
* Encodes this ASN1ObjectIdentifier.
*
* @param enc
* The encoder to encode to.
*
* @throws ASN1Exception
* @throws IOException
*/
public void encode(Encoder enc) throws ASN1Exception, IOException {
enc.writeObjectIdentifier(this);
}
/**
* Decodes to this ASN1ObjectIdentifier.
*
* @param dec
* DOCUMENT ME!
*
* @throws ASN1Exception
* @throws IOException
*/
public void decode(Decoder dec) throws ASN1Exception, IOException {
dec.readObjectIdentifier(this);
checkConstraints();
}
/**
* Returns the string representation of this OID. The string consists of the
* numerical elements of the OID separated by periods.
*
* @return The string representation of the OID.
*/
public String toString() {
StringBuffer buf;
int i;
buf = new StringBuffer();
for (i = 0; i < value_.length; i++) {
buf.append(value_[i] + ".");
}
if (value_.length > 0) {
buf.setLength(buf.length() - 1);
}
return buf.toString();
}
/**
* Compares two OIDs for equality. Two OIDs are equal if the have the same
* number of elements and all corresponding elements are equal.
*
* @param o
* The object to compare to.
* @return <code>true</code> iff the given object is an
* ASN1ObjectIdentifier and iff it equals this one.
*/
public boolean equals(Object o) {
int i;
ASN1ObjectIdentifier oid;
if (!(o instanceof ASN1ObjectIdentifier)) {
return false;
}
oid = (ASN1ObjectIdentifier) o;
if (oid.value_.length != value_.length) {
return false;
}
for (i = 0; i < value_.length; i++) {
if (value_[i] != oid.value_[i]) {
return false;
}
}
return true;
}
/**
* This method computes the hash code of this instance. The hash code of
* this instance is defined as a hash function of the underlying integer
* array.
*
* @return the hash code of this instance.
*/
public int hashCode() {
int i;
int h;
h = 23;
for (i = 0; i < value_.length; i++) {
h = (h * 7) + value_[i];
}
return h;
}
/**
* This method compares two OID and returns -1, 0, 1 if this OID is less
* than, equal or greater than the given one. OID are interpreted as strings
* of numbers. An OID that is a prefix of another is always smaller than the
* other.
*
* @param o
* The OID to compare to.
* @return -1, 0, 1 if this OID is smaller than, equal to, or greater than
* the given OID.
* @throws ClassCastException
* iff <code>o</code> is not an ASN1ObjectIdentifier.
*/
public int compareTo(Object o) {
int n;
int i;
int[] oid;
oid = ((ASN1ObjectIdentifier) o).value_;
n = Math.min(value_.length, oid.length);
for (i = 0; i < n; i++) {
if (value_[i] < oid[i]) {
return -1;
} else if (value_[i] > oid[i]) {
return 1;
}
}
if (value_.length > n) {
return 1;
}
if (oid.length > n) {
return -1;
}
return 0;
}
/**
* This method determines whether the given OID is part of the OID family
* defined by this OID prefix. In other words, this method returns
* <code>true</code> if this OID is a prefix of the given one.
*
* @param o
* the oid to check
* @return true if this OID is a prefix of the given one.
*/
public boolean isPrefixOf(ASN1ObjectIdentifier o) {
int i;
i = value_.length;
if (o.value_.length < i) {
return false;
}
while (i > 0) {
i--;
if (value_[i] != o.value_[i]) {
return false;
}
}
return true;
}
/**
* Returns a clone of this instance. This method is not thread safe. The
* constraints are copied by reference.
*
* @return The clone.
*/
public Object clone() {
int[] m;
ASN1ObjectIdentifier oid;
oid = new ASN1ObjectIdentifier();
m = new int[value_.length];
System.arraycopy(value_, 0, m, 0, m.length);
oid.value_ = m;
oid.setConstraint(getConstraint());
return oid;
}
}

View File

@@ -0,0 +1,211 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* Represents an ASN.1 OCTET STRING type. The corresponding Java type is
* <code>byte[]</code>.
*
* @author Volker Roth
* @version "$Id: ASN1OctetString.java,v 1.3 2001/01/21 13:46:55 vroth Exp $"
*/
public class ASN1OctetString extends ASN1AbstractType {
private static final byte[] DEFAULT_VALUE = new byte[0];
private byte[] value_ = DEFAULT_VALUE;
public ASN1OctetString() {
}
/**
* Creates an instance with side effects. The given array is copied by
* reference.
*
* @param b
* The byte array that is set as contents.
*/
public ASN1OctetString(byte[] b) {
setByteArray0(b);
}
public Object getValue() {
return value_;
}
/**
* Returns the contents octets as a byte array. The returned byte array is
* is the instance used internally. Do not modify it, otherwise side effects
* occur.
*
* @return The contents octets as a byte array.
*/
public byte[] getByteArray() {
return (byte[]) value_.clone();
}
/**
* Sets the given bytes. The given byte array is copied by reference. Be
* careful, side effects can occur if the array is modified subsequent to
* calling this method. Constraints are checked after setting the bytes.
*
* @param b
* The byte array that is set.
* @throws ConstraintException
* if the constraint is not met by the given byte array.
*/
public void setByteArray(byte[] b) throws ConstraintException {
setByteArray0(b);
checkConstraints();
}
/**
* Sets the given bytes. The given byte array is copied by reference. Be
* careful, side effects can occur if the array is modified subsequent to
* calling this method.
*
* @param b
* The byte array that is set.
*/
private void setByteArray0(byte[] b) {
if (b == null)
value_ = DEFAULT_VALUE;
else
value_ = b;
}
public int byteCount() {
return value_.length;
}
public int getTag() {
return ASN1.TAG_OCTETSTRING;
}
public void encode(Encoder enc) throws ASN1Exception, IOException {
enc.writeOctetString(this);
}
public void decode(Decoder dec) throws ASN1Exception, IOException {
dec.readOctetString(this);
checkConstraints();
}
public String toString() {
StringBuffer buf;
String octet;
int i;
buf = new StringBuffer("Octet String");
for (i = 0; i < value_.length; i++) {
octet = Integer.toHexString(value_[i] & 0xff);
buf.append(' ');
if (octet.length() == 1) {
buf.append('0');
}
buf.append(octet);
}
return buf.toString();
}
/**
* Returns a clone. The clone is a deep copy of this instance with the
* exception of constraints. Constraints are copied by reference.
*
* @return The clone.
*/
public Object clone() {
ASN1OctetString o;
try {
o = (ASN1OctetString) super.clone();
} catch (CloneNotSupportedException e) {
/*
* This cannot, cannot, cannot, CANNOT happen ! If it does, put back
* the import statement for 'Cloneable' into ASN1AbstractType !
*/
throw new Error("Internal, clone support mismatch!");
}
o.value_ = (byte[]) value_.clone();
return o;
}
}

View File

@@ -0,0 +1,266 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* Represents an opaque type. An opaque type merely decodes the tag and tag
* class and stores the contents octets in an OCTET STRING. The opaque type is
* represented in ASN.1 as <code><blockquote>
* [UNIVERSAL x] IMPLICIT OCTET STRING
* </blockquote></code>
* where <code>x</code> is the tag.
* <p>
*
* The opaque type is comparable to an {@link ASN1OpenType open type} in that it
* matches any type (just like the deprecated ANY type) on decoding. The
* encoding can be reconstructed easily. This type is used whenever decoding of
* a structure should be deferred to a later point in time. For instance an
* AlgorithmIdentifier implementation can use an opaque type in order to decode
* algorithm parameters. The encoding of the algorithm parameters is then done
* by JCA/JCE classes later on.
* <p>
*
* One drawback of the opaque type is that special handling by the encoders and
* decoders is rquired to make it work properly. The main problem is that the
* opaque type does not store whether the underlying type is constructed or
* primitive. This decision must be made by the encoder.
* <p>
*
* Due to this limitation the opaque type can be used only for decoding types of
* class UNIVERSAL.
*
* @author Volker Roth
* @version "$Id: ASN1Opaque.java,v 1.2 2000/12/06 17:47:25 vroth Exp $"
*/
public class ASN1Opaque extends ASN1TaggedType {
/**
* Creates an instance. On decoding, opaque types pretend to be of a
* particular type and read the actual type's encoding into an OCTET STRING
* from which it can be retrieved later.
*
*/
public ASN1Opaque() {
super(-1, ASN1.CLASS_UNIVERSAL, new ASN1OctetString(), false);
}
/**
* Creates an instance that stores the given encoding. The encoding must be
* a valid DER encoding as specified in X.690. This constructor uses a
* {@link DERDecoder DERDecoder} in order to decode the identifier octets in
* the given encoding.
* <p>
*
* <b>Note:</b> If the given encoding contains the concatenation of
* multiple encodings then only the first one will be stored. All others
* will be lost.
*
* @throws ASN1Exception
* if the given code cannot be decoded.
*/
public ASN1Opaque(byte[] code) throws ASN1Exception {
super(-1, ASN1.CLASS_UNIVERSAL, new ASN1OctetString(), false);
ByteArrayInputStream bis;
DERDecoder dec;
try {
bis = new ByteArrayInputStream(code);
dec = new DERDecoder(bis);
decode(dec);
dec.close();
} catch (IOException e) {
throw new ASN1Exception("Internal, caught IOException!");
}
}
/**
* Creates an instance with the given type, class, and inner type. <b>Be
* careful</b>, the given octet string must contain the valid DER encoding
* of the contents octets of a type that matches the tag and tag class.
* Otherwise coding exceptions are most probably thrown subsequently.
*
* @param tag
* The ASN.1 tag of the opaque type.
* @param tagclass
* The tag class of the opaque type.
* @param b
* The DER compliant encoding of the contents octets of the
* opaque type.
* @throws NullPointerException
* if the given byte array is <code>null</code>.
*/
public ASN1Opaque(int tag, int tagclass, byte[] b) {
super(tag, tagclass, new ASN1OctetString((byte[]) b.clone()), false);
}
/**
* This method adopts the given tag and tag class if this instance is not
* yet initialized with a tag or tag class. In that case <code>true</code>
* is returned.
* <p>
*
* If a tag or tag class is already set then this method calls its super
* method.
*
* @param tag
* The tag to compare with.
* @param tagclass
* The tag class to compare with.
*/
public boolean isType(int tag, int tagclass) {
if (tagclass != ASN1.CLASS_UNIVERSAL)
return false;
if (getTag() == -1) {
setTag(tag);
return true;
}
return super.isType(tag, tagclass);
}
/**
* This method is a convenience method in order to encode this type with
* DER. It uses a {@link DEREncoder DEREncoder} in order to encode this type
* to a byte array which is returned.
* <p>
*
* @return The DER encoding of this type.
*/
public byte[] getEncoded() throws ASN1Exception {
ByteArrayOutputStream bos;
DEREncoder enc;
byte[] code;
try {
bos = new ByteArrayOutputStream();
enc = new DEREncoder(bos);
encode(enc);
code = bos.toByteArray();
enc.close();
return code;
} catch (IOException e) {
throw new ASN1Exception("Internal, caught IOException!");
}
}
/**
* Sets the inner type of this opaque type. The given type must be
* {@link ASN1OctetString ASN1OctetString} or a ClassCastException is
* thrown.
*
* @param t
* The type to set as the inner type.
* @throws NullPointerException
* if the given type is <code>null</code>.
* @throws ClassCastException
* if the given type is not an ASN1OctetString.
*/
public void setInnerType(ASN1Type t) {
super.setInnerType(t);
}
/**
* Returns a clone. The clone is a deep copy of this instance except the
* constraints. Constraints are copied by reference.
*
* @return The clone.
*/
public Object clone() {
ASN1OctetString b;
ASN1Opaque o;
try {
o = (ASN1Opaque) super.clone();
b = (ASN1OctetString) o.getInnerType();
o.setInnerType((ASN1OctetString) b.clone());
} catch (CloneNotSupportedException e) {
/*
* This cannot, cannot, cannot, CANNOT happen ! If it does, put back
* the import statement for 'Cloneable' into ASN1AbstractType !
*/
throw new Error("Internal, clone support mismatch!");
}
return o;
}
}

View File

@@ -0,0 +1,385 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* This type represents what was formerly called the ASN.1 ANY type. The ANY and
* ANY DEFINED BY types are superseded as of ITU-T Recommendation X.680 version
* current December 1997 by the ability to define type classes. Modelling type
* classes is beyond the scope of this ASN.1 package although the package can be
* enhanced accordingly. ASN.1 type classes can contain components whose type is
* unspecified. Such components are called &quot;open types&quot;. This class
* mimics an open type insofar as it decodes any type encountered in an encoded
* stream of ASN.1 types. On encoding the proper type is encoded in place of the
* open type. Decoding an open type that was not properly initialized either by
* a call to a creator with an argument or by decoding it from a valid ASN.1
* encoding results in an {@link ASN1Null ASN1Null} being decoded.
* <p>
*
* This class enforces as an invariant that inner types have the same tagging as
* the type itself. For instance: <blockquote>
*
* <pre>
* ASN1OpenType ot;
* ASN1Integer n;
* n = new Integer(&quot;42&quot;);
* n.setExplicit(true);
* ot = new OpenType(new FooResolver());
* ot.setExplicit(false);
* ot.setInnerType(n);
* </pre>
*
* </blockquote> will cause the tagging method of <code>n</code> to be changed
* into EXPLICIT upon the call to <code>ot.setInnerType()</code>.
*
* @author Volker Roth
* @version "$Id: ASN1OpenType.java,v 1.4 2004/08/06 15:13:01 flautens Exp $"
*/
public class ASN1OpenType extends ASN1AbstractType {
private static final String NO_INNER = "No inner type defined!";
private ASN1Type inner_;
protected Resolver resolver_;
public ASN1OpenType() {
super();
}
/**
* Creates an instance that attempts to resolve the actual type on decoding
* using the given {@link Resolver Resolver}.
*
* @param resolver
* The instance that is asked to deliver the type to decode.
*/
public ASN1OpenType(Resolver resolver) {
resolver_ = resolver;
}
/**
* This constructor corresponds to the superseded ANY DEFINED BY type. The
* open type attempts to resolve the type to decode right before decoding by
* a call to the given registry with the given OID as the argument. The
* exact OID instance is used that is passed to this method as the argument.
* If this instance is decoded before the open type is decoded (because the
* OID is encountered earlier in a decoded stream) then the open type can
* determine the exact type to decode by a call to the registry.
*
* @param oid
* The OID that is passed to the given registry on resolving.
*/
public ASN1OpenType(OIDRegistry registry, ASN1ObjectIdentifier oid) {
resolver_ = new DefinedByResolver(registry, oid);
}
public ASN1OpenType(ASN1ObjectIdentifier oid) {
resolver_ = new DefinedByResolver(oid);
}
/**
* Returns the inner ASN.1 type. If the inner type is not set and a
* {@link Resolver Resolver} is set then the Resolver is asked to resolve
* the inner type. The resulting type is then returned.
* <p>
*
* This method may return <code>null</code> if the resolver cannot
* determine the inner type of the open type. In particular, if the Resolver
* is <code>null</code> and no inner type is already set then
* <code>null</code> is returned.
*
* @return The inner ASN.1 type.
*/
public ASN1Type getInnerType() throws ResolverException {
if (inner_ != null) {
return inner_;
}
if (resolver_ == null) {
return null;
}
inner_ = resolver_.resolve(this);
return inner_;
}
/**
* Sets the inner type. The inner type inherits the tagging of this type.
*
* @param t
* The type to set as the inner type.
* @throws NullPointerException
* if the given type is <code>null</code>.
*/
protected void setInnerType(ASN1Type t) {
inner_ = t;
inner_.setExplicit(isExplicit());
}
/**
* Returns the tag of the inner type.
*
* @return The tag of the inner type.
* @throws IllegalStateException
* if the inner type is not yet initialized.
*/
public int getTag() {
if (inner_ == null) {
throw new IllegalStateException(NO_INNER);
}
return inner_.getTag();
}
/**
* Returns the tag class of the inner type.
*
* @return The tag class of the inner type.
* @throws IllegalStateException
* if the inner type is not yet initialized.
*/
public int getTagClass() {
if (inner_ == null) {
throw new IllegalStateException(NO_INNER);
}
return inner_.getTagClass();
}
/**
* Returns the value of the inner type. The default inner type is
* {@link ASN1Null ASN1Null}. This method calls
* {@link ASN1Type#getValue getValue} on the inner type and returns the
* result.
*
* @return The value of the inner type.
* @throws IllegalStateException
* if the inner type is not yet initialized.
*/
public Object getValue() {
if (inner_ == null) {
throw new IllegalStateException(NO_INNER);
}
return inner_.getValue();
}
/**
* Sets the tagging to either EXPLICIT or IMPLICIT. If this type already has
* an inner type set then the tagging of the inner type is set to the same
* tagging.
*
* @param explicit
* <code>true</code> if this type shall be tagged EXPLICIT
* and <code>false</code> if it shall be encoded IMPLICIT.
* @throws IllegalStateException
* if the inner type is not yet initialized.
*/
public void setExplicit(boolean explicit) {
super.setExplicit(explicit);
if (inner_ != null) {
inner_.setExplicit(explicit);
}
}
/**
* Sets the {@link Constraint Constraint} of the inner type. For instance an
* ASN.1 INTEGER might be constrained to a certain range such as INTEGER
* (0..99). <code>null</code> can be passed as a constraint which disables
* constraint checking.
*
* @param constraint
* The {@link Constraint Constraint} of this type.
* @throws IllegalStateException
* if the inner type is not yet initialized.
*/
public void setConstraint(Constraint constraint) {
if (inner_ == null) {
throw new IllegalStateException(NO_INNER);
}
inner_.setConstraint(constraint);
}
/**
* Checks the constraint on the inner type if it is set. Otherwise this
* method returns silently.
*
* @throws ConstraintException
* if this type is not in the appropriate range of values.
* @throws IllegalStateException
* if the inner type is not yet initialized.
*/
public void checkConstraints() throws ConstraintException {
if (inner_ == null) {
throw new IllegalStateException(NO_INNER);
}
inner_.checkConstraints();
}
/**
* This method compares the given tag and tag class with the tag and tag
* class of the resolved type.
* <p>
* If an exception is thrown by the {@link Resolver Resolver} upon resolving
* the inner type of this type then <code>false</code> is returned in
* order to provoke a decoding error.
* <p>
*
* If no inner type can be resolved then <code>true
* </code> is returned. In
* that case this type behaves like the ANY type known from previous ASN.1
* versions.
*
* @param tag
* The tag to match.
* @param tagclass
* The tag class to match.
* @return <code>true</code> iff the given tag and tag class match one of
* the alternative types represented by this variable type.
*/
public boolean isType(int tag, int tagclass) {
if (inner_ != null) {
return inner_.isType(tag, tagclass);
}
try {
if (resolver_ != null) {
inner_ = resolver_.resolve(this);
}
} catch (ResolverException e) {
return false;
}
/*
* If no inner type could be resolved then we behave like the ANY type.
*/
if (inner_ == null) {
return true;
}
return inner_.isType(tag, tagclass);
}
/**
* Encodes the inner typeof this open type using the given
* {@link Encoder Encoder}. If the inner type is not yet initialized then
* an exception is thrown.
*
* @param enc
* The {@link Encoder Encoder} to use for encoding the inner
* type.
* @throws IllegalStateException
* if the inner type is not yet initialized.
*/
public void encode(Encoder enc) throws ASN1Exception, IOException {
if (inner_ == null) {
throw new IllegalStateException(NO_INNER);
}
enc.writeType(inner_);
}
/**
* Decodes the inner type to the given {@link Decoder decoder}. If a
* {@link Resolver resolver} was specified then it is asked to provide an
* ASN.1 type to decode.
*
* @param dec
* The decoder to decode to.
* @throws IllegalStateException
* if the open type cannot be resolved on runtime.
*/
public void decode(Decoder dec) throws ASN1Exception, IOException {
if (resolver_ != null && inner_ == null) {
inner_ = resolver_.resolve(this);
}
if (inner_ == null) {
inner_ = dec.readType();
} else {
inner_.decode(dec);
}
inner_.setExplicit(isExplicit());
}
/**
* Returns the string representation of this instance.
*
* @return The string representation of this instance.
*/
public String toString() {
if (inner_ == null) {
return "Open Type <NOT InitializED>";
}
return "(Open Type) " + inner_.toString();
}
}

View File

@@ -0,0 +1,122 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.security.BasicPermission;
/**
* This permission is for controlling access to functionality of the ASN.1
* package. In particular, registering and unregistering {@link OIDRegistry
* ASN.1 Object Identifier Registries} is protected using this permission.
* Malicious code may not access the global OIDRegistries, nor register new ones
* or remove registered ones.
* <p>
*
* This permission is a simple named permission. The names distinguished are:
* <ul>
* <li> <code>OIDRegistry.add</code>
* <li> <code>OIDRegistry.remove</code>
* </ul>
*
* @author Volker Roth
* @version "$Id: ASN1Permission.java,v 1.2 2000/12/06 17:47:25 vroth Exp $"
*/
public class ASN1Permission extends BasicPermission {
/**
* Creates an instance with the given name and actions list.
*
* @param name
* The name of the permission.
* @param actions
* The actions (not used).
*/
public ASN1Permission(String name, String actions) {
super(name, actions);
}
/**
* Creates an instance with the given name and actions list.
*
* @param name
* The name of the permission.
*/
public ASN1Permission(String name) {
super(name);
}
}

View File

@@ -0,0 +1,94 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* This class represents an ASN.1 type that is officially registered. In other
* words, this type is associated with a unique OID.
*
* @author Volker Roth
* @version "$Id: ASN1RegisteredType.java,v 1.3 2004/08/06 15:14:52 flautens Exp $"
*/
public interface ASN1RegisteredType extends ASN1Type {
/**
* This method returns the official OID that identifies this ASN.1 type.
*
* @return The official ASN.1 OID of this type.
*/
public ASN1ObjectIdentifier getOID();
}

View File

@@ -0,0 +1,110 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* Represents an ASN.1 SEQUENCE type as specified in ITU-T Recommendation X.680.
*
* @author Volker Roth
* @version "$Id: ASN1Sequence.java,v 1.2 2000/12/06 17:47:25 vroth Exp $"
*/
public class ASN1Sequence extends ASN1AbstractCollection {
public ASN1Sequence() {
super();
}
/**
* Creates an instance with the given capacity.
*
* @param capacity
* The capacity.
*/
public ASN1Sequence(int capacity) {
super(capacity);
}
/**
* Returns the {@link ASN1#TAG_SEQUENCE SEQUENCE} tag.
*
* @return The {@link ASN1#TAG_SEQUENCE SEQUENCE} tag.
*/
public int getTag() {
return ASN1.TAG_SEQUENCE;
}
}

View File

@@ -0,0 +1,227 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* Represents an ASN.1 SEQUENCE OF type as specified in ITU-T Recommendation
* X.680. The SequenceOf and SetOf types do not have default constructors in
* contrast to all the other ASN1Types. The reason is that these types are never
* created directly on decoding ASN.1 structures. The decoding process always
* decodes Sequence and Set types because creating the appropriate SequenceOf or
* SetOf type requires explicit knowledge of the syntactic structure definition.
* On the other hand, if an explicit structure is given for decoding then the
* SequenceOf and SetOf types are decoded properly (because they do not have to
* be created and hence the decoder need not know the component type).
* <p>
*
* Constraints are checked only after decoding by a call to method
* {@link #decode decode}.
*
* @author Volker Roth
* @version "$Id: ASN1SequenceOf.java,v 1.3 2004/08/06 15:16:08 flautens Exp $"
*/
public class ASN1SequenceOf extends ASN1Sequence implements ASN1CollectionOf {
/**
* The {@link ASN1Type ASN1Type} from which the component types of this
* collection are created.
*/
private Resolver resolver_;
/**
* Creates an instance with the given capacity. This constructor is provided
* for subclasses that wish to handle creation of new elements themselves
* and do not rely on an application-provided element type.
*
* @param capacity
* The initial capacity of the set.
*/
protected ASN1SequenceOf(int capacity) {
super(capacity);
}
/**
* Creates an instance that keeps elements of the given type. The type must
* be a valid {@link ASN1Type ASN1Type}. The given class must be public and
* it must have a public default constructor.
*
* @param type
* The class that represents the component type of this SET
* OF.
* @throws IllegalArgumentException
* if the given class does not implement ASN1Type.
* @throws NullPointerException
* if <code>type</code> is <code>null</code>.
*/
public ASN1SequenceOf(Class type) {
if (type == null)
throw new NullPointerException("Need a class!");
resolver_ = new ClassInstanceResolver(type);
}
/**
* Creates an instance with the given capacity.
*
* @param capacity
* The capacity.
*/
public ASN1SequenceOf(Class type, int capacity) {
super(capacity);
if (type == null)
throw new NullPointerException("Need a class!");
resolver_ = new ClassInstanceResolver(type);
}
/**
* Creates an instance that uses the given {@link Resolver Resolver} to
* create new elements.
*
* @param resolver
* The resolver to use for generating elements.
*/
public ASN1SequenceOf(Resolver resolver) {
if (resolver == null) {
throw new NullPointerException("Need a resolver!");
}
resolver_ = resolver;
}
/**
* Returns the Java class representing the ASN.1 type of the elements in
* this collection or <code>ASN1Type.class
* </code> if the type cannot be
* determined.
*
* @return The ASN.1 type of the elements in this collection.
*/
public Class getElementType() {
if (resolver_ instanceof ClassInstanceResolver) {
return ((ClassInstanceResolver) resolver_).getFactoryClass();
}
return ASN1Type.class;
}
/**
* Creates and returns a new instance of the element type of this instance.
* The freshly created instance is added to this instance automatically.
* <p>
*
* New instances are created by invoking the <code>Resolver</code>
* instance set in this instance.
* <p>
*
* If no new instance can be created then an IllegalStateException is
* thrown.
* <p>
*
* <b>{@link Decoder Decoders} should call this method in order to create
* additional elements on decoding.</b> Subclasses may use this method to
* keep track on elements added to them.
*
* @return A new instance of the element type of this set.
* @throws IllegalStateException
* if no new instance could be created.
*/
public ASN1Type newElement() {
try {
ASN1Type o;
o = resolver_.resolve(this);
add(o);
return o;
} catch (Exception e) {
throw new IllegalStateException("Caught " + e.getClass().getName()
+ "(\"" + e.getMessage() + "\")");
}
}
/**
* Reads this collection from the given {@link Decoder Decoder}.
*
* @param dec
* The decoder to read from.
*/
public void decode(Decoder dec) throws ASN1Exception, IOException {
dec.readCollectionOf(this);
checkConstraints();
}
}

115
src/codec/asn1/ASN1Set.java Normal file
View File

@@ -0,0 +1,115 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* Represents an ASN.1 SET type as specified in ITU-T Recommendation X.680.
* <p>
*
* This implementation does not sort the elements according to their encodings
* as required (in principle) by the standard. Upon decoding, all decoded
* elements are kept in the order they appeared in the encoded stream.
*
* @author Volker Roth
* @version "$Id: ASN1Set.java,v 1.2 2000/12/06 17:47:26 vroth Exp $"
*/
public class ASN1Set extends ASN1AbstractCollection {
public ASN1Set() {
super();
}
/**
* Creates an instance with the given capacity.
*
* @param capacity
* The capacity.
*/
public ASN1Set(int capacity) {
super(capacity);
}
/**
* Returns the {@link ASN1#TAG_SET SET} tag.
*
* @return The {@link ASN1#TAG_SET SET} tag.
*/
public int getTag() {
return ASN1.TAG_SET;
}
}

View File

@@ -0,0 +1,253 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* Represents an ASN.1 SEQUENCE OF type as specified in ITU-T Recommendation
* X.680. The SequenceOf and SetOf types do not have default constructors in
* contrast to all the other ASN1Types. The reason is that these types are never
* created directly on decoding ASN.1 structures. The decoding process always
* decodes Sequence and Set types because creating the appropriate SequenceOf or
* SetOf type requires explicit knowledge of the syntactic structure definition.
* On the other hand, if an explicit structure is given for decoding then the
* SequenceOf and SetOf types are decoded properly (because they do not have to
* be created and hence the decoder need not know the component type).
* <p>
*
* This implementation does not sort the elements according to their encodings
* as required (in principle) by the standard. Upon decoding, all decoded
* elements are kept in the order they appeared in the encoded stream.
* <p>
*
* Constraints are checked after decoding instances of this type.
*
* @author Volker Roth
* @version "$Id: ASN1SetOf.java,v 1.3 2004/08/09 06:59:23 flautens Exp $"
*/
public class ASN1SetOf extends ASN1Set implements ASN1CollectionOf {
/**
* The {@link ASN1Type ASN1Type} from which the component types of this
* collection are created.
*/
private Resolver resolver_;
/**
* Creates an instance with the given capacity. This constructor is provided
* for subclasses that wish to handle creation of new elements themselves
* and do not rely on an application-provided element type.
*
* @param capacity
* The initial capacity of the set.
*/
protected ASN1SetOf(int capacity) {
super(capacity);
}
/**
* Creates an instance that keeps elements of the given type. The type must
* be a valid {@link ASN1Type ASN1Type}. The given class must be public and
* it must have a public default constructor.
*
* @param type
* The class that represents the component type of this SET
* OF.
* @throws IllegalArgumentException
* if the given class does not implement ASN1Type.
* @throws NullPointerException
* if <code>type</code> is <code>null</code>.
*/
public ASN1SetOf(Class type) {
if (type == null)
throw new NullPointerException("Need a class!");
resolver_ = new ClassInstanceResolver(type);
}
/**
* Creates an instance with the given capacity.
*
* @param capacity
* The capacity.
*/
public ASN1SetOf(Class type, int capacity) {
super(capacity);
if (type == null)
throw new NullPointerException("Need a class!");
resolver_ = new ClassInstanceResolver(type);
}
/**
* Creates an instance that uses the given {@link Resolver Resolver} to
* create new elements.
*
* @param resolver
* The resolver to use for generating elements.
*/
public ASN1SetOf(Resolver resolver) {
if (resolver == null) {
throw new NullPointerException("Need a resolver!");
}
resolver_ = resolver;
}
/**
* Creates an instance that uses the given {@link Resolver Resolver} to
* create new elements.
*
* @param resolver
* The resolver to use for generating elements.
* @param capacity
* The capacity.
*/
public ASN1SetOf(Resolver resolver, int capacity) {
/*
* This method is used by the updated codec.x501.Name class. I inserted
* this method. --volker roth
*/
super(capacity);
if (resolver == null) {
throw new NullPointerException("Need a resolver!");
}
resolver_ = resolver;
}
/**
* Returns the Java class representing the ASN.1 type of the elements in
* this collection or <code>ASN1Type.class
* </code> if the type cannot be
* determined.
*
* @return The ASN.1 type of the elements in this collection.
*/
public Class getElementType() {
if (resolver_ instanceof ClassInstanceResolver) {
return ((ClassInstanceResolver) resolver_).getFactoryClass();
}
return ASN1Type.class;
}
/**
* Creates and returns a new instance of the element type of this instance.
* The freshly created instance is added to this instance automatically.
* <p>
*
* New instances are created by invoking the <code>Resolver</code>
* instance set in this instance.
* <p>
*
* If no new instance can be created then an IllegalStateException is
* thrown.
* <p>
*
* <b>{@link Decoder Decoders} should call this method in order to create
* additional elements on decoding.</b> Subclasses may use this method to
* keep track on elements added to them.
*
* @return A new instance of the element type of this set.
* @throws IllegalStateException
* if no new instance could be created.
*/
public ASN1Type newElement() {
try {
ASN1Type o;
o = resolver_.resolve(this);
add(o);
return o;
} catch (Exception e) {
throw new IllegalStateException("Caught " + e.getClass().getName()
+ "(\"" + e.getMessage() + "\")");
}
}
/**
* Reads this collection from the given {@link Decoder Decoder}.
*
* @param dec
* The decoder to read from.
*/
public void decode(Decoder dec) throws ASN1Exception, IOException {
dec.readCollectionOf(this);
checkConstraints();
}
}

View File

@@ -0,0 +1,143 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* The common interface of all ASN.1 string types. This interface specifies
* setter and getter methods for string values and methods for string to octet
* and octet to string conversion. See {@link ASN1AbstractString
* ASN1AbstractString} for details on strings.
*
* @author Volker Roth
* @version "$Id: ASN1String.java,v 1.2 2000/12/06 17:47:26 vroth Exp $"
* @see ASN1AbstractString
*/
public interface ASN1String extends ASN1Type {
/**
* Returns the represented string value.
*
* @return The string value of this type.
*/
public String getString();
/**
* Sets the string value.
*
* @param s
* The string value.
*/
public void setString(String s) throws ConstraintException;
/**
* Converts the given byte array to a string.
*
* @param b
* The byte array to convert.
*/
public String convert(byte[] b) throws ASN1Exception;
/**
* Converts the given string to a byte array.
*
* @param s
* The string to convert.
*/
public byte[] convert(String s) throws ASN1Exception;
/**
* Returns the number of octets required to encode the given string
* according to the basic encoding scheme of this type. For restricted
* string types this likely equals the number of characters in the string
* unless special characters or escape sequences are allowed. For
* {@link ASN1BMPString BMPStrings} this is twice the number of characters
* and for {@link ASN1UniversalString UniversalStrings} it is four times the
* number of characters in the string.
* <p>
*
* The number returned must equal the number returned by the method call
* {@link #convert(java.lang.String) convert(s)}. This method is required
* for DER encoding of string types in order to determine the number of
* octets required for encoding the given string. For BER encoding this
* method is not and the encoding of the string may be broken up into
* consecutive OCTET STRINGS.
*
* @param s
* The string whose encoding length is determined.
*/
public int convertedLength(String s) throws ASN1Exception;
}

View File

@@ -0,0 +1,110 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.util.Comparator;
/**
* ASN1 Comparator, used for Sorting an ASN1 Set. First TagClasses of the
* ASN1Types are compared. If they are equal, the Tags of the ASN1Types are
* compared. result is : 1, 0, -1 for a1 > a2, a1 = a2, a1 < a2
*/
public class ASN1TagComparator implements Comparator {
public int compare(Object o1, Object o2) {
ASN1Type a1 = (ASN1Type) o1;
ASN1Type a2 = (ASN1Type) o2;
if (a1.getTagClass() > a2.getTagClass())
return 1;
if (a1.getTagClass() == a2.getTagClass()) {
if (a1.getTag() > a2.getTag()) {
return 1;
}
if (a1.getTag() == a2.getTag()) {
return 0;
}
// only this option, a1.Tag() < a2.Tag() left
return -1;
}
// only this option, a1.TagClass() < a2.TagClass() left
return -1;
}
}

View File

@@ -0,0 +1,328 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* Represents an ASN.1 tagged type. Tagged types are types that modify the tag
* of an underlying type. The ASN.1 type classes
* {@link ASN1#CLASS_CONTEXT CONTEXT}, {@link ASN1#CLASS_PRIVATE PRIVATE}, and
* {@link ASN1#CLASS_APPLICATION APPLICATION} specify tagged types.
*
* @author Volker Roth
* @version "$Id: ASN1TaggedType.java,v 1.4 2004/08/09 07:45:30 flautens Exp $"
*/
public class ASN1TaggedType extends ASN1AbstractType {
private int tag_;
private int cls_ = ASN1.CLASS_CONTEXT;
private ASN1Type inner_;
/**
* Creates an instance with the given tag, tag class, and inner type. The
* tagging method is EXPLICIT if <code>
* explicit</code> is
* <code>true</code> and IMPLICIT otherwise.
*
* @param tag
* The tag of this type.
* @param cls
* The tag class of this type, for instance
* {@link ASN1#CLASS_CONTEXT CONTEXT SPECIFIC}.
* @param inner
* The inner type of this tagged type.
* @param explicit
* <code>true</code> if EXPLICIT tagging shall be used and
* <code>false</code> if the tagging method shall be
* IMPLICIT.
* @throws NullPointerException
* if the given inner type is <code>null</code>.
*/
public ASN1TaggedType(int tag, int cls, ASN1Type inner, boolean explicit) {
setTag(tag);
setTagClass(cls);
setInnerType(inner);
inner_.setExplicit(explicit);
}
/**
* Creates an instance with the given tag and inner type. The tagging method
* is EXPLICIT if <code>
* explicit</code> is <code>true</code> and
* IMPLICIT otherwise. The tag class is set to {@link ASN1#CLASS_CONTEXT
* CONTEXT SPECIFIC}.
*
* @param tag
* The tag of this type.
* @param inner
* The inner type of this tagged type.
* @param explicit
* <code>true</code> if EXPLICIT tagging shall be used and
* <code>false</code> if the tagging method shall be
* IMPLICIT.
* @throws NullPointerException
* if the given inner type is <code>null</code>.
*/
public ASN1TaggedType(int tag, ASN1Type inner, boolean explicit) {
setTag(tag);
setTagClass(ASN1.CLASS_CONTEXT);
setInnerType(inner);
inner_.setExplicit(explicit);
}
/**
* Creates an instance with the given tag, tag class, and inner type. The
* tagging method is EXPLICIT if <code>
* explicit</code> is
* <code>true</code> and IMPLICIT otherwise. The tag class is set to
* {@link ASN1#CLASS_CONTEXT CONTEXT SPECIFIC}. If <code>
* optional</code>
* is <code>true</code> then this type is declared OPTIONAL.
*
* @param tag
* The tag of this type.
* @param inner
* The inner type of this tagged type.
* @param explicit
* <code>true</code> if EXPLICIT tagging shall be used and
* <code>false</code> if the tagging method shall be
* IMPLICIT.
* @param optional
* <code>true</code> declares this type as OPTIONAL.
* @throws NullPointerException
* if the given inner type is <code>null</code>.
*/
public ASN1TaggedType(int tag, ASN1Type inner, boolean explicit,
boolean optional) {
setTag(tag);
setTagClass(ASN1.CLASS_CONTEXT);
setInnerType(inner);
inner_.setExplicit(explicit);
setOptional(optional);
}
/**
* Returns the underlying ASN.1 type. Please note that OPTIONAL modifiers of
* (for instance) context-specific types in compound ASN.1 types refer to
* the outer type and not to the inner type. Types are declared OPTIONAL by
* calling their {@link ASN1Type#setOptional setOptional} method.
*
* @return The underlying ASN.1 type.
*/
public ASN1Type getInnerType() {
return inner_;
}
/**
* Returns the value of the inner type. The default inner type is
* {@link ASN1Null ASN1Null}. This method calls
* {@link ASN1Type#getValue getValue} on the inner type and returns the
* result.
*
* @return The value of the inner type.
*/
public Object getValue() {
return inner_.getValue();
}
/**
* Sets the inner type of this CONTEXT SPECIFIC type.
*
* @param t
* The type to set as the inner type.
* @throws NullPointerException
* if the given type is <code>null</code>.
*/
public void setInnerType(ASN1Type t) {
if (t == null) {
throw new NullPointerException("Type is NULL!");
}
inner_ = t;
}
/**
* Sets the tag of this type.
*
* @param tag
* The tag.
*/
public void setTag(int tag) {
tag_ = tag;
}
/**
* Returns the tag of this type.
*
* @return The tag of this type.
*/
public int getTag() {
return tag_;
}
/**
* Sets the tag class of this type. This tag class may be one of
* {@link ASN1#CLASS_UNIVERSAL UNIVERSAL}, {@link ASN1#CLASS_CONTEXT
* CONTEXT SPECIFIC}, {@link ASN1#CLASS_PRIVATE PRIVATE}, or {@link
* ASN1#CLASS_APPLICATION APPLICATION}.
*
* @param cls
* The tag class.
*/
public void setTagClass(int cls) {
cls_ = cls;
}
/**
* Returns the tag class of this type. The default class of this instance is
* {@link ASN1#CLASS_CONTEXT CONTEXT SPECIFIC}.
*
* @return The class of this ASN.1 tag.
*/
public int getTagClass() {
return cls_;
}
/**
* Tagged types themselves are always tagged EXPLICIT. The inner type can be
* tagged either EXPLICIT or IMPLICIT. IMPLICIT types are isomorphic to the
* underlying type except that the tag and tag class is distinct (with
* regard to encoding).
*
* @return <code>true</code>, tagged types themselves are always tagged
* EXPLICIT.
*/
public boolean isExplicit() {
return true;
}
/**
* Throws an exception if the give tagging type is not EXPLICIT (<code>true</code>).
* Tagged types themselves are always EXPLICIT; re-tagging tagged types is
* <b> very</b> bad style!
*
* @param explicit
* The tagging method of the tagged (outer) type. This should
* not be mixed with the tagging method of the inner type
* which can be tagged either EXPLICIT or IMPLICIT.
*/
public void setExplicit(boolean explicit) {
if (!explicit)
throw new IllegalArgumentException(
"Tagget types are never IMPLICIT!");
}
public void encode(Encoder enc) throws ASN1Exception, IOException {
enc.writeTaggedType(this);
}
public void decode(Decoder dec) throws ASN1Exception, IOException {
dec.readTaggedType(this);
}
public String toString() {
StringBuffer buf;
buf = new StringBuffer();
buf.append("[");
switch (cls_) {
case ASN1.CLASS_CONTEXT:
buf.append("CONTEXT SPECIFIC ");
break;
case ASN1.CLASS_UNIVERSAL:
buf.append("UNIVERSAL ");
break;
case ASN1.CLASS_APPLICATION:
buf.append("APPLICATION ");
break;
case ASN1.CLASS_PRIVATE:
buf.append("PRIVATE ");
break;
}
buf.append(tag_ + "] ");
if (inner_.isExplicit())
buf.append("EXPLICIT ");
else
buf.append("IMPLICIT ");
buf.append(inner_.toString());
return buf.toString();
}
}

View File

@@ -0,0 +1,502 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
/**
* This is the root class of all ASN.1 time types. In principle, the known time
* types are all of type VisibleString.
*
* @author Volker Roth
* @version "$Id: ASN1Time.java,v 1.7 2004/09/20 15:22:31 pebinger Exp $"
*/
abstract public class ASN1Time extends ASN1VisibleString {
/**
* The <code>TimeZone</code> representing universal coordinated time
* (UTC).
*/
private static final TimeZone TZ = TimeZone.getTimeZone("GMT");
/**
* Used to fill with zeroes.
*/
protected static final String ZEROES = "0000";
/**
* The internal storage of the date.
*/
protected Date date_;
/**
* Returns a Java Date instance representing the time in this ASN.1 time
* type.
*
* @return The time as a Java Date instance.
*/
public Date getDate() {
return (Date) date_.clone();
}
/**
* Returns a Java long representing the time in milliseconds since January
* 1, 1970, 00:00:00 GMT in this ASN.1 time type.
*
* @return The number of milliseconds since January 1, 1970, 00:00:00 GMT.
*/
public long getTime() {
return date_.getTime();
}
/**
* Sets the time from the given <code>Calendar</code>.
*
* @param calendar
* The <code>Calendar</code> with the date that shall be
* set.
*/
public void setDate(Calendar calendar) {
if (calendar == null) {
throw new NullPointerException("calendar");
}
date_ = calendar.getTime();
setString0(toString(date_));
}
/**
* Sets the time from the given Date instance.
*
* @param date
* The Date.
*/
public void setDate(Date date) {
if (date == null) {
throw new NullPointerException("date");
}
date_ = (Date) date.clone();
setString0(toString(date_));
}
/**
* Sets the time from the given time in milliseconds since January 1, 1970,
* 00:00:00 GMT.
*
* @param time
* The number of milliseconds since January 1, 1970, 00:00:00
* GMT.
*/
public void setDate(long time) {
date_ = new Date(time);
setString0(toString(date_));
}
/**
* Sets the date to the one represented by the given string. The internal
* string representation is normalized and complies to DER. The date string
* is thus converted to GMT.
*
* @param date
* The date as a X.680 date string.
* @throws IllegalArgumentException
* if the string is not well-formed.
* @throws StringIndexOutOfBoundsException
* if the string is not well-formed.
*/
public void setDate(String date) {
if (date == null) {
throw new NullPointerException("date string");
}
date_ = toDate(date);
setString0(toString(date_));
}
/**
* Sets the string value.
*
* @param s
* The string value.
*/
public void setString(String s) {
date_ = toDate(s);
/*
* The value must be set literally because this method is called by the
* decoders. This ensures that the encoding is bitwise identical to the
* decoding.
*/
setString0(s);
}
public void encode(Encoder enc) throws ASN1Exception, IOException {
enc.writeTime(this);
}
public void decode(Decoder enc) throws ASN1Exception, IOException {
enc.readTime(this);
}
abstract protected int[] getFields();
abstract protected int[] getFieldLengths();
abstract protected int[] getFieldCorrections();
/**
* Converts the given <code>Date</code> into a string representation
* according to DER as described in X.690.
*
* @param date
* The <code>Date</code> that is converted.
* @return The string with the date.
*/
protected String toString(Date date) {
StringBuffer buf;
Calendar cal;
String s;
int[] lengths;
int[] correct;
int[] fields;
int len;
int w;
int n;
int v;
int lastzero;
if (date == null) {
throw new NullPointerException("date");
}
cal = new GregorianCalendar(TZ);
fields = getFields();
correct = getFieldCorrections();
lengths = getFieldLengths();
buf = new StringBuffer(20);
/*
* Date is UTC time (most of the time ;-) and we set Calendar to UTC.
*/
cal.setTime(date);
for (n = 0; n < fields.length; n++) {
v = cal.get(fields[n]) - correct[n];
s = String.valueOf(v);
len = s.length();
/*
* If the target length is zero then we truncate to the left, and
* take only the hundreds if they are greater than zero. Hence, only
* one digit is printed. In summary, we handle the case of
* milliseconds.
*/
w = lengths[n];
if (w == 0) {
if (v > 0) {
buf.append(".");
// add leading 0s if necessary
s = ZEROES.substring(0, 3 - s.length()) + s;
if (s.charAt(s.length() - 1) != '0') {
buf.append(s);
} else {
lastzero = s.length() - 1;
while ((lastzero > 0)
&& (s.charAt(lastzero - 1) == '0')) {
lastzero--;
}
buf.append(s.substring(0, lastzero));
}
}
continue;
}
/*
* If we have to fill up then we fill zeroes to the left. This
* accounts for days as well as hours and minutes.
*/
if (w < 0) {
w = -w;
}
if (len < w) {
buf.append(ZEROES.substring(0, w - len));
buf.append(s);
}
/*
* If we must truncate then we take the rightmost characters. This
* accounts for truncated years e.g. "98" instead of "1998".
*/
else if (len > w) {
buf.append(s.substring(len - w));
}
/*
* Everything is fine, we got the length we need.
*/
else {
buf.append(s);
}
}
buf.append('Z');
return buf.toString();
}
/**
* Converts the given string to a <code>Date</code> object.
*
* @param code
* The string encoding of the date to be converted.
* @return The <code>Date</code> object.
* @throws IllegalArgumentException
* if the given string is not a valid BER encoding of a
* date.
*/
protected Date toDate(String code) {
Calendar cal;
Calendar res;
TimeZone tz;
int[] lengths;
int[] correct;
int[] fields;
String s;
int pos;
int len;
int n;
int w;
int v;
int c;
if (code == null) {
throw new NullPointerException("code");
}
cal = new GregorianCalendar(TZ);
cal.setTime(new Date(0));
fields = getFields();
correct = getFieldCorrections();
lengths = getFieldLengths();
len = code.length();
for (pos = 0, n = 0; n < fields.length; n++) {
/*
* If the field length is zero then we handle milliseconds. In
* particular, we test whether the milliseconds are present.
*/
w = lengths[n];
if (w == 0) {
/*
* No character, no period or comma, therefor no milliseconds
* either.
*/
if (pos >= len) {
continue;
}
c = code.charAt(pos);
/*
* No period or comma but another character presumably means
* that there are no millis but a time zone offset - or a bad
* code.
*/
if (c != '.' && c != ',') {
continue;
}
pos++;
/*
* We have millis, and now we're gonna read them!
*/
for (v = 0; (v < 3 && pos < len); v++) {
if (!Character.isDigit(code.charAt(pos))) {
break;
}
pos++;
}
/*
* If we did not consume at least one digit then we have a bad
* encoding.
*/
if (v == 0) {
throw new IllegalArgumentException(
"Milliseconds format error!");
}
s = code.substring(pos - v, pos);
if (v < 3) {
s = s + ZEROES.substring(0, 3 - v);
}
v = Integer.parseInt(s);
v = v + correct[n];
cal.set(fields[n], v);
continue;
}
/*
* Here we deal with optional digit fields such as seconds in BER.
*/
if (w < 0) {
w = -w;
if (pos >= len || !Character.isDigit(code.charAt(pos))) {
continue;
}
}
/*
* We fetch the required number of characters and try to decode
* them.
*/
s = code.substring(pos, pos + w);
v = Integer.parseInt(s);
v = v + correct[n];
pos = pos + w;
/*
* Special case for UTCTime: we have to correct for years before
* 1970.
*/
if (fields[n] == Calendar.YEAR && lengths[n] == 2) {
v = v + ((v < 70) ? 2000 : 1900);
}
cal.set(fields[n], v);
}
/*
* We still have to deal with time zone offsets and time zone
* specifications - nasty stuff.
*/
if (pos < len) {
c = code.charAt(pos);
/*
* If there is a '+' or '-' then we have a time differential to GMT
* and no trailing 'Z'.
*/
if (c == '+' || c == '-') {
s = code.substring(pos, pos + 5);
tz = TimeZone.getTimeZone("GMT" + s);
pos = pos + 5;
}
/*
* No time differential means we either have a 'Z' or a bad
* encoding.
*/
else if (code.charAt(pos) != 'Z') {
throw new IllegalArgumentException(
"Illegal char in place of 'Z' (" + pos + ")");
}
/*
* We got the 'Z', thus we have GMT.
*/
else {
tz = TimeZone.getTimeZone("GMT");
pos++;
}
}
/*
* We reached the end of the string without encountering a time
* differential or a 'Z', therefor we use the local time zone. This
* should rarely happen unless someone screws up. Nevertheless, it's a
* valid code.
*/
else {
tz = TimeZone.getDefault();
}
if (pos != len) {
throw new IllegalArgumentException(
"Trailing characters after encoding! (" + pos + ")");
}
/*
* we now have a Calendar calibrated to GMT and a time zone in tz. Now
* we merge both together in order to get the correct time according to
* GMT.
*/
res = Calendar.getInstance(tz);
res.setTime(new Date(0));
for (n = 0; n < fields.length; n++) {
res.set(fields[n], cal.get(fields[n]));
}
return res.getTime();
}
}

View File

@@ -0,0 +1,168 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* The basic interface for Java objects representing primitive ASN.1 types
* according to ITU-T Recommendation X.680. A special feature are
* {@link Constraint constraints}. With constraints the range of valid values
* of an ASN.1 type can be limited. Constraints are validated for most types in
* the setter methods allowing initialization with Java types.
* <p>
*
* An abstract implementation of most of the methods declared in this interface
* can be found in {@link ASN1AbstractType ASN1AbstractType}.
*
* @author Volker Roth
* @version "$Id: ASN1Type.java,v 1.2 2000/12/06 17:47:26 vroth Exp $"
*/
public interface ASN1Type {
public Object getValue();
public void setOptional(boolean optional);
public boolean isOptional();
public int getTag();
public int getTagClass();
public void setExplicit(boolean explicit);
public boolean isExplicit();
/**
* Returns <code>true</code> if this type matches the given tag and
* tagclass. This method is primarily used by decoders in order to verify
* the tag and tag class of a decoded type. Basic types need not implement
* this method since {@link ASN1AbstractType ASN1AbstractType} provides a
* default implementation. Certain variable types such as {@link ASN1Choice
* ASN1Choice} and {@link ASN1OpenType ASN1OpenType} implement this method.
* This helps decoders to determine if a decoded type matches a given ASN.1
* structure.
*
* @param tag
* The tag to match.
* @param tagclass
* The tag class to match.
* @return <code>true</code> if this type matches the given tag and tag
* class.
*/
public boolean isType(int tag, int tagclass);
public void encode(Encoder enc) throws ASN1Exception, IOException;
public void decode(Decoder dec) throws ASN1Exception, IOException;
/**
* Sets a {@link Constraint constraint} for this type. Constraints are
* checked by setter methods and as the last operation of a call to the
* {@link ASN1Type#decode decode()} method.
*
* A number of constraints can be defined in ASN.1; one example is the SIZE
* constraint on string types. For instance,
* <tt>foo IA5String (SIZE 10..20)</tt> means the string <tt>foo</tt>
* can be 10 to 20 characters long. Strings can also be constrained with
* regard to the character sets. The constraint model of this package allows
* to add arbitrary constraints on types.
* <p>
*
* @param o
* The constraint to set.
*/
public void setConstraint(Constraint o);
/**
* Returns the {@link Constraint Constraint} of this type or
* <code>null</code> if there is none.
*
* @return The Constraint or <code>null</code>.
*/
public Constraint getConstraint();
/**
* Checks the {@link Constraint constraints} registered with this instance.
*
* @see Constraint
* @see ConstraintCollection
*/
public void checkConstraints() throws ConstraintException;
}

View File

@@ -0,0 +1,105 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* This class represents an ASN.1 T61String as described in ITU-T Recommendation
* X.680. Note that no value checking is performed!
*
* @author Markus Tak (by cut-and-paste ;-) )
* @version "$Id: ASN1VisibleString.java,v 1.1 2004/08/09 07:53:21 flautens Exp $"
*/
public class ASN1VisibleString extends ASN1AbstractString {
public ASN1VisibleString() {
super();
}
/**
* Creates an instance with the given string value. No constraints can be
* set yet so none are checked.
*
* @param s
* The string value.
*/
public ASN1VisibleString(String s) {
super(s);
}
public int getTag() {
return ASN1.TAG_VISIBLESTRING;
}
}

View File

@@ -0,0 +1,262 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author Volker Roth
* @version "$Id: AbstractEncoder.java,v 1.3 2005/03/22 15:55:36 flautens Exp $"
*/
public abstract class AbstractEncoder extends FilterOutputStream implements
Encoder {
/**
* Creates an encoder that writes its output to the given output stream.
*
* @param out
* The output stream to which the encoded ASN.1 objects are
* written.
*/
public AbstractEncoder(OutputStream out) {
super(out);
}
/**
*
*/
public void writeType(ASN1Type t) throws ASN1Exception, IOException {
t.encode(this);
}
/**
* This method encodes identifier and length octets. The given length can be
* negative in which case 0x80 is written to indicate INDEFINITE LENGTH
* encoding. Please note that this is appropriate only for a BER encoding or
* CER encoding (ITU-T Recommenation X.690). Encoders are responsible for
* writing the end of code octets <code>0x00 0x00</code> after encoding
* the content octets.
*
* @param tag
* The ASN.1 tag
* @param cls
* The ASN.1 tag class.
* @param prim
* <code>true</code> if the encoding is PRIMITIVE and
* <code>false</code> if it is CONSTRUCTED.
* @param len
* The number of content octets or -1 to indicate INDEFINITE
* LENGTH encoding.
*/
protected void writeHeader(int tag, int cls, boolean prim, int len)
throws IOException {
int b;
int i;
b = cls & ASN1.CLASS_MASK;
if (!prim) {
b = b | ASN1.CONSTRUCTED;
}
if (tag > 30) {
b = b | ASN1.TAG_MASK;
out.write(b);
writeBase128(tag);
} else {
b = b | tag;
out.write(b);
}
if (len == -1) {
out.write(0x80);
} else {
if (len > 127) {
i = (significantBits(len) + 7) / 8;
out.write(i | 0x80);
writeBase256(len);
} else {
out.write(len);
}
}
}
/**
* This method computes the number of octets needed to encode the identifier
* and length octets of the {@link ASN1Type ASN.1 type} with the given tag
* and contents length. The given length can be negative in which case
* INDEFINITE LENGTH encoding is assumed.
*
* @return The number of octets required for encoding the identifier and
* length octets.
* @param tag
* The ASN.1 tag.
* @param len
* The number of contents octets of the ASN.1 type with the
* given tag and length.
*/
protected int getHeaderLength(int tag, int len) {
int n;
n = 2;
if (tag > 30) {
n = n + ((significantBits(tag) + 6) / 7);
}
if (len > 127) {
n = n + ((significantBits(len) + 7) / 8);
}
return n;
}
/**
* Writes the given integer to the output in base 128 representation with
* bit 7 of all octets except the last one being set to &quot;1&quot;. The
* minimum number of octets necessary is used.
*
* @param n
* The integer to be written to the output.
* @throws IOException
* Thrown by the underlying output stream.
*/
protected void writeBase128(int n) throws IOException {
int i;
int j;
i = (significantBits(n) + 6) / 7;
j = (i - 1) * 7;
while (i > 1) {
out.write(((n >>> j) & 0x7f) | 0x80);
j = j - 7;
i--;
}
out.write(n & 0x7f);
}
/**
* Writes the given integer to the output in base 256 with the minimal
* number of octets.
*
* @param n
* The integer to be written to the output.
* @throws IOException
* Thrown by the underlying output stream.
*/
protected void writeBase256(int n) throws IOException {
int i;
int j;
i = (significantBits(n) + 7) / 8;
j = (i - 1) * 8;
while (i > 0) {
out.write((n >>> j) & 0xff);
j = j - 8;
i--;
}
}
/**
* Counts the number of significant bits in the given integer. There is
* always at least one significant bit.
*
* @param n
* The integer.
* @return The number of significant bits in the given integer.
*/
protected int significantBits(int n) {
int i;
if (n == 0) {
return 1;
}
i = 0;
while (n > 255) {
n = n >>> 8;
i += 8;
}
while (n > 0) {
n = n >>> 1;
i++;
}
return i;
}
}

View File

@@ -0,0 +1,149 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* Resolves requests for instances based on a class object. New instances are
* generated by invoking <code>newInstance()
* </code> on the wrapped class
* object. The class must provide a no-arg default constructor.
*
* @author Volker Roth
* @version "$Id: ClassInstanceResolver.java,v 1.2 2000/12/06 17:47:27 vroth Exp $"
*/
public class ClassInstanceResolver extends Object implements Resolver {
/**
* The class that is used as a factory.
*/
private Class factory_;
/**
* Creates an instance with the given factory class.
*
* @param factory
* The factory class.
* @throws IllegalArgumentException
* if <code>factory</code> has no default constructor, or
* does not implement <code>
* ASN1Type</code>.
*/
public ClassInstanceResolver(Class factory) {
if (factory == null) {
throw new NullPointerException("Need a factory class!");
}
try {
factory.getConstructor(new Class[0]);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Class " + factory.getName()
+ " has no default constructor!");
}
if (!ASN1Type.class.isAssignableFrom(factory)) {
throw new IllegalArgumentException("Class " + factory.getName()
+ " is not an ASN1Type!");
}
factory_ = factory;
}
/**
* Returns the class object of the factory class.
*
* @return The class object.
*/
public Class getFactoryClass() {
return factory_;
}
/**
* Resolves the call by returning a new instance of the the factory class.
* The factory class must have been specified at the time of constructing
* this instance.
*
* @param caller
* The caller. The caller is ignored.
* @throws ResolverException
* if for some reason the call cannot be resolved.
*/
public ASN1Type resolve(ASN1Type caller) throws ResolverException {
try {
return (ASN1Type) factory_.newInstance();
} catch (Exception e) {
throw new ResolverException("Caught " + e.getClass().getName()
+ "(\"" + e.getMessage() + "\")");
}
}
}

View File

@@ -0,0 +1,93 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* This interface specifies a constraint of some ASN.1 type. Constraints are
* called to check the validity of a type right after initialization and after
* decoding. For instance an OCTET STRING may be defined to be at most 8 octets
* long. This may be implemented by adding a constraint to an
* {@link ASN1OctetString ASN1OctetString} instance that verifies the length of
* the octets string.
*
* @author Volker Roth
* @version "$Id: Constraint.java,v 1.2 2000/12/06 17:47:28 vroth Exp $"
*/
public interface Constraint {
public void constrain(ASN1Type o) throws ConstraintException;
}

View File

@@ -0,0 +1,94 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* Thrown by {@link Constraint Constraint} instances if the validation of some
* ASN.1 type fails.
*
* @author Volker Roth
* @version "$Id: ConstraintException.java,v 1.2 2000/12/06 17:47:28 vroth Exp $"
*/
public class ConstraintException extends ASN1Exception {
public ConstraintException() {
}
public ConstraintException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,119 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.util.Comparator;
/**
* Compares two DER Encodings and orders them according to the strict ordering
* rules applied in DER encoded SET OF types.
*
* @author Volker Roth
* @version "$Id: DERCodeComparator.java,v 1.1 2004/08/09 07:57:53 flautens Exp $"
*/
public class DERCodeComparator extends Object implements Comparator {
public int compare(Object o1, Object o2) {
byte[] a1;
byte[] a2;
int n;
int m;
int x;
int y;
a1 = (byte[]) o1;
a2 = (byte[]) o2;
m = Math.min(a1.length, a2.length);
for (n = 0; n < m; n++) {
x = a1[n] & 0xff;
y = a2[n] & 0xff;
if (x < y) {
return -1;
} else if (x > y) {
return 1;
}
}
if (a1.length == a2.length) {
return 0;
} else if (a1.length < a2.length) {
return -1;
}
return 1;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,571 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
/**
* If ,right after instantiating the encoder, the strict parameter is set to
* true, the encoder uses the strict encoding rules from X680/X690 for Sets and
* SetOfs. As long as the flag is not set, the encoder behaves as usual.
*
* @author Volker Roth
* @version "$Id: DEREncoder.java,v 1.7 2004/08/09 11:10:08 flautens Exp $"
*/
public class DEREncoder extends AbstractEncoder {
private int[] stack_;
private int sp_;
/**
* if true, the strict encoding rules for sets and set of are used.
*/
private boolean strict = false;
/**
* This variable has a bit set for each tag that denotes a CONSTRUCTED type.
*/
private int constructed_ = ((1 << ASN1.TAG_SEQUENCE) | (1 << ASN1.TAG_SET) | (1 << ASN1.TAG_REAL));
/**
* Creates an encoder that writes its output to the given output stream.
*
* @param out
* The output stream to which the encoded ASN.1 objects are
* written.
*/
public DEREncoder(OutputStream out) {
super(out);
}
/**
* returns the value of the strict parameter.
*/
public boolean isStrict() {
return this.strict;
}
/**
* Sets the value of the strict parameter.
*/
public void setStrict(boolean _strictness) {
this.strict = _strictness;
}
/**
* Encodes the identifier and length octets. If there are no known lengths
* then this method creates and runs a
* {@link RunLengthEncoder RunLengthEncoder} on the given type in order to
* establish the length of it and of any contained types. This method must
* not be called with OPTIONAL types else errors may occur. It is the
* responsibility of the caller to ascertain this precondition. Only the
* headers of types that are tagged {@link ASN1Type#isExplicit EXPLICIT} are
* encoded. If the given type is tagged IMPLICIT then this method simply
* returns.
*
* @param t
* The type of which the header is encoded.
* @param primitive
* <code>true</code> if the encoding is PRIMITIVE and
* <code>false</code> if it is CONSTRUCTED.
*/
protected void writeHeader(ASN1Type t, boolean primitive)
throws ASN1Exception, IOException {
int length;
if (!t.isExplicit()) {
return;
}
if (stack_ == null || sp_ == 0) {
RunLengthEncoder enc;
enc = new RunLengthEncoder();
enc.writeType(t);
stack_ = enc.getLengthFields();
sp_ = stack_.length;
if (sp_ < 1) {
throw new ASN1Exception("Cannot determine length!");
}
}
length = stack_[--sp_];
writeHeader(t.getTag(), t.getTagClass(), primitive, length);
}
public void writeBoolean(ASN1Boolean t) throws ASN1Exception, IOException {
if (t.isOptional())
return;
writeHeader(t, true);
write(t.isTrue() ? 0xff : 0x00);
}
public void writeInteger(ASN1Integer t) throws ASN1Exception, IOException {
if (t.isOptional())
return;
writeHeader(t, true);
write(t.getBigInteger().toByteArray());
}
public void help(byte[] b) {
int i;
for (i = 0; i < b.length; i++) {
System.err.println(" " + (b[i] & 0xff));
}
}
/**
* Encodes a bitstring. This method expects that the bitstring instance is
* already compact. In other words, it does not contain trailing zeroes and
* the pad count is in the range of zero to seven.
*/
public void writeBitString(ASN1BitString t) throws ASN1Exception,
IOException {
if (t.isOptional()) {
return;
}
writeHeader(t, true);
write(t.getPadCount());
if (!t.isZero()) {
write(t.getBytes());
}
}
public void writeOctetString(ASN1OctetString t) throws ASN1Exception,
IOException {
if (t.isOptional())
return;
writeHeader(t, true);
write(t.getByteArray());
}
public void writeNull(ASN1Null t) throws ASN1Exception, IOException {
if (t.isOptional())
return;
writeHeader(t, true);
}
public void writeObjectIdentifier(ASN1ObjectIdentifier t)
throws ASN1Exception, IOException {
if (t.isOptional())
return;
writeHeader(t, true);
int i;
int[] e;
e = t.getOID();
if (e.length < 2)
throw new ASN1Exception("OID must have at least 2 elements!");
write(e[0] * 40 + e[1]);
for (i = 2; i < e.length; i++)
writeBase128(e[i]);
}
public void writeReal(ASN1Type t) {
throw new UnsupportedOperationException("Real is not yet supported!");
}
public void writeString(ASN1String t) throws ASN1Exception, IOException {
if (t.isOptional())
return;
writeHeader(t, true);
write(t.convert(t.getString()));
}
public void writeCollection(ASN1Collection t) throws ASN1Exception,
IOException {
if (t.isOptional())
return;
Iterator i;
Collection c;
// Collection h;
ArrayList h;
writeHeader(t, false);
c = t.getCollection();
if (isStrict() && t instanceof ASN1SetOf) {
// von VR war writeStrictSetOf(t);
writeStrictSetOf((ASN1SetOf) t);
return;
}
if (isStrict() && t instanceof ASN1Set) {
h = new ArrayList(c.size());
h.addAll(c);
Collections.sort(h, new ASN1TagComparator());
c = h;
}
try {
for (i = c.iterator(); i.hasNext();)
writeType((ASN1Type) i.next());
} catch (ClassCastException e) {
throw new ASN1Exception("Non-ASN.1 type in collection!");
}
}
/**
* This method fixes the DER SET OF strict encoding issue brought up by
* pea-counter implementations of decoders that insist on sorting the SET OF
* components by encoding -- something no sane implementation requires.
*
* The method of implementation is basically a hack. Don't take this as a
* good programming pattern. Moreover, this implementation becomes
* completely and utterly THREAD UNSAFE. Not that this would mater too much.
*/
protected void writeStrictSetOf(ASN1SetOf t) throws ASN1Exception,
IOException {
ByteArrayOutputStream bos;
OutputStream old;
Collection c;
ArrayList res;
Iterator i;
byte[] buf;
/*
* Prepare working variables
*/
c = t.getCollection();
res = new ArrayList(c.size());
bos = new ByteArrayOutputStream();
/*
* Safe the original output stream and replace it with our byte array
* output stream.
*/
old = super.out;
super.out = bos;
try {
/*
* Go ahead and encode everything into byte arrays.
*/
for (i = c.iterator(); i.hasNext();) {
writeType((ASN1Type) i.next());
/*
* If something has been encoded then we safe it for later
* sorting.
*/
if (bos.size() > 0) {
res.add(bos.toByteArray());
bos.reset();
}
}
} finally {
/*
* Restore the original output stream.
*/
super.out = old;
}
/*
* Now, we sort the different codes and write them
*/
Collections.sort(res, new DERCodeComparator());
for (i = res.iterator(); i.hasNext();) {
buf = (byte[]) i.next();
write(buf, 0, buf.length);
}
}
public void writeTime(ASN1Time t) throws ASN1Exception, IOException {
writeString(t);
}
public void writeTaggedType(ASN1TaggedType t) throws ASN1Exception,
IOException {
if (t.isOptional())
return;
boolean primitive;
ASN1Type o;
int tag;
o = t.getInnerType();
if (!o.isExplicit()) {
if (t instanceof ASN1Opaque)
tag = t.getTag();
else
tag = o.getTag();
primitive = ((constructed_ & (1 << tag)) == 0);
} else
primitive = false;
writeHeader(t, primitive);
writeType(t.getInnerType());
}
public void writeTypeIdentifier(ASN1Type t) {
throw new UnsupportedOperationException(
"TypeIdentifier is not yet supported!");
}
public void write(byte[] b) throws IOException {
out.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
}
/**
* Writes an arbitrary {@link ASN1Type ASN1Type}. The given type is written
* only if it is not declared OPTIONAL. The type is written by calling its
* {@link ASN1Type#encode encode} method with <code>this</code> as the
* argument. The called emthod then should invoke the appropriate encoder
* method of the primitive type to which the given type corresponds.
*
* @param t
* The type to write.
* @throws ASN1Exception
* if the given type cannot be encoded.
* @throws IOException
* if an I/O error occurs.
*/
public void writeType(ASN1Type t) throws ASN1Exception, IOException {
if (!t.isOptional())
t.encode(this);
}
/**
* This method encodes identifier and length octets. The given length can be
* negative in which case 0x80 is written to indicate INDEFINITE LENGTH
* encoding. Please note that this is appropriate only for a BER encoding or
* CER encoding (ITU-T Recommenation X.690). Encoders are responsible for
* writing the end of code octets <code>0x00 0x00</code> after encoding
* the content octets.
*
* @param tag
* The ASN.1 tag
* @param cls
* The ASN.1 tag class.
* @param prim
* <code>true</code> if the encoding is PRIMITIVE and
* <code>false</code> if it is CONSTRUCTED.
* @param len
* The number of content octets or -1 to indicate INDEFINITE
* LENGTH encoding.
*/
protected void writeHeader(int tag, int cls, boolean prim, int len)
throws IOException {
int b, i;
b = cls & ASN1.CLASS_MASK;
if (!prim)
b = b | ASN1.CONSTRUCTED;
if (tag > 30) {
b = b | ASN1.TAG_MASK;
out.write(b);
writeBase128(tag);
} else {
b = b | tag;
out.write(b);
}
if (len == -1)
out.write(0x80);
else {
if (len > 127) {
i = (significantBits(len) + 7) / 8;
out.write(i | 0x80);
writeBase256(len);
} else
out.write(len);
}
}
/**
* This method computes the number of octets needed to encode the identifier
* and length octets of the {@link ASN1Type ASN.1 type} with the given tag
* and contents length. The given length can be negative in which case
* INDEFINITE LENGTH encoding is assumed.
*
* @return The number of octets required for encoding the identifier and
* length octets.
* @param tag
* The ASN.1 tag.
* @param len
* The number of contents octets of the ASN.1 type with the
* given tag and length.
*/
protected int getHeaderLength(int tag, int len) {
int n;
n = 2;
if (tag > 30)
n = n + (significantBits(tag) + 6) / 7;
if (len > 127)
n = n + (significantBits(len) + 7) / 8;
return n;
}
/**
* Writes the given integer to the output in base 128 representation with
* bit 7 of all octets except the last one being set to &quot;1&quot;. The
* minimum number of octets necessary is used.
*
* @param n
* The integer to be written to the output.
* @throws IOException
* Thrown by the underlying output stream.
*/
protected void writeBase128(int n) throws IOException {
int i, j;
i = (significantBits(n) + 6) / 7;
j = (i - 1) * 7;
while (i > 1) {
out.write(((n >>> j) & 0x7f) | 0x80);
j = j - 7;
i--;
}
out.write(n & 0x7f);
}
/**
* Writes the given integer to the output in base 256 with the minimal
* number of octets.
*
* @param n
* The integer to be written to the output.
* @throws IOException
* Thrown by the underlying output stream.
*/
protected void writeBase256(int n) throws IOException {
int i, j;
i = (significantBits(n) + 7) / 8;
j = (i - 1) * 8;
while (i > 0) {
out.write((n >>> j) & 0xff);
j = j - 8;
i--;
}
}
/**
* Counts the number of significant bits in the given integer. There is
* always at least one significant bit.
*
* @param n
* The integer.
* @return The number of significant bits in the given integer.
*/
protected int significantBits(int n) {
int i;
if (n == 0)
return 1;
i = 0;
while (n > 255) {
n = n >>> 8;
i += 8;
}
while (n > 0) {
n = n >>> 1;
i++;
}
return i;
}
}

126
src/codec/asn1/Decoder.java Normal file
View File

@@ -0,0 +1,126 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* Defines the methods that must be implemented by decoders of ASN.1 types.
*
*
* @author Volker Roth
* @version "$Id: Decoder.java,v 1.2 2000/12/06 17:47:28 vroth Exp $"
*/
public interface Decoder {
public ASN1Type readType() throws ASN1Exception, IOException;
public void readType(ASN1Type t) throws ASN1Exception, IOException;
public void readBoolean(ASN1Boolean t) throws ASN1Exception, IOException;
public void readInteger(ASN1Integer t) throws ASN1Exception, IOException;
public void readBitString(ASN1BitString t) throws ASN1Exception,
IOException;
public void readOctetString(ASN1OctetString t) throws ASN1Exception,
IOException;
public void readNull(ASN1Null t) throws ASN1Exception, IOException;
public void readObjectIdentifier(ASN1ObjectIdentifier t)
throws ASN1Exception, IOException;
public void readReal(ASN1Type t) throws ASN1Exception, IOException;
public void readString(ASN1String t) throws ASN1Exception, IOException;
public void readCollection(ASN1Collection t) throws ASN1Exception,
IOException;
public void readCollectionOf(ASN1CollectionOf t) throws ASN1Exception,
IOException;
public void readTime(ASN1Time t) throws ASN1Exception, IOException;
public void readTaggedType(ASN1TaggedType t) throws ASN1Exception,
IOException;
public void readChoice(ASN1Choice t) throws ASN1Exception, IOException;
}

View File

@@ -0,0 +1,154 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* This interface is used by the {@link ASN1OpenType ASN1OpenType} in order to
* resolve the ASN.1 type to decode at runtime. Concrete implementations of this
* interface can be used to model references to type classes as well or to
* compensate for the superseded ASN.1 ANY DEFINED BY type.
* <p>
*
* Implementations shall determine and return the correct ASN.1 type to be
* decoded in the defined method.
*
* @author Volker Roth
* @version "$Id: DefinedByResolver.java,v 1.2 2000/12/06 17:47:28 vroth Exp $"
*/
public class DefinedByResolver extends Object implements Resolver {
private OIDRegistry registry_;
private ASN1ObjectIdentifier oid_;
/**
* Creates an instance that attempts to resolve the given OID against the
* given registry upon calling {@link #resolve resolve}. The OID instance
* used or resolving is the one passed to this constructor. Hence, an OID
* can be added to a compound ASN.1 type and an {@link ASN1OpenType
* ASN1OpenType} can be initialized with this. If the OID is decoded before
* the open type then the open type is resolved against the given registry
* and the decoded OID. In other words the ASN.1 ANY DEFINED BY type can be
* modelled with an ASN1OpenType and an instance of this resolver class.
*
* @param registry
* The registry to resolve the given OID against.
* @param oid
* The oid instance to use when resolving.
*/
public DefinedByResolver(OIDRegistry registry, ASN1ObjectIdentifier oid) {
if (registry == null || oid == null)
throw new NullPointerException("Registry or OID is null!");
registry_ = registry;
oid_ = oid;
}
/**
* Creates an instance that resolves the given OID against the
* {@link OIDRegistry#getGlobalOIDRegistry global OID registry}.
*
* @param oid
* The OID to resolve.
*/
public DefinedByResolver(ASN1ObjectIdentifier oid) {
if (oid == null)
throw new NullPointerException("OID is null!");
registry_ = OIDRegistry.getGlobalOIDRegistry();
oid_ = oid;
}
/**
* Looks up the private OID in the private registry and returns the resolved
* ASN.1 type. If the OID cannot be resolved against the registry then an
* exception is thrown.
*
* @param caller
* The calling ASN.1 type.
* @throws ResolverException
* if the private OID cannot be mapped onto an ASN.1 type by
* the private registry.
*/
public ASN1Type resolve(ASN1Type caller) throws ResolverException {
ASN1Type t;
t = registry_.getASN1Type(oid_);
if (t == null) {
throw new ResolverException("Cannot resolve " + oid_);
}
return t;
}
}

122
src/codec/asn1/Encoder.java Normal file
View File

@@ -0,0 +1,122 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
/**
* Defines the methods that must be implemented by encoders of ASN.1 types.
*
*
* @author Volker Roth
* @version "$Id: Encoder.java,v 1.2 2000/12/06 17:47:29 vroth Exp $"
*/
public interface Encoder {
public void writeType(ASN1Type t) throws ASN1Exception, IOException;
public void writeBoolean(ASN1Boolean t) throws ASN1Exception, IOException;
public void writeInteger(ASN1Integer t) throws ASN1Exception, IOException;
public void writeBitString(ASN1BitString t) throws ASN1Exception,
IOException;
public void writeOctetString(ASN1OctetString t) throws ASN1Exception,
IOException;
public void writeNull(ASN1Null t) throws ASN1Exception, IOException;
public void writeObjectIdentifier(ASN1ObjectIdentifier t)
throws ASN1Exception, IOException;
public void writeReal(ASN1Type t) throws ASN1Exception, IOException;
public void writeString(ASN1String t) throws ASN1Exception, IOException;
public void writeCollection(ASN1Collection t) throws ASN1Exception,
IOException;
public void writeTime(ASN1Time t) throws ASN1Exception, IOException;
public void writeTaggedType(ASN1TaggedType t) throws ASN1Exception,
IOException;
public void writeTypeIdentifier(ASN1Type t) throws ASN1Exception,
IOException;
}

View File

@@ -0,0 +1,319 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.security.AccessController;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* This class maps ASN.1 object identifiers onto ASN.1 types suitable for
* decoding the structure defined by the given OID. It is modelled along the
* lines of the ClassLoader and provides a hierarchy and top-level OID
* registries.
*
* @author Volker Roth
* @version "$Id: OIDRegistry.java,v 1.4 2004/08/09 08:32:22 flautens Exp $"
*/
public class OIDRegistry extends Object {
/**
* The list of global OID registries.
*/
private static Set registries_ = Collections.synchronizedSet(new HashSet());
/**
* The global instance of OID registries.
*/
private static OIDRegistry global_ = new OIDRegistry();
/**
* The parent OID registry.
*/
private OIDRegistry parent_ = null;
/**
* Creates an OID registry.
*/
private OIDRegistry() {
}
/**
* This method returns the global OIDRegistry instance that may be used for
* querying
*
* @return The global OID registry.
*/
final static public OIDRegistry getGlobalOIDRegistry() {
return global_;
}
/**
* Adds a registry to the set of globally known ones unless it is already in
* the global set. This method checks the permission
* <p>
*
* {@link ASN1Permission ASN1Permission}, &quot; OIDRegistry.add&quot;
* <p>
*
* The reference to the parent registry of the given registry is cleared
* before it is added.
*
* @param r
* The registry to add.
* @throws SecurityException
* iff the caller has no right to add registries to the
* global ones.
*/
final public static void addOIDRegistry(OIDRegistry r) {
if (r == null) {
return;
}
AccessController.checkPermission(new ASN1Permission("OIDRegistry.add"));
r.parent_ = null;
registries_.add(r);
}
/**
* Removes the given OID registry from the set of globally known ones. This
* method checks the permission
* <p>
*
* {@link ASN1Permission ASN1Permission}, &quot; OIDRegistry.remove&quot;
*
* @param r
* The registry to remove.
* @throws SecurityException
* iff the caller has no right to remove OID registries.
*/
final public static void removeOIDRegistry(OIDRegistry r) {
if (r == null) {
return;
}
AccessController.checkPermission(new ASN1Permission(
"OIDRegistry.remove"));
registries_.remove(r);
}
/**
* Creates an OID registry with the given parent. If an OID is not found by
* this registry then the search is delegated to the parent registry.
*
* @param parent
* The parent OID registry.
*/
public OIDRegistry(OIDRegistry parent) {
parent_ = parent;
}
/**
* Retrieves an ASN.1 type based on the given OID. If no type is found then
* <code>null</code> is returned. This method first calls {@link
* #getLocalASN1Type(ASN1ObjectIdentifier) getLocalASN1Type}. If no ASN.1
* type is found for the given OID then <code>getASN1Type</code> is called
* for the parent OIDRegistry.
*
* @param oid
* The registered OID of the desired type.
* @return The type or <code>null</code> if no type with the given OID is
* known.
*/
final public ASN1Type getASN1Type(ASN1ObjectIdentifier oid) {
ASN1Type o;
o = getLocalASN1Type(oid);
if (o == null && parent_ != null) {
return parent_.getASN1Type(oid);
}
return o;
}
/**
* Retrieves an ASN.1 type for the given OID or <code>null</code> if no
* such type was found.
* <p>
*
* This method should be overridden by subclasses. Subclasses should
* retrieve a pointer to their private synchronized Map with OID to String
* (or Class) mappings, and call the method with the same name but which
* takes an additional Map.
* <p>
*
* This implementation searches the global registries for a matching entry.
*/
protected ASN1Type getLocalASN1Type(ASN1ObjectIdentifier oid) {
Iterator i;
ASN1Type o;
OIDRegistry r;
for (i = registries_.iterator(); i.hasNext();) {
r = (OIDRegistry) i.next();
o = r.getASN1Type(oid);
if (o != null) {
return o;
}
}
return null;
}
/**
* Retrieves an ASN.1 type for the given OID or <code>null</code> if no
* such type was found. Strings in the given <code>Map</code> are replaced
* by the resolved classes.
* <p>
*
* This is a convenience method that can be called by subclasses with a Map
* that is specific to the subclass.
*
* @param oid
* The OID that is resolved.
* @param map
* The <code>Map</code> that holds the OID to class (name)
* mapping. The <code>Map</code> values consist either of
* strings (class names) or of the resolved class objects.
*/
protected ASN1Type getLocalASN1Type(ASN1ObjectIdentifier oid, Map map) {
Object o;
Class c;
if (oid == null || map == null) {
throw new NullPointerException("oid or map");
}
o = map.get(oid);
if (o == null) {
return null;
}
try {
if (o instanceof String) {
c = Class.forName((String) o);
map.put(new ASN1ObjectIdentifier(oid.getOID()), c);
o = c;
}
c = (Class) o;
return (ASN1Type) c.newInstance();
} catch (Exception e) {
e.printStackTrace(System.err);
return null;
}
}
/**
* This method returns the default OID registry. Subclasses should override
* this method and provide a static instance of an OID registry that
* delegates to the global OID registry if a requested OID could not be
* found locally. This implementation returns the global OID registry by
* default.
*
* @return The default OID registry.
*/
static public OIDRegistry getDefaultRegistry() {
return OIDRegistry.getGlobalOIDRegistry();
}
/**
* An OIDRegistry equals another iff both are of the same class.
*
* @return <code>true</code> if both registries are of the same class.
*/
public boolean equals(Object o) {
if (getClass() == o.getClass()) {
return true;
}
return false;
}
/**
* The hash code of an instance is the hash code of its class. This is
* required to be consistent with the {@link #equals equals()} method.
*/
public int hashCode() {
return getClass().hashCode();
}
}

View File

@@ -0,0 +1,94 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* This interface is used by the {@link ASN1OpenType ASN1OpenType} in order to
* resolve the ASN.1 type to decode at runtime. Concrete implementations of this
* interface can be used to model references to type classes as well or to
* compensate for the superseded ASN.1 ANY DEFINED BY type.
* <p>
*
* Implementations shall determine and return the correct ASN.1 type to be
* decoded in the defined method.
*
* @author Volker Roth
* @version "$Id: Resolver.java,v 1.2 2000/12/06 17:47:29 vroth Exp $"
*/
public interface Resolver {
public ASN1Type resolve(ASN1Type caller) throws ResolverException;
}

View File

@@ -0,0 +1,93 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
/**
* Thrown by {@link OpenTypeResolver resolvers} if a problem is detected.
*
* @author Volker Roth
* @version "$Id: ResolverException.java,v 1.2 2000/12/06 17:47:29 vroth Exp $"
*/
public class ResolverException extends ASN1Exception {
public ResolverException() {
}
public ResolverException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,419 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.asn1;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
/**
* This encoder makes one pass through the given ASN.1 type and computes the
* length of the type encoding according to the DER (ITU-T Recommendation
* X.690). The result is an array of integers with the length of the individual
* non-optional and non-implicit type encodings in the reverse order of the
* order in which the given type is traversed during actual encoding. This array
* is used by the {@link DEREncoder DEREncoder} when encoding a type.
*
* @author Volker Roth
* @version "$Id: RunLengthEncoder.java,v 1.2 2000/12/06 17:47:29 vroth Exp $"
*/
public class RunLengthEncoder extends Object implements Encoder {
/**
* The number of slots by which the internal buffer is incremented if its
* capacity is eexceeded.
*/
public static final int INCREMENT = 256;
private int[] stack_;
private int tops_;
private int[] acc_;
private int topa_;
/**
* Creates an encoder.
*/
public RunLengthEncoder() {
}
/**
* This method brings in the harvest of the encoding procedure. It returns
* the individual lengths of the DER encodings of the types written to to
* this encoder. The order of length fields is the reverse order of the pre
* order parsing of the written types.
* <p>
*
* If this method is called before a type has been encoded then an array of
* zero length is returned. Only non-optional types are counted thus the
* zero length array might be returned also when all encoded types were
* declared optional.
*
* @return The lengths fields.
*/
public int[] getLengthFields() {
if (tops_ == 0)
return new int[0];
int[] res;
res = new int[tops_];
System.arraycopy(stack_, 0, res, 0, tops_);
return res;
}
/**
* Encodes the length array of the given type.
*/
public void writeType(ASN1Type o) throws ASN1Exception {
try {
o.encode(this);
} catch (IOException e) {
throw new ASN1Exception("Caught IOException without I/O!");
}
}
/**
* This method computes the number of octets needed to encode the identifier
* and length octets of the {@link ASN1Type ASN.1 type} with the given tag
* and contents length. The length must not be negative else an exception is
* thrown. Since this encoder is meant to work in conjunction with a
* {@link DEREncoder DEREncoder} no indefinite length is supported.
*
* @return The number of octets required for encoding the identifier and
* length octets.
* @param tag
* The ASN.1 tag.
* @param len
* The number of contents octets of the ASN.1 type with the
* given tag and length.
* @throws ASN1Exception
* if the given length is negative.
*/
public int getHeaderLength(int tag, int len) throws ASN1Exception {
int n;
if (len < 0)
throw new ASN1Exception("Length is negative!");
n = 2;
if (tag > 30)
n = n + (significantBits(tag) + 6) / 7;
if (len > 127)
n = n + (significantBits(len) + 7) / 8;
return n;
}
/**
* Counts the number of significant bits in the given integer. There is
* always at least one significant bit.
*
* @param n
* The integer.
* @return The number of significant bits in the given integer.
*/
protected int significantBits(int n) {
int i;
if (n == 0)
return 1;
i = 0;
while (n > 255) {
n = n >>> 8;
i += 8;
}
while (n > 0) {
n = n >>> 1;
i++;
}
return i;
}
public void writeBoolean(ASN1Boolean t) throws ASN1Exception {
if (t.isOptional())
return;
push(t, 1);
}
public void writeInteger(ASN1Integer t) throws ASN1Exception {
if (t.isOptional())
return;
int n;
n = t.getBigInteger().bitLength() / 8 + 1;
push(t, n);
}
public void writeBitString(ASN1BitString t) throws ASN1Exception {
if (t.isOptional())
return;
int n;
if (t.isZero())
n = 1;
else
n = (t.bitCount() + 7) / 8 + 1;
push(t, n);
}
public void writeOctetString(ASN1OctetString t) throws ASN1Exception {
if (t.isOptional())
return;
push(t, t.byteCount());
}
public void writeNull(ASN1Null t) throws ASN1Exception {
if (t.isOptional())
return;
push(t, 0);
}
public void writeObjectIdentifier(ASN1ObjectIdentifier t)
throws ASN1Exception {
if (t.isOptional())
return;
int n;
int i;
int[] e;
e = t.getOID();
if (e.length < 2)
throw new ASN1Exception("OID must have at least 2 elements!");
for (n = 1, i = 2; i < e.length; i++)
n = n + (significantBits(e[i]) + 6) / 7;
push(t, n);
}
public void writeReal(ASN1Type t) {
throw new UnsupportedOperationException("Real is not yet supported!");
}
public void writeString(ASN1String t) throws ASN1Exception {
if (t.isOptional())
return;
push(t, t.convertedLength(t.getString()));
}
public void writeCollection(ASN1Collection t) throws ASN1Exception {
if (t.isOptional())
return;
int n;
int p;
int i;
ArrayList l;
Collection c;
c = t.getCollection();
if (c instanceof ArrayList)
l = (ArrayList) c;
else {
l = new ArrayList(c.size());
l.addAll(c);
}
try {
for (p = sp(), i = l.size() - 1; i >= 0; i--)
writeType((ASN1Type) l.get(i));
n = accumulate(p);
push(t, n);
} catch (ClassCastException e) {
throw new ASN1Exception("Non-ASN.1 type in collection!");
}
}
public void writeCollectionOf(ASN1Collection t) throws ASN1Exception {
writeCollection(t);
}
public void writeTime(ASN1Time t) throws ASN1Exception {
writeString(t);
}
public void writeTaggedType(ASN1TaggedType t) throws ASN1Exception {
if (t.isOptional())
return;
int n;
int p;
p = sp();
writeType(t.getInnerType());
n = accumulate(p);
push(t, n);
}
public void writeTypeIdentifier(ASN1Type t) {
throw new UnsupportedOperationException(
"TypeIdentifier is not yet supported!");
}
/**
* Clears the length array and prepares this encoder for a new run.
*/
protected void reset() {
tops_ = 0;
topa_ = 0;
}
/**
* Pushes another length integer onto the internal stacks. The value is
* pushed both on the running stack as well as on the accumulator stack. The
* stacks increase dynamically in size in chunks of
* {@link #INCREMENT INCREMENT} integers and never shrink in capacity.
*
* @param t
* The ASN.1 type.
* @param n
* The integer.
*/
protected void push(ASN1Type t, int n) throws ASN1Exception {
if (stack_ == null) {
stack_ = new int[INCREMENT];
tops_ = 0;
}
if (tops_ == stack_.length) {
int[] stack;
stack = new int[stack_.length + INCREMENT];
System.arraycopy(stack_, 0, stack, 0, stack_.length);
stack_ = stack;
}
if (acc_ == null) {
acc_ = new int[INCREMENT];
topa_ = 0;
}
if (topa_ == acc_.length) {
int[] stack;
stack = new int[acc_.length + INCREMENT];
System.arraycopy(acc_, 0, stack, 0, acc_.length);
acc_ = stack;
}
if (t.isExplicit()) {
stack_[tops_++] = n;
acc_[topa_++] = n + getHeaderLength(t.getTag(), n);
} else
acc_[topa_++] = n;
}
/**
* Returns the accumulator stack pointer.
*
* @return The accumulator stack pointer.
*/
protected int sp() {
return topa_;
}
/**
* Accumulates all values on the accumulator stack from the given position
* to the top of the stack and returns the result. All accumulated values
* are popped off the stack.
*
* @param pos
* The position to start from.
* @throws IllegalStateException
* if the given position is atop the top of the stack.
*/
protected int accumulate(int pos) {
int n;
int i;
if (pos > topa_)
throw new IllegalStateException(
"Internal error, bad stack pointer!");
for (n = 0, i = pos; i < topa_; i++)
n = n + acc_[i];
topa_ = pos;
return n;
}
}

View File

@@ -0,0 +1,528 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.pkcs8;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import codec.CorruptedCodeException;
import codec.InconsistentStateException;
import codec.asn1.ASN1Exception;
import codec.asn1.ASN1Integer;
import codec.asn1.ASN1ObjectIdentifier;
import codec.asn1.ASN1OctetString;
import codec.asn1.ASN1Sequence;
import codec.asn1.ASN1Set;
import codec.asn1.ASN1SetOf;
import codec.asn1.ASN1TaggedType;
import codec.asn1.ASN1Type;
import codec.asn1.DERDecoder;
import codec.asn1.DEREncoder;
import codec.x501.Attribute;
import codec.x509.AlgorithmIdentifier;
/**
* This class represents a <code>PrivateKeyInfo</code> as defined in <a
* href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-8.html"> PKCS#8</a>.
* The ASN.1 definition of this structure is
* <p>
* <blockquote>
*
* <pre>
* PrivateKeyInfo ::= SEQUENCE (
* version Version, -- 0 for version 1.2 Nov 93
* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
* privateKey PrivateKey,
* attributes [0] IMPLICIT Attributes OPTIONAL
* }
* Version ::= INTEGER
* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
* PrivateKey ::= OCTET STRING
* Attributes ::= SET OF Attribute
* </pre>
*
* The following definitions are taken from the X501 standard:
*
* <pre>
* Attribute ::= SEQUENCE {
* type AttributeType
* values SET OF AttributeValue
* -- at least one value is required --
* }
* AttributeType ::= OBJECT IDENTIFIER
* AttributeValue ::= ANY
* </pre>
*
* </blockquote>
*
* @author Markus Tak
* @author Volker Roth
* @version "$Id: PrivateKeyInfo.java,v 1.3 2004/08/24 10:01:21 pebinger Exp $"
*/
public class PrivateKeyInfo extends ASN1Sequence {
/**
* The default version.
*/
public static final int VERSION = 0;
/**
* Version 1.2 November 1993 identifier.
*/
public static final int VERSION_1_2 = 0;
/**
* Version is the syntax version number, for compatibility with future
* revisions of the <a
* href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-8.html" PKCS#8
* Standard</a>. It shall be 0 for that version.
*/
protected ASN1Integer version_;
/**
* The {@link ASN1ObjectIdentifier OID} of the private key algorithm used in
* this structure.
*/
protected AlgorithmIdentifier algorithm_;
/**
* Stores the <b>encoded</b> {@link PrivateKey private Key}. The
* interpretation of the contents is defined in the registration of the
* private-key algorithm. For an RSA private key, for example, the contents
* are a DER encoding of a value of type RSAPrivateKey.
*/
transient private ASN1OctetString encodedKey_;
/**
* Attributes are the extended information that is encrypted along with the
* private-key information.
*/
protected ASN1Set attributes_;
/**
* This constructor builds the data structure.
*/
public PrivateKeyInfo() {
version_ = new ASN1Integer(VERSION);
add(version_);
algorithm_ = new AlgorithmIdentifier();
add(algorithm_);
encodedKey_ = new ASN1OctetString();
add(encodedKey_);
attributes_ = new ASN1SetOf(Attribute.class);
add(new ASN1TaggedType(0, attributes_, false, true));
}
/**
* Creates an instance with the given <b>pre encoded raw key</b>. The
* encoded is embedded &quot;as is&quot;, the key encoding can be either a
* DER compliant one or a special encoding.
*
* Please note that the byte array returned by the <code>
* getEncoded()</code>
* method of the <code>Key</code> interface must not be passed to this
* constructor because the bytes returned by this method do not contain a
* raw key but a complete PrivateKeyInfo structure (as this one).
*
* @param aid
* The AlgorithmIdentifier with the OID and parameters for
* the raw algorithm that belongs to the given key.
* @param key
* The raw key that shall be wrapped in this instance.
*/
public PrivateKeyInfo(AlgorithmIdentifier aid, byte[] key) {
version_ = new ASN1Integer(VERSION);
add(version_);
algorithm_ = aid;
add(algorithm_);
encodedKey_ = new ASN1OctetString(key);
add(encodedKey_);
attributes_ = new ASN1Set();
add(new ASN1TaggedType(0, attributes_, false, true));
}
/**
* Creates an instance with the given <b>ASN.1 raw key</b>. The given raw
* key is <b>encoded using DER</b> before it is set up in this instance.
* <p>
*
* @param aid
* The AlgorithmIdentifier with the OID and parameters for
* the raw algorithm that belongs to the given key.
* @param key
* The raw key that shall be wrapped in this instance.
* @throws InconsistentStateException
* if an exception is thrown while encoding the given key.
* No such exception should ever happen.
*/
public PrivateKeyInfo(AlgorithmIdentifier aid, ASN1Type key) {
ByteArrayOutputStream bos;
DEREncoder enc;
byte[] code;
version_ = new ASN1Integer(VERSION);
add(version_);
algorithm_ = aid;
add(algorithm_);
try {
bos = new ByteArrayOutputStream();
enc = new DEREncoder(bos);
key.encode(enc);
code = bos.toByteArray();
enc.close();
} catch (IOException e) {
throw new InconsistentStateException("Caught IOException!");
} catch (ASN1Exception e) {
throw new InconsistentStateException("Caught ASN1Exception!");
}
encodedKey_ = new ASN1OctetString(code);
add(encodedKey_);
attributes_ = new ASN1Set();
add(new ASN1TaggedType(0, attributes_, false, true));
}
/**
* Creates an instance with the given private key.
*
* @param key
* the actual private key as a java object
* @throws NullPointerException
* if the given key is <code>null</code>.
*/
public PrivateKeyInfo(PrivateKey key) throws InvalidKeyException {
super(2);
setPrivateKey(key);
}
/**
* Returns the {@link AlgorithmIdentifier AlgorithmIdentifier} of the
* embedded key.
*
* @return The AlgorithmIdentifier.
*/
public AlgorithmIdentifier getAlgorithmIdentifier() {
return algorithm_;
}
/**
* Returns the private key embedded in this structure.
* <p>
*
* This method creates an PKCS8EncodedKeySpec of this instance and feeds it
* into a key factory. In order to locate a suitable key factory, the
* installed providers must define appropriate OID mappings.
*
* @return The private key.
* @throws InconsistentStateException
* if the key spec generated by this method is rejected by
* the key factory that is used to generate the key.
* @throws NoSuchAlgorithmException
* if there is no key factory registered for the algorithm
* of the embedded key or no appropriate OID mapping is
* defined by the installed providers.
*/
public PrivateKey getPrivateKey() throws NoSuchAlgorithmException {
ByteArrayOutputStream bos;
PKCS8EncodedKeySpec spec;
DEREncoder enc;
KeyFactory kf;
String alg;
try {
bos = new ByteArrayOutputStream();
enc = new DEREncoder(bos);
encode(enc);
spec = new PKCS8EncodedKeySpec(bos.toByteArray());
enc.close();
alg = algorithm_.getAlgorithmOID().toString();
kf = KeyFactory.getInstance(alg);
return kf.generatePrivate(spec);
} catch (ASN1Exception e) {
throw new InconsistentStateException("Internal, encoding error!");
} catch (IOException e) {
throw new InconsistentStateException(
"Internal, I/O exception caught!");
} catch (InvalidKeySpecException e) {
throw new InconsistentStateException(
"Encoded key spec rejected by key factory!");
}
}
/**
* Initializes this instance with the given private key.
*
* @param key
* The private key from which this instance is initialized.
* @throws InvalidKeyException
* if the given key cannot be decoded properly.
* @throws NullPointerException
* if the given key is <code>null</code>.
*/
public void setPrivateKey(PrivateKey key) throws InvalidKeyException {
if (key == null)
throw new NullPointerException("Key is null!");
DERDecoder dec;
clear();
version_ = new ASN1Integer(VERSION);
add(version_);
algorithm_ = new AlgorithmIdentifier();
add(algorithm_);
encodedKey_ = new ASN1OctetString();
add(encodedKey_);
attributes_ = new ASN1SetOf(Attribute.class);
add(new ASN1TaggedType(0, attributes_, false, true));
try {
dec = new DERDecoder(new ByteArrayInputStream(key.getEncoded()));
decode(dec);
dec.close();
} catch (IOException e) {
throw new InvalidKeyException("Caught IOException!");
} catch (ASN1Exception e) {
throw new InvalidKeyException("Bad encoding!");
}
}
/**
* Returns the version number of this instance.
*
* @return The version number.
*/
public int getVersion() {
return version_.getBigInteger().intValue();
}
/**
* Sets the version number of this instance.
*
* @param version
* The version number.
*/
public void setVersion(int version) {
version_ = new ASN1Integer(version);
set(0, version_);
}
/**
* Sets the {@link AlgorithmIdentifier AlgorithmIdentifier} of this
* instance. This algorithm identifier must match the raw key of this
* instance.
* <p>
*
* The given instance is set up in this structure. Side effects will occur
* if it is modified subsequently.
*
* @param aid
* The AlgorithmIdentifier.
*/
public void setAlgorithm(AlgorithmIdentifier aid) {
if (aid == null)
throw new NullPointerException("Algorithm identifier is null!");
set(1, aid);
algorithm_ = aid;
}
/**
* Encodes and sets the given ASN.1 key structure as the raw key.
*
* @throws InconsistentStateException
* if an internal error occurs while the key is encoded.
* This should never happen.
*/
protected void setRawKey(ASN1Type key) {
ByteArrayOutputStream bos;
DEREncoder enc;
try {
bos = new ByteArrayOutputStream();
enc = new DEREncoder(bos);
key.encode(enc);
encodedKey_ = new ASN1OctetString(bos.toByteArray());
enc.close();
set(2, encodedKey_);
} catch (ASN1Exception e) {
throw new InconsistentStateException("Internal, encoding error!");
} catch (IOException e) {
throw new InconsistentStateException(
"Internal, I/O exception caught!");
}
}
/**
* Returns an unmodifiable list view on the attributes.
*
* @return The attributes.
*/
public List getAttributes() {
if (attributes_.isOptional()) {
return null;
}
return Collections.unmodifiableList(attributes_);
}
/**
* Sets the given attributes.
*
* @param attributes
* The attributes.
*/
public void setAttributes(Collection attributes) {
if (attributes == null) {
throw new NullPointerException("Attributes instance is null!");
}
attributes_.clear();
attributes_.addAll(attributes);
attributes_.setOptional(false);
}
/**
* Returns the raw key material. <b>The key material consists of an encoded
* key structure.</b> ASN.1/DER is often used as the encoding. However,
* this need not always be the case. Elliptic curve cryptosystems use
* specific encodings.
* <p>
*
* If the key encoding is ASN.1/DER then the raw key can be retrieved as an
* ASN.1 type by means of the {@link #getDecodedRawKey getDecodedRawKey()}
* method.
* <p>
*
* The returned value is a copy. No side effects are caused by modifying it.
*
* @return The raw key bits as a byte array.
*/
public byte[] getRawKey() {
return (byte[]) encodedKey_.getByteArray().clone();
}
/**
* Returns an ASN.1 type that represents the decoded raw key. Decoding is
* done by means of ASN.1/DER. <b>Be careful, not all public keys are
* encoded according to DER.</b> Elliptic curve cryptosystems use specific
* encodings.
*
* @return The raw key decoded according to DER.
*/
public ASN1Type getDecodedRawKey() throws CorruptedCodeException {
DERDecoder dec;
ASN1Type raw;
try {
dec = new DERDecoder(new ByteArrayInputStream(encodedKey_
.getByteArray()));
raw = dec.readType();
dec.close();
return raw;
} catch (ASN1Exception e) {
throw new CorruptedCodeException("Cannot decode raw key!");
} catch (IOException e) {
throw new InconsistentStateException(
"Internal, I/O exception caught!");
}
}
}

621
src/codec/util/JCA.java Normal file
View File

@@ -0,0 +1,621 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.util;
import java.security.Provider;
import java.security.Security;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* A number of invariants must hold for the properties defined by the installed
* providers such that this class can work properly:
* <ul>
* <li> Aliases must be mapped to standard JCA/JCE names whenever possible. All
* Aliases for an engine must map to the same name.
* <li> Two OID mappings with the same OID must map to the same name.
* <li> The slashed form of signature names must be set up as an alias.
* <li> Signature engines that do not have a corresponding cipher engine still
* require a reverse OID mapping of the form Alg.Alias.Cipher.OID.<i>oid</i> =
* <i>name</i>, where <i>name</i> is the cipher name component of a slashed
* form alias for that signature engine.
* </ul>
*
* @author Volker Roth
* @version "$Id: JCA.java,v 1.5 2004/08/11 14:33:49 flautens Exp $"
*/
public class JCA extends Object {
/**
* The digest/cipher name to signature algorithm name mapping.
*/
private static Map dc2s_ = new HashMap();
/**
* The signature algorithm name to digest/cipher name mapping.
*/
private static Map s2dc_ = new HashMap();
/**
* The root alias map. Each map entry consists of the lower case engine name
* mapped to another map that holds the aliases for that engine.
*/
protected static Map aliases_ = initAliasLookup();
/**
* Let no-one create an instance.
*
*/
private JCA() {
}
/**
* Reads the properties of the installed providers and builds an optimized
* alias lookup table. All entries of the form
* <ol>
* <li> &quot;Alg.Alias.&quot;+&lt;engine&gt;+&quot;.&quot;+&lt;alias&gt; =
* &lt;value&gt;
* <li> &quot;Alg.Alias.&quot;+&lt;engine&gt;+&quot;.OID.&quot;+&lt;oid&gt; =
* &lt;value&gt;
* <li> &quot;Alg.Alias.&quot;+&lt;engine&gt;+&quot;.&quot;+&lt;oid&gt; =
* &lt;value&gt;
* </ol>
* are transformed and stored in a hashmap which is used by this class in
* order to do quick lookups of aliases and OID mappings. The stored entries
* are of the form:
* <ol>
* <li> &lt;engine&gt;+&quot;.&quot;+&lt;alias&gt; = &lt;value&gt;
* <li> &quot;oid.&quot;+&lt;value&gt; = &lt;oid&gt;
* <li> &quot;oid.&quot;+&lt;oid&gt; = &lt;value&gt;
* </ol>
* In case multiple providers define mappings for the same keys the mapping
* of the first registered provider wins.
*/
static private Map initAliasLookup() {
Enumeration e;
Provider[] provider;
String k; // key
String v; // value
String s; // string
String p; // previous mapping
Map map;
int i;
int j;
map = new HashMap();
provider = Security.getProviders();
/*
* We start from the last provider and work our way to the first one
* such that aliases of preferred providers overwrite entries of less
* favoured providers.
*/
for (i = provider.length - 1; i >= 0; i--) {
e = provider[i].propertyNames();
while (e.hasMoreElements()) {
k = (String) e.nextElement();
v = provider[i].getProperty(k);
if (!k.startsWith("Alg.Alias.")) {
continue;
}
/*
* Truncate k to <engine>.<alias>
*/
k = k.substring(10).toLowerCase();
j = k.indexOf('.');
if (j < 1) {
continue;
}
/*
* Copy <engine> to s Truncate k to <alias>
*/
s = k.substring(0, j);
k = k.substring(j + 1);
if (k.length() < 1) {
continue;
}
/*
* If <alias> starts with a digit then we assume it is an OID.
* OIDs are uniquely defined, hence we ommit <engine> in the oid
* mappings. But we also include the alias mapping for this oid.
*/
if (Character.isDigit(k.charAt(0))) {
p = (String) map.get("oid." + k);
if (p != null && p.length() >= v.length()) {
continue;
}
map.put("oid." + k, v);
map.put(s + "." + k, v);
}
/*
* If <alias> starts with the string "OID." then we found a
* reverse mapping. In that case we swap <alias> and the value
* of the mapping, and make an entry of the form "oid."+<value> =
* <oid>
*/
else if (k.startsWith("oid.")) {
k = k.substring(4);
v = v.toLowerCase();
map.put("oid." + v, k);
}
/*
* In all other cases we make an entry of the form <engine>+"."+<alias> =
* <value> as is defined in the providers.
*/
else {
map.put(s + "." + k, v);
}
}
}
// System.out.println("MAP : "+map);
return map;
}
/*
* static private void dump(Map map) { Iterator i; Map.Entry entry;
*
* for (i=map.entrySet().iterator(); i.hasNext();) { entry =
* (Map.Entry)i.next(); System.out.println( entry.getKey()+" =
* "+entry.getValue()); } }
*/
/**
* Returns the JCA standard name for a given OID. The OID must be a string
* of numbers separated by dots, and can be preceded by the prefix
* &quot;OID.&quot;. If the OID is not defined in a mapping of some
* registered provider then <code>null</code> is returned.
* <p>
*
* OID mappings are unambigous; no engine type is required for the mapping
* and no engine type is returned as part of the result. The returned string
* consists only of the name of the algorithm.
*
* @param oid
* The string with the OID that shall be resolved.
* @return The standard JCA engine name for the given OID or
* <code>null</code> if no such OID is defined.
* @throws NullPointerException
* if the oid is <code>null</code>.
*/
public static String getName(String oid) {
if (oid == null) {
throw new NullPointerException("OID is null!");
}
if (oid.startsWith("OID.") || oid.startsWith("oid.")) {
oid = oid.substring(4);
}
return (String) aliases_.get("oid." + oid);
}
/**
* Resolves the given alias to the standard JCA name for the given engine
* type. If no appropriate mapping is defined then <code>null</code> is
* returned. If the given alias is actually an OID string and there is an
* appropriate alias mapping defined for that OID by some provider then the
* corresponding JCA name is returned.
*
* @param engine
* The JCA engine type name.
* @param alias
* The alias to resolve for the given engine type.
* @return The standard JCA name or <code>null</code> if no appropriate
* mapping could be found.
* @throws IllegalArgumentException
* if the alias is an empty string.
* @throws NullPointerException
* if the alias or engine name is <code>null</code>.
*/
public static String resolveAlias(String engine, String alias) {
if (alias == null || engine == null) {
throw new NullPointerException("Engine or alias is null!");
}
if (alias.length() < 1) {
throw new IllegalArgumentException("Zero-length alias!");
}
return (String) aliases_.get(engine.toLowerCase() + "."
+ alias.toLowerCase());
}
/**
* Returns the OID of the given algorithm name. The given name must be the
* JCA standard name of the algorithm and not an alias. Use
* {@link #resolveAlias resolveAlias} to map aliases onto their standard
* names.
*
* @param algorithm
* The JCA standard name of the algorithm for which the OID
* should be returned.
* @return The OID or <code>null</code> if no appropriate mapping could be
* found.
* @throws NullPointerException
* if engine or algorithm is <code>null</code>.
*/
public static String getOID(String algorithm) {
if (algorithm == null) {
throw new NullPointerException("Algorithm is null!");
}
if (algorithm.length() < 1) {
throw new IllegalArgumentException("Algorithm name is empty!");
}
if (Character.isDigit(algorithm.charAt(0))) {
return algorithm;
}
return (String) aliases_.get("oid." + algorithm.toLowerCase());
}
/**
* Returns the OID of the given algorithm name. The given engine name is
* taken as a hint if the given algorithm name is a non-standard name. In
* that case one shot is given to alias resolving before a second attempt is
* made to map the algorithm to an OID. Alias resolving is done by means of
* the {@link #resolveAlias resolveAlias} method.
*
* @param algorithm
* The JCA standard name of the algorithm for which the OID
* should be returned.
* @param engine
* The engine name that is taken as a hint for alias
* resolving if the algorithm name cannot be resolved in the
* first attempt.
* @return The OID or <code>null</code> if no appropriate mapping could be
* found.
* @throws NullPointerException
* if engine or algorithm is <code>null</code>.
*/
public static String getOID(String algorithm, String engine) {
String oid;
oid = getOID(algorithm);
if (oid != null) {
return oid;
}
algorithm = resolveAlias(engine, algorithm);
if (algorithm == null) {
return null;
}
return getOID(algorithm);
}
/**
* This method maps a given digest algorithm OID and cipher algorithm OID
* onto the standard name of the combined signature algorithm. For this to
* work the aliases must be well defined such as described below:
* <dl>
* <dt> Digest Algorithm
* <dd> Alg.Alias.MessageDigest.<i>oid</i><sub>1</sub> = <i>digestAlg</i>
* <dt> Cipher Algorithm
* <dd> Alg.Alias.Cipher.<i>oid</i><sub>2</sub> = <i>cipherAlg</i>
* <dt> Signature Algorithm
* <dd> Alg.Alias.Signature.<i>digestAlg</i>/<i>cipherAlg</i> =
* <i>signatureAlg</i>
* </dl>
* The <i>oid</i> denotes the sequence of OID numbers separated by dots but
* without a leading &quot;OID.&quot;. In some cases, such as the DSA, there
* is no cipher engine corresponding to <i>oid</i><sub>2</sub>. In this
* case, <i>oid</i><sub>2</sub> must be mapped to the corresponding name
* by other engine types, such as a KeyFactory.
* <p>
*
* All found mappings are cached for future use, as well as the reverse
* mapping, which is much more complicated to synthesise.
*
* @param doid
* The string representation of the digest algorithm OID. The
* OID must have a &quot;OID.&quot; prefix.
* @return The standard JCE name of the signature algorithm or
* <code>null</code> if no mapping could be found.
*/
public static String getSignatureName(String doid, String coid) {
String dn;
String cn;
String sn;
String dc;
dn = getName(doid);
cn = getName(coid);
if (dn == null || cn == null) {
return null;
}
dc = dn + "/" + cn;
synchronized (dc2s_) {
sn = (String) dc2s_.get(dc);
if (sn != null) {
return sn;
}
}
sn = resolveAlias("signature", dc);
if (sn != null) {
synchronized (dc2s_) {
cn = dc.toLowerCase();
if (!dc2s_.containsKey(cn)) {
dc2s_.put(cn, sn);
}
}
synchronized (s2dc_) {
cn = sn.toLowerCase();
if (!s2dc_.containsKey(cn)) {
s2dc_.put(cn, dc);
}
}
}
return sn;
}
/**
* This method maps the standard signature algorithm name to the
* <i>digestAlg</i>/<i>cipherAlg</i> format. This format can be used to
* retrieve the OID of the digest algorithm and cipher algorithm
* respectively. For this to work the aliases must be well defined such as
* described below:
* <dl>
* <dt> Signature Algorithm
* <dd> Alg.Alias.Signature.<i>d</i>/<i>c</i> = <i>sigAlg</i> where
* <i>d</i> denotes the digest algorithm and <i>c</i> the cipher
* algorithm. <i>sigAlg</i> must be the name under which the algorithm
* engine is published.
* </dl>
*
* If <code>sigAlg</code> contains a &quot;/&quot; then we assume that the
* given algorithm name is already of the desired form and return
* <code>sigAlg</code>.
*
* @param sigAlg
* The standard signature algorithm name.
* @return The <i>digestAlg</i>/<i>cipherAlg</i> format of the given
* signature algorithm name or <code>
* null</code> if no suitable
* mapping could be found.
*/
public static String getSlashedForm(String sigAlg) {
String v;
if (sigAlg.indexOf("/") > 0) {
return sigAlg;
}
sigAlg = sigAlg.toLowerCase();
synchronized (s2dc_) {
v = (String) s2dc_.get(sigAlg);
if (v != null) {
return v;
}
}
Iterator i;
String k;
int m;
for (i = aliases_.keySet().iterator(); i.hasNext();) {
k = (String) i.next();
if (!k.startsWith("signature.")) {
continue;
}
v = (String) aliases_.get(k);
if (!v.equalsIgnoreCase(sigAlg)) {
continue;
}
k = k.substring(10);
m = k.indexOf("/");
if (m < 0) {
continue;
}
synchronized (s2dc_) {
if (!s2dc_.containsKey(sigAlg)) {
s2dc_.put(sigAlg, k);
}
}
return k;
}
return null;
}
/**
* This method maps the given standard signature algorithm name to the
* string representation of the OID associated with the digest algorithm of
* the given signature algorithm.
*
* @param sigAlg
* The standard signature algorithm name.
* @return The string representation of the OID associated with the digest
* alorithm used for <code>sigAlg</code>.
*/
public static String getDigestOID(String sigAlg) {
int n;
String v;
String h;
String r;
v = getSlashedForm(sigAlg);
if (v == null) {
return null;
}
n = v.indexOf("/");
if (n < 0) {
return null;
}
h = v.substring(0, n);
r = getOID(h);
if (r != null) {
return r;
}
/*
* We now try to "repair" the bad algorithm name if we find a fitting
* alias instead.
*/
h = resolveAlias("MessageDigest", h);
if (h == null) {
return null;
}
r = getOID(h);
if (r != null) {
v = h + "/" + v.substring(n + 1);
synchronized (s2dc_) {
s2dc_.put(sigAlg, v);
}
}
return r;
}
/**
* This method maps the given standard signature algorithm name to the
* string representation of the OID associated with the cipher algorithm of
* the given signature algorithm.
* <p>
* This conversion is a bit tricky. In cases such as DSA, no corresponding
* Cipher engine exists, since DSA is not designed to be used as a cipher.
* In such cases, some provider needs to set up a bogus alias of the form:
* <dl>
* <dt> Signature Algorithm
* <dd> Alg.Alias.Cipher.OID.<i>oid</i> = DSA
* </dl>
*
* The <i>oid</i> denotes the sequence of OID numbers separated by dots but
* without a leading &quot;OID.&quot;.
*
* @param sigAlg
* The standard signature algorithm name.
* @return The string representation of the OID associated with the cipher
* alorithm used for <code>sigAlg</code>.
*/
public static String getCipherOID(String sigAlg) {
int n;
String s;
String v;
String r;
v = getSlashedForm(sigAlg);
if (v == null) {
return null;
}
n = v.indexOf("/");
if (n < 0) {
return null;
}
s = v.substring(n + 1);
r = getOID(s);
if (r != null) {
return r;
}
/*
* We now try to "repair" the bad algorithm name if we find a fitting
* alias instead.
*/
s = resolveAlias("Signature", s);
if (s == null) {
return null;
}
r = getOID(s);
if (r != null) {
v = v.substring(0, n) + "/" + s;
synchronized (s2dc_) {
s2dc_.put(sigAlg, v);
}
}
return r;
}
}

View File

@@ -0,0 +1,312 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.x501;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import codec.asn1.ASN1Exception;
import codec.asn1.ASN1Null;
import codec.asn1.ASN1ObjectIdentifier;
import codec.asn1.ASN1OpenType;
import codec.asn1.ASN1RegisteredType;
import codec.asn1.ASN1Sequence;
import codec.asn1.ASN1Set;
import codec.asn1.ASN1SetOf;
import codec.asn1.ASN1Type;
import codec.asn1.Decoder;
import codec.asn1.DefinedByResolver;
import codec.asn1.OIDRegistry;
/**
* This class represents an <code>Attribute</code> as defined in X.501
* standard. The ASN.1 definition of this structure is
* <p>
*
* <pre>
* Attribute ::= SEQUENCE {
* type AttributeType,
* values SET OF AttributeValue
* }
* AttributeType ::= ObjectIdentifier
* AttributeValue ::= ANY
* </pre>
*
* @author Volker Roth
* @version "$Id: Attribute.java,v 1.4 2007/08/30 08:45:05 pebinger Exp $"
*/
public class Attribute extends ASN1Sequence implements ASN1RegisteredType {
/**
* The Object Identifier specifying the attribute type.
*/
protected ASN1ObjectIdentifier type_;
/**
* The List of Attribute values.
*/
protected ASN1Set values_;
/**
* Creates an instance ready for parsing. Any type of ASN.1 structure will
* be accepted as the values of this attribute. An <code>ASN1OpenType</code>
* is used for this.
*/
public Attribute() {
super(2);
type_ = new ASN1ObjectIdentifier();
values_ = new ASN1SetOf(ASN1OpenType.class);
add(type_);
add(values_);
}
/**
* Creates an instance ready for parsing. The given
* {@link OIDRegistry OIDRegistry} is used to resolve the attribute type. If
* the attribute type cannot be resolved upon decoding then an exception is
* thrown.
*
* @param registry
* The <code>OIDRegistry</code> to use for resolving
* attribute value types, or <code>null
* </code> if the
* global registry shall be used.
*/
public Attribute(OIDRegistry registry) {
super(2);
if (registry == null) {
registry = OIDRegistry.getGlobalOIDRegistry();
}
type_ = new ASN1ObjectIdentifier();
values_ = new ASN1SetOf(new DefinedByResolver(registry, type_));
add(type_);
add(values_);
}
/**
* Creates a new instance that is initialized with the given OID and value.
* <b>Note:</b> the given values are not cloned or copied, they are used
* directly. Hence, the given types must not be modified after hereafter in
* order to avoid side effects.
* <p>
*
* The OID must not be <code>null</code>. The <code>
* value</code> can be
* <code>null</code> and is replaced by {@link ASN1Null ASN1Null} in that
* case.
*
* @param oid
* The OID that identifies the given value.
* @param value
* The ASN.1 type.
*/
public Attribute(ASN1ObjectIdentifier oid, ASN1Type value) {
super(2);
if (oid == null) {
throw new NullPointerException("Need an OID!");
}
if (value == null) {
value = new ASN1Null();
}
type_ = oid;
values_ = new ASN1Set(1);
values_.add(value);
add(oid);
add(values_);
}
/**
* The arguments passed to this constructor are set up directly for parsing.
* They are not cloned! The OID of the Attribute is the OID returned by the
* registered type.
*
* @param value
* The registered ASN.1 type.
*/
public Attribute(ASN1RegisteredType value) {
super(2);
if (value == null) {
throw new NullPointerException("Need a value!");
}
type_ = value.getOID();
if (type_ == null) {
throw new NullPointerException("Value does not provide an OID!");
}
values_ = new ASN1Set(1);
values_.add(value);
add(type_);
add(values_);
}
/**
* This method returns the OID of this Attribute.
*
* @return The OID
*/
public ASN1ObjectIdentifier getOID() {
return type_;
}
/**
* This method returns an unmodifiable view of the list of values of this
* Attribute.
*
* @return The unmodifiable view of the list of attribute values.
*/
public List valueList() {
return Collections.unmodifiableList(values_);
}
/**
* returns the number of values in this attribute.
*
* @return The number of values.
*/
public int valueCount() {
return values_.size();
}
/**
* Returns the value at the given position where position is between 0 and
* <code>valueCount()-1</code>.
*
* @return The value at the given position.
* @throws ArrayIndexOutOfBoundsException
* if the given position is not within the bounds of the
* list of attribute values.
*/
public ASN1Type valueAt(int index) {
return (ASN1Type) values_.get(index);
}
/**
* Decodes this instance. If the internal storage object of attributes is a
* <code>ASN1SetOf</code> then that set is transformed into a
* <code>ASN1Set</code>, and any <code>ASN1OpenType</code> instances
* are stripped away. This makes a number of internal objects available for
* garbage collection.
* <p>
*
* Consequently, after decoding this instance contains a set with the pure
* attribute values.
*
* @param dec
* The decoder to use.
*/
public void decode(Decoder dec) throws IOException, ASN1Exception {
super.decode(dec);
if (!(values_ instanceof ASN1SetOf)) {
return;
}
ArrayList list;
ASN1Type o;
Iterator i;
try {
list = new ArrayList(values_.size());
for (i = values_.iterator(); i.hasNext();) {
o = (ASN1Type) i.next();
if (o instanceof ASN1OpenType) {
o = ((ASN1OpenType) o).getInnerType();
}
list.add(o);
}
values_.clear();
values_.addAll(list);
} catch (ClassCastException e) {
throw new ASN1Exception("Unexpected type in SET OF!");
} catch (NullPointerException e) {
throw new ASN1Exception("NULL in SET OF!");
}
}
}

View File

@@ -0,0 +1,558 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.x509;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import codec.CorruptedCodeException;
import codec.InconsistentStateException;
import codec.asn1.ASN1;
import codec.asn1.ASN1Exception;
import codec.asn1.ASN1Null;
import codec.asn1.ASN1ObjectIdentifier;
import codec.asn1.ASN1Opaque;
import codec.asn1.ASN1Sequence;
import codec.asn1.ASN1Type;
import codec.asn1.DEREncoder;
import codec.pkcs8.PrivateKeyInfo;
import codec.util.JCA;
/**
* This class represents the ASN.1/DER value of the AlgorithmIdentifier defined
* in Annex D to Recommendation X.509. This structure is extensively used for
* instance in the PKCS standards of RSA Inc. The ASN.1 definition of this
* structure is as given below:
* <p>
*
* <pre>
* AlgorithmIdentifier ::= SEQUENCE{
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* }
* </pre>
*
* <p>
* For this class to work properly, providers need to define the following
* algorithm aliases for the {@link java.security.AlgorithmParameters
* AlgorithmParameters} implementations they provide:
* <ol>
* <li> AlgorithmParameters.MyAlg = <i>class</i>
* <li> Alg.Alias.AlgorithmParameters.1.2.3.4 = MyAlg
* <li> Alg.Alias.AlgorithmParameters.OID.1.2.3.4 = MyAlg
* </ol>
* The first property defined the mapping of the JCE compliant standard name of
* the algorithm to the implementing class. The second provider entry allows
* mapping OID to those algorithm names while the third allows mapping those
* names on corresponding OID.
* <p>
*
* The alias definitions are used by this class in order to find an
* AlgorithmParameters implementation for the OID embedded in the X.509
* AlgorithmIdentifier structure, and to create the OID for a given
* AlgorithmParameters instances. This is done by means of the {@link JCA JCA}
* class, which operates on the engine and alias definitions of the installed
* providers.
* <p>
*
*
*
*
* @author Volker Roth
* @version "$Id: AlgorithmIdentifier.java,v 1.3 2004/08/13 11:37:03 pebinger
* Exp $"
* @see JCA
*/
public class AlgorithmIdentifier extends ASN1Sequence {
/**
* The algorithm parameters of the algorithm specified by this algorithm
* identifier.
*/
protected ASN1Opaque parameters_;
/**
* The OID of the algorithm.
*/
protected ASN1ObjectIdentifier algorithm_;
/**
* Creates an {@link AlgorithmIdentifier AlgorithmIdentifier} from the given
* key. The key must be either a public key or a private key. No secret
* (symmetric) keys are accepted.
* <p>
*
* The keys encoding must be either a a {@link PrivateKeyInfo
* PrivateKeyInfo} or a {@link SubjectPublicKeyInfo SubjectPublicKeyInfo}.
*
* @param key
* The key from which the AlgorithmIdentifier shall be
* extracted.
* @throws IllegalArgumentException
* if the given key is neither a PublicKey or a PrivateKey.
* @throws CorruptedCodeException
* if an exception was caught while decoding the key's
* encoding.
*/
public static AlgorithmIdentifier createAlgorithmIdentifier(Key key)
throws CorruptedCodeException {
try {
if (key instanceof PublicKey) {
return new SubjectPublicKeyInfo((PublicKey) key)
.getAlgorithmIdentifier();
}
if (key instanceof PrivateKey) {
return new PrivateKeyInfo((PrivateKey) key)
.getAlgorithmIdentifier();
}
throw new IllegalArgumentException("Key type not supported!");
} catch (InvalidKeyException e) {
throw new CorruptedCodeException("Error decoding key!");
}
}
/**
* This method builds the tree of ASN.1 objects used for decoding this
* structure.
*/
public AlgorithmIdentifier() {
super(2);
algorithm_ = new ASN1ObjectIdentifier();
parameters_ = new ASN1Opaque();
parameters_.setOptional(true);
add(algorithm_);
add(parameters_);
}
/**
* Creates an instance initialized to the given algorithm. The algorithm
* must not have parameters since this constructor does not take a parameter
* argument.
*
* @param algorithm
* The JCE standard algorithm name.
* @throws NoSuchAlgorithmException
* if the name cannot be resolved to an OID or the OID has a
* bad syntax.
* @throws NullPointerException
* if <code>algorithm</code> is <code>null</code>.
*/
public AlgorithmIdentifier(String algorithm)
throws NoSuchAlgorithmException {
super(2);
if (algorithm == null)
throw new NullPointerException("Need an algorithm name!");
String oid;
oid = JCA.getOID(algorithm);
if (oid == null)
throw new NoSuchAlgorithmException("No OID alias for algorithm "
+ algorithm);
try {
algorithm_ = new ASN1ObjectIdentifier(oid);
} catch (IllegalArgumentException e) {
throw new NoSuchAlgorithmException("Bad OID alias for algorithm "
+ algorithm);
}
parameters_ = new ASN1Opaque(ASN1.TAG_NULL, ASN1.CLASS_UNIVERSAL,
new byte[0]);
add(algorithm_);
add(parameters_);
}
/**
* Creates an instance with the given OID and opaque algorithm parameter
* representation. Both the given OID and the parameter encoding is cloned
* or copied. No side effects occur if these arguments are modified after
* completition of this constructor.
*
* @param oid
* The algorithm object identifier.
* @param b
* The opaque DER encoding of the parameters for the
* algorithm known under the given OID. If no parameters are
* required then <code>null</code> might be passed. In that
* case {@link ASN1Null ASN.1 NULL} is encoded.
* @throws ASN1Exception
* if the opaque representation does not contain a valid DER
* header and contents octets.
*/
public AlgorithmIdentifier(ASN1ObjectIdentifier oid, byte[] b)
throws ASN1Exception {
super(2);
if (oid == null)
throw new NullPointerException("Need an OID!");
algorithm_ = (ASN1ObjectIdentifier) oid.clone();
if (b == null) {
/*
* Usually, we'd define the following type as OPTIONAl. However, in
* case no parameters are given a NULL is set instead.
*/
parameters_ = new ASN1Opaque(ASN1.TAG_NULL, ASN1.CLASS_UNIVERSAL,
new byte[0]);
} else
parameters_ = new ASN1Opaque(b);
add(algorithm_);
add(parameters_);
}
/**
* Creates an instance that is initialized from the given
* AlgorithmParameters instance. This method attempts to map the algorithm
* name to an ASN.1 OID by calling {@link JCA#getOID(String) JCA#getOID}.
* <p>
*
* @param alg
* The name of the algorithm.
* @param params
* The AlgorithmParameters.
* @throws NullPointerException
* if <code>alg</code> is <code>null</code>.
* @throws InvalidAlgorithmParameterException
* if the given parameters have a bad encoding, or the OID
* of the algorithm cannot be determined.
*/
public AlgorithmIdentifier(String alg, AlgorithmParameters params)
throws InvalidAlgorithmParameterException {
super(2);
String s;
if (alg == null)
throw new NullPointerException("Algorithm is null!");
s = JCA.getOID(alg);
if (s == null) {
s = "1.3.14.3.2.7"; // DES_CBC
}
try {
algorithm_ = new ASN1ObjectIdentifier(s);
} catch (IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(
"Bad OID alias for algorithm " + params.getAlgorithm());
}
try {
if (params == null) {
parameters_ = new ASN1Opaque(ASN1.TAG_NULL,
ASN1.CLASS_UNIVERSAL, new byte[0]);
} else {
parameters_ = new ASN1Opaque(params.getEncoded());
}
} catch (IOException e) {
throw new InvalidAlgorithmParameterException(
"Error during parameter encoding!");
} catch (ASN1Exception e) {
throw new InvalidAlgorithmParameterException(
"Parameter encoding is not ASN.1/DER!");
}
add(algorithm_);
add(parameters_);
}
/**
* Creates an instance with the given OID and parameters. The parameters are
* encoded according to DER and stored by means of an opaque type. If the
* given parameters are <code>null</code> then an ASN.1 NULL is encoded.
*
* @param oid
* The OID to use.
* @param params
* The ASN.1 type of which the parameters consist.
* @throws InconsistentStateException
* if an internal error occurs; this should never happen.
* @throws ASN1Exception
* if the given parameters cannot be encoded. This should
* rarely happen.
*/
public AlgorithmIdentifier(ASN1ObjectIdentifier oid, ASN1Type params)
throws ASN1Exception {
super(2);
DEREncoder enc;
ByteArrayOutputStream bos;
if (oid == null)
throw new NullPointerException("Need an OID!");
algorithm_ = (ASN1ObjectIdentifier) oid.clone();
try {
if (params == null || (params instanceof ASN1Null))
parameters_ = new ASN1Opaque(ASN1.TAG_NULL,
ASN1.CLASS_UNIVERSAL, new byte[0]);
else {
bos = new ByteArrayOutputStream();
enc = new DEREncoder(bos);
params.encode(enc);
parameters_ = new ASN1Opaque(bos.toByteArray());
bos.close();
}
add(algorithm_);
add(parameters_);
} catch (IOException e) {
throw new InconsistentStateException(
"Internal, caught IOException!");
}
}
/**
* This method locates a suitable {@link java.security.AlgorithmParameters
* AlgorithmParameters} implementation if it is available from the JCE
* compliant security providers that are installed locally.
* <p>
*
* Such providers need to specify the following aliases for this to work:
* <ul>
* <li> AlgorithmParameters.MyAlg = <i>class</i>
* <li> Alg.Alias.AlgorithmParameters.1.2.3.4 = MyAlg
* </ul>
* If you ever want to test a provider for compliance with the JCE and
* <i>cleverness</i>, test it against the FhG-IGD PKCS package. If it
* doesn't work then better demand fixes from the provider's vendor.
* <p>
*
* This method may be called only if this instance is initialized properly
* either by specifying AlgorithmParameters in a constructor or by parsing a
* valid ASN.1/DER encoding.
*
* @throws NoSuchAlgorithmException
* if no matching AlgorithmParameters engine is found.
* @throws InvalidAlgorithmParameterException
* if the parameters cannot be decoded properly.
* @return The AlgorithmParameters or <code>null</code> if none are
* enclosed in this structure.
*/
public AlgorithmParameters getParameters() throws NoSuchAlgorithmException,
InvalidAlgorithmParameterException {
AlgorithmParameters params;
String s;
if (parameters_.isOptional())
return null;
if (parameters_.getTag() == ASN1.TAG_NULL
&& parameters_.getTagClass() == ASN1.CLASS_UNIVERSAL)
return null;
/*
* Since alias resolution is Provider-local and hardly any Provider does
* it right and complete, we have to resolve aliases on our own.
*/
s = JCA.getName(algorithm_.toString());
if (s == null)
throw new NoSuchAlgorithmException("Cannot resolve "
+ algorithm_.toString());
/*
* If we resolve cipher names then we have to remove the trailing
* padding string, if present.
*/
int n;
n = s.indexOf("/");
if (n > 0)
s = s.substring(0, n);
params = AlgorithmParameters.getInstance(s);
try {
params.init(parameters_.getEncoded());
} catch (IOException e) {
throw new InvalidAlgorithmParameterException(
"Caught IOException(\"" + e.getMessage() + "\")");
} catch (ASN1Exception e) {
throw new InvalidAlgorithmParameterException(
"Caught ASN1Exception(\"" + e.getMessage() + "\")");
}
return params;
}
/**
* This method returns the OID of the algorithm represented by this
* AlgorithmIdentifier. The OID returned is the one used internally. Do not
* modify the returned OID! Otherwise, side effects occur.
*
* @return The algorithm OID.
*/
public ASN1ObjectIdentifier getAlgorithmOID() {
return algorithm_;
}
/**
* This method returns the JCE standard name of the algorithm specified in
* this AlgorithmIdentifier. However, for this to work a proper alias for
* the algorithm must be defined by some provider. See the general
* documentation of this class for details on that.
* <p>
*
* This method calls {@link JCA#getName(String) JCA.getName()} with the
* string representation of this instance's
* {@link #algorithm_ object identifier}.
* <p>
*
* If you are {@link #getParameters retrieving the parameters} anyway then
* avoid calling this method and call
* {@link java.security.AlgorithmParameters#getAlgorithm getAlgorithm} on
* the parameter instance instead.
*/
public String getAlgorithmName() {
return JCA.getName(algorithm_.toString());
}
/**
* Returns a string representation of this object.
*
* @return The string representation.
*/
public String toString() {
String s;
String t;
t = "X.509 AlgorithmIdentifier " + algorithm_.toString();
s = getAlgorithmName();
if (s != null)
return t + " (" + s + ")";
return t;
}
/**
* This method returns <code>true</code> if the given object is an
* instance of this class or a subclass thereof and the algorithm OID of the
* given object equals this object's algorithm OID.
*
* @return <code>true</code> if the given object equals this one.
*/
public boolean equals(Object o) {
if (!(o instanceof AlgorithmIdentifier))
return false;
return algorithm_.equals(((AlgorithmIdentifier) o).getAlgorithmOID());
}
public int hashCode() {
return algorithm_.hashCode();
}
/**
* Returns a clone. The clone is a deep copy of this instance except from
* the constraints. Constraints are copied by reference.
*
* @return The clone.
*/
public Object clone() {
AlgorithmIdentifier aid;
aid = (AlgorithmIdentifier) super.clone();
aid.clear();
aid.algorithm_ = (ASN1ObjectIdentifier) algorithm_.clone();
aid.parameters_ = (ASN1Opaque) parameters_.clone();
aid.add(algorithm_);
aid.add(parameters_);
return aid;
}
}

View File

@@ -0,0 +1,418 @@
/* ========================================================================
*
* This file is part of CODEC, which is a Java package for encoding
* and decoding ASN.1 data structures.
*
* Author: Fraunhofer Institute for Computer Graphics Research IGD
* Department A8: Security Technology
* Fraunhoferstr. 5, 64283 Darmstadt, Germany
*
* Rights: Copyright (c) 2004 by Fraunhofer-Gesellschaft
* zur Foerderung der angewandten Forschung e.V.
* Hansastr. 27c, 80686 Munich, Germany.
*
* ------------------------------------------------------------------------
*
* The software package is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software package; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA or obtain a copy of the license at
* http://www.fsf.org/licensing/licenses/lgpl.txt.
*
* ------------------------------------------------------------------------
*
* The CODEC library can solely be used and distributed according to
* the terms and conditions of the GNU Lesser General Public License for
* non-commercial research purposes and shall not be embedded in any
* products or services of any user or of any third party and shall not
* be linked with any products or services of any user or of any third
* party that will be commercially exploited.
*
* The CODEC library has not been tested for the use or application
* for a determined purpose. It is a developing version that can
* possibly contain errors. Therefore, Fraunhofer-Gesellschaft zur
* Foerderung der angewandten Forschung e.V. does not warrant that the
* operation of the CODEC library will be uninterrupted or error-free.
* Neither does Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V. warrant that the CODEC library will operate and
* interact in an uninterrupted or error-free way together with the
* computer program libraries of third parties which the CODEC library
* accesses and which are distributed together with the CODEC library.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not warrant that the operation of the third parties's computer
* program libraries themselves which the CODEC library accesses will
* be uninterrupted or error-free.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* shall not be liable for any errors or direct, indirect, special,
* incidental or consequential damages, including lost profits resulting
* from the combination of the CODEC library with software of any user
* or of any third party or resulting from the implementation of the
* CODEC library in any products, systems or services of any user or
* of any third party.
*
* Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
* does not provide any warranty nor any liability that utilization of
* the CODEC library will not interfere with third party intellectual
* property rights or with any other protected third party rights or will
* cause damage to third parties. Fraunhofer Gesellschaft zur Foerderung
* der angewandten Forschung e.V. is currently not aware of any such
* rights.
*
* The CODEC library is supplied without any accompanying services.
*
* ========================================================================
*/
package codec.x509;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import codec.CorruptedCodeException;
import codec.InconsistentStateException;
import codec.asn1.ASN1BitString;
import codec.asn1.ASN1Exception;
import codec.asn1.ASN1Sequence;
import codec.asn1.ASN1Type;
import codec.asn1.DERDecoder;
import codec.asn1.DEREncoder;
/**
* Subject Public Key Info according to RFC2459. Consists of an AlgorithmID and
* the corresponding public key <blockquote>
*
* <pre>
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING
* }
* </pre>
*
* <blockquote>
*
* Raw public key material embedded in this structure need not be ASN.1/DER
* encoded. Some crypto systems such as elliptic curve systems use specific
* encodings of keys. For this reason, keys can be retrieved by means of two
* alternative ways:
* <ul>
* <li> Raw encoded keys, returned as byte arrays, and
* <li> Raw decoded keys, returned as ASN.1 types.
* </ul>
* Only ASN.1/DER is supported as decoding method. Keys encoded in another code
* must be decoded externally.
*
* Creation date: (18.08.99 15:23:09)
*
* @author Markus Tak
* @version "$Id: SubjectPublicKeyInfo.java,v 1.3 2004/08/16 08:53:58 pebinger
* Exp $"
*/
public class SubjectPublicKeyInfo extends ASN1Sequence {
private AlgorithmIdentifier algorithm_;
private ASN1BitString encodedKey_;
/**
* Creates an instance that is ready for decoding.
*/
public SubjectPublicKeyInfo() {
super(2);
algorithm_ = new AlgorithmIdentifier();
add(algorithm_);
encodedKey_ = new ASN1BitString();
add(encodedKey_);
}
/**
* Creates an instance with the given {@link AlgorithmIdentifier
* AlgorithmIdentifier} and encoded public key. The public key is wrapped
* into an {@link ASN1BitString ASN1BitString} as required by the
* specification of this structure. Hence, the encoded key is taken &quot;as
* is&quot;.
* <p>
*
* The given arguments are put into this instance literally. The arguments
* are not copied or cloned. Therefor side effects can occur when the given
* arguments are modified after this constructor was called.
*
* @param aid
* AlgorithmIdentifier of the public key algorithm
* @param key
* The encoded key material.
* @throws NullPointerException
* if either argument is <code>null</code>.
*/
public SubjectPublicKeyInfo(AlgorithmIdentifier aid, byte[] key) {
super(2);
if (aid == null || key == null)
throw new NullPointerException("Some arg is null!");
algorithm_ = aid;
add(algorithm_);
encodedKey_ = new ASN1BitString(key, 0);
add(encodedKey_);
}
/**
* Creates an instance with the given {@link AlgorithmIdentifier
* AlgorithmIdentifier} and key. <b>The given key must be a raw key
* structure represented by means of an ASN.1 structure. The key structure
* is encoded into a bit string which is put into this instance.</b>
*
* @param aid
* The AlgorithmIdentifier of the public key algorithm.
* @param key
* The public key as a ASN.1 data structure.
*/
public SubjectPublicKeyInfo(AlgorithmIdentifier aid, ASN1Type key) {
super(2);
algorithm_ = aid;
add(algorithm_);
add(null);
setRawKey(key);
}
/**
* Creates an instance that is initialized from the given public key.
*
* @param key
* The public key.
* @throws InvalidKeyException
* if the key cannot be decoded properly.
* @throws NullPointerException
* if the given key is <code>null</code>.
*/
public SubjectPublicKeyInfo(PublicKey key) throws InvalidKeyException {
super(2);
setPublicKey(key);
}
/**
* Returns the public key embedded in this structure.
* <p>
*
* This method creates an X509EncodedKeySpec of this instance and feeds it
* into a key factory. In order to locate a suitable key factory, the
* installed providers must define appropriate OID mappings.
*
* @return The public key.
* @throws InconsistentStateException
* if the key spec generated by this method is rejected by
* the key factory that is used to generate the key.
* @throws NoSuchAlgorithmException
* if there is no key factory registered for the algorithm
* of the embedded key or no appropriate OID mapping is
* defined by the installed providers.
*/
public PublicKey getPublicKey() throws NoSuchAlgorithmException {
ByteArrayOutputStream bos;
X509EncodedKeySpec spec;
DEREncoder enc;
KeyFactory kf;
String alg;
try {
bos = new ByteArrayOutputStream();
enc = new DEREncoder(bos);
encode(enc);
spec = new X509EncodedKeySpec(bos.toByteArray());
enc.close();
alg = algorithm_.getAlgorithmOID().toString();
kf = KeyFactory.getInstance(alg);
return kf.generatePublic(spec);
} catch (ASN1Exception e) {
throw new InconsistentStateException("Internal, encoding error!");
} catch (IOException e) {
throw new InconsistentStateException(
"Internal, I/O exception caught!");
} catch (InvalidKeySpecException e) {
throw new InconsistentStateException(
"Encoded key spec rejected by key factory!");
}
}
/**
* Initializes this instance with the given public key.
*
* @param key
* The public key from which this instance is initialized.
* @throws InvalidKeyException
* if the given key cannot be decoded properly.
* @throws NullPointerException
* if the given key is <code>null</code>.
*/
public void setPublicKey(PublicKey key) throws InvalidKeyException {
if (key == null)
throw new NullPointerException("Key is null!");
DERDecoder dec;
clear();
algorithm_ = new AlgorithmIdentifier();
add(algorithm_);
encodedKey_ = new ASN1BitString();
add(encodedKey_);
try {
dec = new DERDecoder(new ByteArrayInputStream(key.getEncoded()));
decode(dec);
dec.close();
} catch (IOException e) {
throw new InvalidKeyException("Caught IOException!");
} catch (ASN1Exception e) {
throw new InvalidKeyException("Bad encoding!");
}
}
/**
* Encodes and sets the given ASN.1 key structure as the raw key.
*
* @throws InconsistentStateException
* if an internal error occurs while the key is encoded.
* This should never happen.
*/
protected void setRawKey(ASN1Type key) {
ByteArrayOutputStream bos;
DEREncoder enc;
try {
bos = new ByteArrayOutputStream();
enc = new DEREncoder(bos);
key.encode(enc);
encodedKey_ = new ASN1BitString(bos.toByteArray(), 0);
enc.close();
set(1, encodedKey_);
} catch (ASN1Exception e) {
throw new InconsistentStateException("Internal, encoding error!");
} catch (IOException e) {
throw new InconsistentStateException(
"Internal, I/O exception caught!");
}
}
/**
* Returns the raw key material. <b>The key material consists of an encoded
* key structure.</b> ASN.1/DER is often used as the encoding. However,
* this need not always be the case. Elliptic curve cryptosystems use
* specific encodings.
* <p>
*
* If the key encoding is ASN.1/DER then the raw key can be retrieved as an
* ASN.1 type by means of the {@link #getDecodedRawKey getDecodedRawKey()}
* method.
*
* @return The raw key bytes as a byte array.
*/
public byte[] getRawKey() {
return encodedKey_.getBytes();
}
/**
* Returns an ASN.1 type that represents the decoded raw key. Decoding is
* done by means of ASN.1/DER. <b>Be careful, not all public keys are
* encoded according to DER.</b> Elliptic curve cryptosystems use specific
* encodings.
*
* @return The raw key decoded according to DER.
*/
public ASN1Type getDecodedRawKey() throws CorruptedCodeException {
DERDecoder dec;
ASN1Type raw;
try {
dec = new DERDecoder(new ByteArrayInputStream(encodedKey_
.getBytes()));
raw = dec.readType();
dec.close();
return raw;
} catch (ASN1Exception e) {
throw new CorruptedCodeException("Cannot decode raw key!");
} catch (IOException e) {
throw new InconsistentStateException(
"Internal, I/O exception caught!");
}
}
/**
* Returns the {@link AlgorithmIdentifier AlgorithmIdentifier} of the public
* key.
*
* @return The key algorithm's AlgorithmIdentifier.
*/
public AlgorithmIdentifier getAlgorithmIdentifier() {
return algorithm_;
}
/**
* sets the AlgorithmIdentifier for this public key
*
* @param aid
* AlgorithmIdentifier of this public key
*/
public void setAlgorithmIdentifier(AlgorithmIdentifier aid) {
if (aid == null)
throw new NullPointerException("Need an algorithm identifier!");
set(0, aid);
algorithm_ = aid;
}
/**
* @deprecated This method is no longer used.
*/
public ASN1Type getKeyStruct() throws CorruptedCodeException {
return getKeyStruct(true);
}
/**
* @param derDecode
* <code>true</code> if the raw key shall be decoded.
* @deprecated This method is no longer used.
*/
public ASN1Type getKeyStruct(boolean derDecode)
throws CorruptedCodeException {
if (derDecode)
return getDecodedRawKey();
return encodedKey_;
}
/**
* @param key
* The key structure.
* @deprecated This method is no longer used.
*/
public void setKeyStruct(ASN1Type key) {
setRawKey(key);
}
}

View File

@@ -0,0 +1,555 @@
/*
* Copyright (c) 1998-2003 by The FlexiProvider Group,
* Technische Universitaet Darmstadt
*
* For conditions of usage and distribution please refer to the
* file COPYING in the root directory of this package.
*
*/
package de.flexiprovider.api;
import java.io.ByteArrayOutputStream;
import de.flexiprovider.api.exceptions.BadPaddingException;
import de.flexiprovider.api.exceptions.IllegalBlockSizeException;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.InvalidKeyException;
import de.flexiprovider.api.exceptions.InvalidParameterException;
import de.flexiprovider.api.exceptions.ShortBufferException;
import de.flexiprovider.api.keys.Key;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
/**
* The AsymmetricBlockCipher class extends CipherSpi. An instance of this class
* will be created by the Cipher.getInstance(String)-mechanism of the Cipher
* class.<br>
* NOTE: Some Ciphers are using Padding. OneAndZeroesPadding is used as default
* padding. However padding can still be specified, but mode is not supported:
* Example: Cipher.getInstance("SomeCipher/NONE/SomePadding"); If you try to
* intantiate the cipher with something else than "NONE" as mode,
* NoSuchAlgorithmException is thrown.
*
* @author Thomas Wahrenbruch
* @author Hristo Indzhov
*/
public abstract class AsymmetricBlockCipher extends Cipher {
/**
* ParameterSpec used with this cipher
*/
protected AlgorithmParameterSpec paramSpec;
/**
* Internal buffer
*/
protected ByteArrayOutputStream buf;
/**
* The maximum number of bytes the cipher can decrypt.
*/
protected int maxPlainTextSize;
/**
* The maximum number of bytes the cipher can encrypt.
*/
protected int cipherTextSize;
/**
* The AsymmetricBlockCipher() constructor
*/
public AsymmetricBlockCipher() {
buf = new ByteArrayOutputStream();
}
/**
* Return the block size (in bytes). Note: although the ciphers extending
* this class are not block ciphers, the method was adopted to return the
* maximal plaintext and ciphertext sizes for non hybrid ciphers. If the
* cipher is hybrid, it returns 0.
*
* @return if the cipher is not a hybrid one the max plain/cipher text size
* is returned, otherwise 0 is returned
*/
public final int getBlockSize() {
return opMode == ENCRYPT_MODE ? maxPlainTextSize : cipherTextSize;
}
/**
* @return <tt>null</tt> since no initialization vector is used.
*/
public final byte[] getIV() {
return null;
}
/**
* Return the length in bytes that an output buffer would need to be in
* order to hold the result of the next update or doFinal operation, given
* the input length <tt>inLen</tt> (in bytes). This call takes into
* account any unprocessed (buffered) data from a previous update call, and
* padding. The actual output length of the next update() or doFinal() call
* may be smaller than the length returned by this method.
* <p>
* If the input length plus the length of the buffered data exceeds the
* maximum length, <tt>0</tt> is returned.
*
* @param inLen
* the length of the input
* @return the length of the ciphertext or <tt>0</tt> if the input is too
* long.
*/
public final int getOutputSize(int inLen) {
int totalLen = inLen + buf.size();
int maxLen = getBlockSize();
if (totalLen > maxLen) {
// the length of the input exceeds the maximal supported length
return 0;
}
return maxLen;
}
/**
* <p>
* Returns the parameters used with this cipher.
* <p>
* The returned parameters may be the same that were used to initialize this
* cipher, or may contain the default set of parameters or a set of randomly
* generated parameters used by the underlying cipher implementation
* (provided that the underlying cipher implementation uses a default set of
* parameters or creates new parameters if it needs parameters but was not
* initialized with any).
* <p>
*
* @return the parameters used with this cipher, or null if this cipher does
* not use any parameters.
*/
public final AlgorithmParameterSpec getParameters() {
return paramSpec;
}
/**
* Initializes the cipher for encryption by forwarding it to
* initEncrypt(Key, FlexiSecureRandom).
*
* <p>
* If this cipher requires any algorithm parameters that cannot be derived
* from the given key, the underlying cipher implementation is supposed to
* generate the required parameters itself (using provider-specific default
* or random values) if it is being initialized for encryption, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using engineGetParameters or
* engineGetIV (if the parameter is an IV).
*
* @param key
* the encryption or decryption key.
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher.
*/
public final void initEncrypt(Key key) throws InvalidKeyException {
try {
initEncrypt(key, null, Registry.getSecureRandom());
} catch (InvalidAlgorithmParameterException e) {
throw new InvalidParameterException(
"This cipher needs algorithm parameters for initialization (cannot be null).");
}
}
/**
* Initialize this cipher for encryption by forwarding it to
* initEncrypt(Key, FlexiSecureRandom, AlgorithmParameterSpec).
* <p>
* If this cipher requires any algorithm parameters that cannot be derived
* from the given key, the underlying cipher implementation is supposed to
* generate the required parameters itself (using provider-specific default
* or random values) if it is being initialized for encryption, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using engineGetParameters or
* engineGetIV (if the parameter is an IV).
*
* @param key
* the encryption or decryption key.
* @param random
* the source of randomness.
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher.
*/
public final void initEncrypt(Key key, SecureRandom random)
throws InvalidKeyException {
try {
initEncrypt(key, null, random);
} catch (InvalidAlgorithmParameterException iape) {
throw new InvalidParameterException(
"This cipher needs algorithm parameters for initialization (cannot be null).");
}
}
/**
* Initializes the cipher for encryption by forwarding it to
* initEncrypt(Key, FlexiSecureRandom, AlgorithmParameterSpec).
*
* @param key
* the encryption or decryption key.
* @param params
* the algorithm parameters.
*
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher.
* @throws InvalidAlgorithmParameterException
* if the given algortihm parameters are inappropriate for
* this cipher, or if this cipher is being initialized for
* decryption and requires algorithm parameters and params
* is null.
*/
public final void initEncrypt(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
initEncrypt(key, params, Registry.getSecureRandom());
}
/**
* This method initializes the AsymmetricBlockCipher with a certain key for
* data encryption.
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random.
* <p>
* Note that when a Cipher object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it
* <p>
*
* @param key
* the key which has to be used to encrypt data.
* @param secureRandom
* the source of randomness.
* @param params
* the algorithm parameters.
*
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher
* @throws InvalidAlgorithmParameterException
* if the given algorithm parameters are inappropriate for
* this cipher, or if this cipher is being initialized for
* decryption and requires algorithm parameters and params
* is null.
*/
public final void initEncrypt(Key key, AlgorithmParameterSpec params,
SecureRandom secureRandom) throws InvalidKeyException,
InvalidAlgorithmParameterException {
opMode = ENCRYPT_MODE;
initCipherEncrypt(key, params, secureRandom);
}
/**
* Initialize the cipher for decryption by forwarding it to
* {@link #initDecrypt(Key, AlgorithmParameterSpec)}.
* <p>
* If this cipher requires any algorithm parameters that cannot be derived
* from the given key, the underlying cipher implementation is supposed to
* generate the required parameters itself (using provider-specific default
* or random values) if it is being initialized for encryption, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using engineGetParameters or
* engineGetIV (if the parameter is an IV).
*
* @param key
* the encryption or decryption key.
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher.
*/
public final void initDecrypt(Key key) throws InvalidKeyException {
try {
initDecrypt(key, null);
} catch (InvalidAlgorithmParameterException iape) {
throw new InvalidParameterException(
"This cipher needs algorithm parameters for initialization (cannot be null).");
}
}
/**
* This method initializes the AsymmetricBlockCipher with a certain key for
* data decryption.
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random.
* <p>
* Note that when a Cipher object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it
* <p>
*
* @param key
* the key which has to be used to decrypt data.
* @param params
* the algorithm parameters.
*
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher
* @throws InvalidAlgorithmParameterException
* if the given algorithm parameters are inappropriate for
* this cipher, or if this cipher is being initialized for
* decryption and requires algorithm parameters and params
* is null.
*/
public final void initDecrypt(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
opMode = DECRYPT_MODE;
initCipherDecrypt(key, params);
}
/**
* Continue a multiple-part encryption or decryption operation. This method
* just writes the input into an internal buffer.
*
* @param input
* byte array containing the next part of the input
* @param inOff
* index in the array where the input starts
* @param inLen
* length of the input
* @return a new buffer with the result (always empty)
*/
public final byte[] update(byte[] input, int inOff, int inLen) {
if (inLen != 0) {
buf.write(input, inOff, inLen);
}
return new byte[0];
}
/**
* Continue a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized), processing another data part.
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @param output
* the output buffer
* @param outOff
* the offset where the result is stored
* @return the length of the output (always 0)
*/
public final int update(byte[] input, int inOff, int inLen, byte[] output,
int outOff) {
update(input, inOff, inLen);
return 0;
}
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @return a new buffer with the result
* @throws IllegalBlockSizeException
* if the plaintext or ciphertext size is too large.
* @throws BadPaddingException
* if the ciphertext is invalid.
*/
public final byte[] doFinal(byte[] input, int inOff, int inLen)
throws IllegalBlockSizeException, BadPaddingException {
checkLength(inLen);
update(input, inOff, inLen);
byte[] mBytes = buf.toByteArray();
buf.reset();
switch (opMode) {
case ENCRYPT_MODE:
return messageEncrypt(mBytes);
case DECRYPT_MODE:
return messageDecrypt(mBytes);
default:
return null;
}
}
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @param output
* the buffer for the result
* @param outOff
* the offset where the result is stored
* @return the output length
* @throws ShortBufferException
* if the output buffer is too small to hold the result.
* @throws IllegalBlockSizeException
* if the plaintext or ciphertext size is too large.
* @throws BadPaddingException
* if the ciphertext is invalid.
*/
public final int doFinal(byte[] input, int inOff, int inLen, byte[] output,
int outOff) throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException {
if (output.length < getOutputSize(inLen)) {
throw new ShortBufferException("Output buffer too short.");
}
byte[] out = doFinal(input, inOff, inLen);
System.arraycopy(out, 0, output, outOff, out.length);
return out.length;
}
/**
* Since asymmetric block ciphers do not support modes, this method does
* nothing.
*
* @param modeName
* the cipher mode (unused)
*/
protected final void setMode(String modeName) {
// empty
}
/**
* Since asymmetric block ciphers do not support padding, this method does
* nothing.
*
* @param paddingName
* the name of the padding scheme (not used)
*/
protected final void setPadding(String paddingName) {
// empty
}
/**
* Check if the message length plus the length of the input length can be
* en/decrypted. This method uses the specific values
* {@link #maxPlainTextSize} and {@link #cipherTextSize} which are set by
* the implementations. If the input length plus the length of the internal
* buffer is greater than {@link #maxPlainTextSize} for encryption or not
* equal to {@link #cipherTextSize} for decryption, an
* {@link IllegalBlockSizeException} will be thrown.
*
* @param inLen
* length of the input to check
* @throws IllegalBlockSizeException
* if the input length is invalid.
*/
protected void checkLength(int inLen) throws IllegalBlockSizeException {
int inLength = inLen + buf.size();
if (opMode == ENCRYPT_MODE) {
if (inLength > maxPlainTextSize) {
throw new IllegalBlockSizeException(
"The length of the plaintext (" + inLength
+ " bytes) is not supported by "
+ "the cipher (max. " + maxPlainTextSize
+ " bytes).");
}
} else if (opMode == DECRYPT_MODE) {
if (inLength != cipherTextSize) {
throw new IllegalBlockSizeException(
"Illegal ciphertext length (expected " + cipherTextSize
+ " bytes, was " + inLength + " bytes).");
}
}
}
/**
* Initialize the AsymmetricBlockCipher with a certain key for data
* encryption.
*
* @param key
* the key which has to be used to encrypt data
* @param params
* the algorithm parameters
* @param sr
* the source of randomness
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher.
* @throws InvalidAlgorithmParameterException
* if the given parameters are inappropriate for
* initializing this cipher.
*/
protected abstract void initCipherEncrypt(Key key,
AlgorithmParameterSpec params, SecureRandom sr)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Initialize the AsymmetricBlockCipher with a certain key for data
* encryption.
*
* @param key
* the key which has to be used to decrypt data
* @param params
* the algorithm parameters
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher
* @throws InvalidAlgorithmParameterException
* if the given parameters are inappropriate for
* initializing this cipher.
*/
protected abstract void initCipherDecrypt(Key key,
AlgorithmParameterSpec params) throws InvalidKeyException,
InvalidAlgorithmParameterException;
/**
* Encrypt the message stored in input. The method should also perform an
* additional length check.
*
* @param input
* the message to be encrypted (usually the message length is
* less than or equal to maxPlainTextSize)
* @return the encrypted message (it has length equal to maxCipherTextSize_)
* @throws IllegalBlockSizeException
* if the input is inappropriate for this cipher.
* @throws BadPaddingException
* if the input format is invalid.
*/
protected abstract byte[] messageEncrypt(byte[] input)
throws IllegalBlockSizeException, BadPaddingException;
/**
* Decrypt the ciphertext stored in input. The method should also perform an
* additional length check.
*
* @param input
* the ciphertext to be decrypted (the ciphertext length is
* less than or equal to maxCipherTextSize)
* @return the decrypted message
* @throws IllegalBlockSizeException
* if the input is inappropriate for this cipher.
* @throws BadPaddingException
* if the input format is invalid.
*/
protected abstract byte[] messageDecrypt(byte[] input)
throws IllegalBlockSizeException, BadPaddingException;
}

View File

@@ -0,0 +1,431 @@
/*
* Copyright (c) 1998-2003 by The FlexiProvider Group,
* Technische Universitaet Darmstadt
*
* For conditions of usage and distribution please refer to the
* file COPYING in the root directory of this package.
*/
package de.flexiprovider.api;
import de.flexiprovider.api.exceptions.BadPaddingException;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.InvalidKeyException;
import de.flexiprovider.api.exceptions.InvalidParameterException;
import de.flexiprovider.api.exceptions.ShortBufferException;
import de.flexiprovider.api.keys.Key;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
/**
* The AsymmetricHybridCipher class extends CipherSpi. An instance of this class
* will be created by the Cipher.getInstance(String)-mechanism of the Cipher
* class.<br>
* NOTE: Some Ciphers are using Padding. OneAndZeroesPadding is used as default
* padding. However padding can still be specified, but mode is not supported:
* Example: Cipher.getInstance("SomeCipher/NONE/SomePadding"); If you try to
* intantiate the cipher with something else than "NONE" as mode,
* NoSuchAlgorithmException is thrown.
*
* @author Thomas Wahrenbruch
* @author Hristo Indzhov
*/
public abstract class AsymmetricHybridCipher extends Cipher {
/**
* ParameterSpec used with this cipher
*/
protected AlgorithmParameterSpec paramSpec;
/**
* Since asymmetric hybrid ciphers do not support modes, this method does
* nothing.
*
* @param modeName
* the cipher mode (unused)
*/
protected final void setMode(String modeName) {
// empty
}
/**
* Since asymmetric hybrid ciphers do not support padding, this method does
* nothing.
*
* @param paddingName
* the name of the padding scheme (not used)
*/
protected final void setPadding(String paddingName) {
// empty
}
/**
* @return <tt>null</tt> since no initialization vector is used.
*/
public final byte[] getIV() {
return null;
}
/**
* @return 0 since the implementing algorithms are not block ciphers
*/
public final int getBlockSize() {
return 0;
}
/**
* Return the parameters used with this cipher.
* <p>
* The returned parameters may be the same that were used to initialize this
* cipher, or may contain the default set of parameters or a set of randomly
* generated parameters used by the underlying cipher implementation
* (provided that the underlying cipher implementation uses a default set of
* parameters or creates new parameters if it needs parameters but was not
* initialized with any).
*
* @return the parameters used with this cipher, or <tt>null</tt> if this
* cipher does not use any parameters.
*/
public final AlgorithmParameterSpec getParameters() {
return paramSpec;
}
/**
* Return the length in bytes that an output buffer would need to be in
* order to hold the result of the next update or doFinal operation, given
* the input length <tt>inLen</tt> (in bytes). This call takes into
* account any unprocessed (buffered) data from a previous update call, and
* padding. The actual output length of the next update() or doFinal() call
* may be smaller than the length returned by this method.
*
* @param inLen
* the length of the input
* @return the length of the output of the next <tt>update()</tt> or
* <tt>doFinal()</tt> call
*/
public final int getOutputSize(int inLen) {
return opMode == ENCRYPT_MODE ? encryptOutputSize(inLen)
: decryptOutputSize(inLen);
}
/**
* Initialize the cipher for encryption by forwarding it to
* {@link #initEncrypt(Key, AlgorithmParameterSpec, SecureRandom)}.
* <p>
* If this cipher requires any algorithm parameters that cannot be derived
* from the given key, the underlying cipher implementation is supposed to
* generate the required parameters itself (using provider-specific default
* or random values) if it is being initialized for encryption, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using {@link #getParameters()}.
*
* @param key
* the encryption key
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher.
* @throws InvalidParameterException
* if this cipher needs algorithm parameters for
* initialization and cannot generate parameters itself.
*/
public final void initEncrypt(Key key) throws InvalidKeyException {
try {
initEncrypt(key, null, Registry.getSecureRandom());
} catch (InvalidAlgorithmParameterException e) {
throw new InvalidParameterException(
"This cipher needs algorithm parameters for initialization (cannot be null).");
}
}
/**
* Initialize this cipher for encryption by forwarding it to
* {@link #initEncrypt(Key, AlgorithmParameterSpec, SecureRandom)}.
* <p>
* If this cipher requires any algorithm parameters that cannot be derived
* from the given key, the underlying cipher implementation is supposed to
* generate the required parameters itself (using provider-specific default
* or random values) if it is being initialized for encryption, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using {@link #getParameters()}.
*
* @param key
* the encryption key
* @param random
* the source of randomness
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher.
* @throws InvalidParameterException
* if this cipher needs algorithm parameters for
* initialization and cannot generate parameters itself.
*/
public final void initEncrypt(Key key, SecureRandom random)
throws InvalidKeyException {
try {
initEncrypt(key, null, random);
} catch (InvalidAlgorithmParameterException iape) {
throw new InvalidParameterException(
"This cipher needs algorithm parameters for initialization (cannot be null).");
}
}
/**
* Initialize the cipher for encryption by forwarding it to initEncrypt(Key,
* FlexiSecureRandom, AlgorithmParameterSpec).
*
* @param key
* the encryption key
* @param params
* the algorithm parameters
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher.
* @throws InvalidAlgorithmParameterException
* if the given algorithm parameters are inappropriate for
* this cipher, or if this cipher is initialized with
* <tt>null</tt> parameters and cannot generate parameters
* itself.
*/
public final void initEncrypt(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
initEncrypt(key, params, Registry.getSecureRandom());
}
/**
* Initialize the cipher with a certain key for data encryption.
* <p>
* If this cipher requires any random bytes (e.g., for parameter
* generation), it will get them from <tt>random</tt>.
* <p>
* Note that when a Cipher object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it.
*
* @param key
* the encryption key
* @param random
* the source of randomness
* @param params
* the algorithm parameters
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher
* @throws InvalidAlgorithmParameterException
* if the given algorithm parameters are inappropriate for
* this cipher, or if this cipher is initialized with
* <tt>null</tt> parameters and cannot generate parameters
* itself.
*/
public final void initEncrypt(Key key, AlgorithmParameterSpec params,
SecureRandom random) throws InvalidKeyException,
InvalidAlgorithmParameterException {
opMode = ENCRYPT_MODE;
initCipherEncrypt(key, params, random);
}
/**
* Initialize the cipher for decryption by forwarding it to initDecrypt(Key,
* FlexiSecureRandom).
* <p>
* If this cipher requires any algorithm parameters that cannot be derived
* from the given key, the underlying cipher implementation is supposed to
* generate the required parameters itself (using provider-specific default
* or random values) if it is being initialized for encryption, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using {@link #getParameters()}.
*
* @param key
* the decryption key
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher.
*/
public final void initDecrypt(Key key) throws InvalidKeyException {
try {
initDecrypt(key, null);
} catch (InvalidAlgorithmParameterException iape) {
throw new InvalidParameterException(
"This cipher needs algorithm parameters for initialization (cannot be null).");
}
}
/**
* Initialize the cipher with a certain key for data decryption.
* <p>
* If this cipher requires any random bytes (e.g., for parameter
* generation), it will get them from <tt>random</tt>.
* <p>
* Note that when a Cipher object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it
*
* @param key
* the decryption key
* @param params
* the algorithm parameters
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher
* @throws InvalidAlgorithmParameterException
* if the given algorithm parameters are inappropriate for
* this cipher, or if this cipher is initialized with
* <tt>null</tt> parameters and cannot generate parameters
* itself.
*/
public final void initDecrypt(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
opMode = DECRYPT_MODE;
initCipherDecrypt(key, params);
}
/**
* Continue a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized), processing another data part.
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @return a new buffer with the result (maybe an empty byte array)
*/
public abstract byte[] update(byte[] input, int inOff, int inLen);
/**
* Continue a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized), processing another data part.
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @param output
* the output buffer
* @param outOff
* the offset where the result is stored
* @return the length of the output
* @throws ShortBufferException
* if the output buffer is too small to hold the result.
*/
public final int update(byte[] input, int inOff, int inLen, byte[] output,
int outOff) throws ShortBufferException {
if (output.length < getOutputSize(inLen)) {
throw new ShortBufferException("output");
}
byte[] out = update(input, inOff, inLen);
System.arraycopy(out, 0, output, outOff, out.length);
return out.length;
}
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @return a new buffer with the result
* @throws BadPaddingException
* if the ciphertext is invalid.
*/
public abstract byte[] doFinal(byte[] input, int inOff, int inLen)
throws BadPaddingException;
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @param output
* the buffer for the result
* @param outOff
* the offset where the result is stored
* @return the output length
* @throws ShortBufferException
* if the output buffer is too small to hold the result.
* @throws BadPaddingException
* if the ciphertext is invalid.
*/
public final int doFinal(byte[] input, int inOff, int inLen, byte[] output,
int outOff) throws ShortBufferException, BadPaddingException {
if (output.length < getOutputSize(inLen)) {
throw new ShortBufferException("Output buffer too short.");
}
byte[] out = doFinal(input, inOff, inLen);
System.arraycopy(out, 0, output, outOff, out.length);
return out.length;
}
/**
* Compute the output size of an update() or doFinal() operation of a hybrid
* asymmetric cipher in encryption mode when given input of the specified
* length.
*
* @param inLen
* the length of the input
* @return the output size
*/
protected abstract int encryptOutputSize(int inLen);
/**
* Compute the output size of an update() or doFinal() operation of a hybrid
* asymmetric cipher in decryption mode when given input of the specified
* length.
*
* @param inLen
* the length of the input
* @return the output size
*/
protected abstract int decryptOutputSize(int inLen);
/**
* Initialize the AsymmetricHybridCipher with a certain key for data
* encryption.
*
* @param key
* the key which has to be used to encrypt data
* @param params
* the algorithm parameters
* @param sr
* the source of randomness
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher.
* @throws InvalidAlgorithmParameterException
* if the given parameters are inappropriate for
* initializing this cipher.
*/
protected abstract void initCipherEncrypt(Key key,
AlgorithmParameterSpec params, SecureRandom sr)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Initialize the AsymmetricHybridCipher with a certain key for data
* encryption.
*
* @param key
* the key which has to be used to decrypt data
* @param params
* the algorithm parameters
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher
* @throws InvalidAlgorithmParameterException
* if the given parameters are inappropriate for
* initializing this cipher.
*/
protected abstract void initCipherDecrypt(Key key,
AlgorithmParameterSpec params) throws InvalidKeyException,
InvalidAlgorithmParameterException;
}

View File

@@ -0,0 +1,897 @@
/*
* Copyright (c) 1998-2003 by The FlexiProvider Group,
* Technische Universitaet Darmstadt
*
* For conditions of usage and distribution please refer to the
* file COPYING in the root directory of this package.
*
*/
package de.flexiprovider.api;
import java.lang.reflect.Method;
import de.flexiprovider.api.exceptions.BadPaddingException;
import de.flexiprovider.api.exceptions.IllegalBlockSizeException;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.InvalidKeyException;
import de.flexiprovider.api.exceptions.InvalidParameterException;
import de.flexiprovider.api.exceptions.NoSuchModeException;
import de.flexiprovider.api.exceptions.NoSuchPaddingException;
import de.flexiprovider.api.exceptions.ShortBufferException;
import de.flexiprovider.api.keys.Key;
import de.flexiprovider.api.keys.SecretKey;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
import de.flexiprovider.common.mode.ModeParameterSpec;
import de.flexiprovider.common.util.JavaSecureRandomWrapper;
/**
* The BlockCipher class extends CipherSpi and handles the creation of
* PaddingScheme, BlockCipher and Mode. An instance of this class will be
* created by the Cipher.getInstance(String)-mechanism of the Cipher class.
* <p>
* BlockCipher ensures that a Mode and a PaddingsScheme are created, even if the
* user has set no preferences. For this to work, BlockCipher requires version
* 1.3 of the mode class that can handle a getInstance()-call without arguments
* to return a default Mode or Padding.
* <p>
* BlockCipher will acknowledge only <b>one</b> call of engineSetMode() and
* engineSetPadding() to ensure that these settings aren't changed while
* encrypting.
*
* @author Christoph Sesterhenn, Christoph Ender
* @author Ralf-Philipp Weinmann
* @author Martin D<>ring, Johannes M<>ller
*/
public abstract class BlockCipher extends Cipher {
/**
* The reference to the mode class.
*/
private Mode mode;
/**
* The reference to the padding scheme.
*/
private PaddingScheme paddingScheme;
/**
* AlgorithmParameterSpec
*/
private AlgorithmParameterSpec paramSpec;
/**
* This buffer holds the outsize left by an update operation
*/
private byte[] buffer = null;
/**
* the block size of the mode
*/
private int modeBlockSize;
/**
* Used to check if an initialization method has been called.
*/
private boolean initialized = false;
/**
* the source of randomness, if necessary
*/
protected SecureRandom random;
// ****************************************************
// JCA adapter methods
// ****************************************************
/**
* Initialize this cipher object with proper key and algorithm parameters,
* and some random seed. Before a cipher object is ready for data
* processing, it has to be initialized according to the desired
* cryptographic operation, which is specified by the opmode parameter
* (either ENCRYPT_MODE or DECCRYPT_MODE). e.g.
* cipher_obj.init(Cipher.ENCRYPT_MODE, key, alg_params, random_seed); The
* Cipher init will call the proper CipherSpi engineInit method. Note: If
* the Mode needs an initialization vector, a try to retrieve it from the
* AlgorithmParametersSpec is made.
*
* @param opmode
* the operation mode for which this cipher is used
* (ENCRYPT_MODE or DECRYPT_MODE)
* @param key
* the key
* @param paramSpec
* the algorithm parameters
* @param javaRand
* the random seed
* @throws java.security.InvalidKeyException
* if the key is inappropriate for initializing this block
* cipher.
* @throws java.security.InvalidAlgorithmParameterException
* if the parameters are inappropriate for initializing this
* block cipher.
*/
protected final void engineInit(int opmode, java.security.Key key,
java.security.spec.AlgorithmParameterSpec paramSpec,
java.security.SecureRandom javaRand)
throws java.security.InvalidKeyException,
java.security.InvalidAlgorithmParameterException {
random = new JavaSecureRandomWrapper(javaRand);
initModeAndPadding();
opMode = opmode;
buffer = new byte[0];
ModeParameterSpec modeParams;
AlgorithmParameterSpec cipherParams;
if (paramSpec == null) {
modeParams = null;
cipherParams = null;
} else if (paramSpec instanceof javax.crypto.spec.IvParameterSpec) {
modeParams = new ModeParameterSpec(
(javax.crypto.spec.IvParameterSpec) paramSpec);
cipherParams = null;
} else if (paramSpec instanceof ModeParameterSpec) {
modeParams = (ModeParameterSpec) paramSpec;
cipherParams = null;
} else {
if (!(paramSpec instanceof AlgorithmParameterSpec)) {
throw new java.security.InvalidAlgorithmParameterException(
"unsupported type");
}
cipherParams = (AlgorithmParameterSpec) paramSpec;
byte[] iv;
Method getIV;
try {
getIV = cipherParams.getClass().getMethod("getIV", null);
iv = (byte[]) getIV.invoke(cipherParams, null);
} catch (Exception ex) {
// if no getIV() method is found, iv remains null
iv = null;
}
if (iv == null) {
modeParams = null;
} else {
modeParams = new ModeParameterSpec(iv);
}
}
if (!(key instanceof SecretKey)) {
throw new java.security.InvalidKeyException("unsupported type");
}
if (opmode == ENCRYPT_MODE) {
mode.initEncrypt((SecretKey) key, modeParams, cipherParams);
} else if (opmode == DECRYPT_MODE) {
mode.initDecrypt((SecretKey) key, modeParams, cipherParams);
}
modeBlockSize = mode.blockSize;
paddingScheme.setBlockSize(modeBlockSize);
initialized = true;
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
/**
* Set the mode of this cipher. The mode can only be set once.
*
* @param modeName
* the cipher mode
* @throws NoSuchModeException
* if neither the mode with the given name nor the default
* mode can be found
*/
public final void setMode(String modeName) throws NoSuchModeException {
if (mode != null) {
return;
}
if ((modeName == null) || (modeName == "")) {
mode = Registry.getMode();
} else {
mode = Registry.getMode(modeName);
}
mode.setBlockCipher(this);
}
/**
* Set the padding scheme of this cipher. The padding scheme can only be set
* once.
*
* @param paddingName
* the padding scheme
* @throws NoSuchPaddingException
* if the requested padding scheme cannot be found.
*/
public final void setPadding(String paddingName)
throws NoSuchPaddingException {
if (paddingScheme != null) {
return;
}
if (paddingName == null || paddingName.equals("")) {
paddingScheme = Registry.getPaddingScheme();
} else {
paddingScheme = Registry.getPaddingScheme(paddingName);
}
}
/**
* Return the initialization vector. This is useful in the context of
* password-based encryption or decryption, where the IV is derived from a
* user-provided passphrase.
*
* @return the initialization vector in a new buffer, or <tt>null</tt> if
* the underlying algorithm does not use an IV, or if the IV has not
* yet been set.
*/
public final byte[] getIV() {
return initialized ? mode.iv : null;
}
/**
* Return the blocksize the algorithm uses. This method will usually be
* called by the mode.
*
* @return the blocksize of the cipher
*/
protected abstract int getCipherBlockSize();
/**
* @return the block size of the used mode, or -1 if the cipher has not been
* initialized.
*/
public final int getBlockSize() {
return initialized ? modeBlockSize : -1;
}
/**
* Return the length in bytes that an output buffer would need to be in
* order to hold the result of the next update or doFinal operation, given
* the input length inputLen (in bytes).
* <p>
* This call takes into account any unprocessed (buffered) data from a
* previous update call, and padding.
* <p>
* The actual output length of the next update or doFinal call may be
* smaller than the length returned by this method.
*
* @param inLen
* the input length (in bytes)
* @return the required output buffer size (in bytes)
*/
public final int getOutputSize(int inLen) {
if (!initialized) {
return -1;
}
final int newInLen = inLen + (buffer == null ? 0 : buffer.length);
return newInLen + paddingScheme.padLength(newInLen);
}
/**
* Return the parameters used with this cipher.
* <p>
* The returned parameters may be the same that were used to initialize this
* cipher, or may contain the default set of parameters or a set of randomly
* generated parameters used by the underlying cipher implementation
* (provided that the underlying cipher implementation uses a default set of
* parameters or creates new parameters if it needs parameters but was not
* initialized with any).
*
* @return the parameters used with this cipher, or null if this cipher does
* not use any parameters.
*/
public final AlgorithmParameterSpec getParameters() {
return initialized ? paramSpec : null;
}
/**
* Initialize this cipher with a key and a source of randomness for
* encryption.
* <p>
* If this cipher requires any algorithm parameters that cannot be derived
* from the given key, the underlying cipher implementation is supposed to
* generate the required parameters itself (using provider-specific default
* or random values) if it is being initialized for encryption, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using engineGetParameters or
* engineGetIV (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random.
* <p>
* Note that when a {@link BlockCipher} object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it
*
* @param key
* the encryption key
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher
* @throws InvalidParameterException
* if this block cipher requires parameters for
* initialization and cannot generate parameters itself.
*/
public final void initEncrypt(Key key) throws InvalidKeyException,
InvalidParameterException {
initEncrypt(key, Registry.getSecureRandom());
}
/**
* Initialize this cipher with a key and a source of randomness for
* encryption.
* <p>
* If this cipher requires any algorithm parameters that cannot be derived
* from the given key, the underlying cipher implementation is supposed to
* generate the required parameters itself (using provider-specific default
* or random values) if it is being initialized for encryption, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using engineGetParameters or
* engineGetIV (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random and they will be stored in the class variable rndBytes.
* <p>
* Note that when a {@link BlockCipher} object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it
*
* @param key
* the encryption key
* @param random
* the source of randomness
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher
* @throws InvalidParameterException
* if this block cipher requires parameters for
* initialization and cannot generate parameters itself.
*/
public final void initEncrypt(Key key, SecureRandom random)
throws InvalidKeyException, InvalidParameterException {
try {
initEncrypt(key, (ModeParameterSpec) null,
(AlgorithmParameterSpec) null, random);
} catch (InvalidAlgorithmParameterException e) {
throw new InvalidParameterException(
"This cipher needs algorithm parameters for initialization (cannot be null).");
}
}
/**
* Initialize this cipher with a key, a set of algorithm parameters, and a
* source of randomness for encryption.
* <p>
* If this cipher requires any algorithm parameters and paramSpec is null,
* the underlying cipher implementation is supposed to generate the required
* parameters itself (using provider-specific default or random values) if
* it is being initialized for encryption, and raise an
* InvalidAlgorithmParameterException if it is being initialized for
* decryption. The generated parameters can be retrieved using
* engineGetParameters or engineGetIV (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random.
* <p>
* Note that when a {@link BlockCipher} object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it.
*
* @param key
* the encryption key
* @param cipherParams
* the cipher parameters
* @param random
* the source of randomness
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* block cipher.
* @throws InvalidAlgorithmParameterException
* if the parameters are inappropriate for initializing this
* block cipher.
*/
public final void initEncrypt(Key key, AlgorithmParameterSpec cipherParams,
SecureRandom random) throws InvalidKeyException,
InvalidAlgorithmParameterException {
initEncrypt(key, null, cipherParams, random);
}
/**
* Initialize this cipher with a key, a set of algorithm parameters, and a
* source of randomness for encryption.
* <p>
* If this cipher requires any algorithm parameters and paramSpec is null,
* the underlying cipher implementation is supposed to generate the required
* parameters itself (using provider-specific default or random values) if
* it is being initialized for encryption, and raise an
* InvalidAlgorithmParameterException if it is being initialized for
* decryption. The generated parameters can be retrieved using
* engineGetParameters or engineGetIV (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random.
* <p>
* Note that when a {@link BlockCipher} object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it.
*
* @param key
* the encryption key
* @param modeParams
* the mode parameters
* @param cipherParams
* the cipher parameters
* @param random
* the source of randomness
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* block cipher.
* @throws InvalidAlgorithmParameterException
* if the parameters are inappropriate for initializing this
* block cipher.
*/
public final void initEncrypt(Key key, ModeParameterSpec modeParams,
AlgorithmParameterSpec cipherParams, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
this.random = random != null ? random : Registry.getSecureRandom();
initModeAndPadding();
opMode = ENCRYPT_MODE;
buffer = new byte[0];
paramSpec = cipherParams;
if (!(key instanceof SecretKey)) {
throw new InvalidKeyException("unsupported type");
}
mode.initEncrypt((SecretKey) key, modeParams, cipherParams);
modeBlockSize = mode.blockSize;
paddingScheme.setBlockSize(modeBlockSize);
initialized = true;
}
/**
* Initialize this cipher with a key and a source of randomness for
* decryption.
* <p>
* If this cipher requires any algorithm parameters that cannot be derived
* from the given key, the underlying cipher implementation is supposed to
* generate the required parameters itself (using provider-specific default
* or random values) if it is being initialized for encryption, and raise an
* InvalidKeyException if it is being initialized for decryption. The
* generated parameters can be retrieved using engineGetParameters or
* engineGetIV (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random.
* <p>
* Note that when a {@link BlockCipher} object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it
*
* @param key
* the encryption key
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher
* @throws InvalidParameterException
* if the parameters are
*/
public final void initDecrypt(Key key) throws InvalidKeyException,
InvalidParameterException {
try {
initDecrypt(key, (ModeParameterSpec) null,
(AlgorithmParameterSpec) null);
} catch (InvalidAlgorithmParameterException e) {
throw new InvalidParameterException(
"This cipher needs algorithm parameters for initialization (cannot be null).");
}
}
/**
* Initialize this cipher with a key, a set of algorithm parameters, and a
* source of randomness for decryption.
* <p>
* If this cipher requires any algorithm parameters and paramSpec is null,
* the underlying cipher implementation is supposed to generate the required
* parameters itself (using provider-specific default or random values) if
* it is being initialized for encryption, and throw an
* {@link InvalidAlgorithmParameterException} if it is being initialized for
* decryption. The generated parameters can be retrieved using
* engineGetParameters or engineGetIV (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random.
* <p>
* Note that when a {@link BlockCipher} object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it.
*
* @param key
* the encryption key
* @param cipherParams
* the cipher parameters
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* block cipher.
* @throws InvalidAlgorithmParameterException
* if the parameters are inappropriate for initializing this
* block cipher.
*/
public final void initDecrypt(Key key, AlgorithmParameterSpec cipherParams)
throws InvalidKeyException, InvalidAlgorithmParameterException {
initDecrypt(key, null, cipherParams);
}
/**
* Initialize this cipher with a key, a set of algorithm parameters, and a
* source of randomness for decryption.
* <p>
* If this cipher requires any algorithm parameters and paramSpec is null,
* the underlying cipher implementation is supposed to generate the required
* parameters itself (using provider-specific default or random values) if
* it is being initialized for encryption, and throw an
* {@link InvalidAlgorithmParameterException} if it is being initialized for
* decryption. The generated parameters can be retrieved using
* engineGetParameters or engineGetIV (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random.
* <p>
* Note that when a {@link BlockCipher} object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it.
*
* @param key
* the encryption key
* @param modeParams
* the mode parameters
* @param cipherParams
* the cipher parameters
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* block cipher.
* @throws InvalidAlgorithmParameterException
* if the parameters are inappropriate for initializing this
* block cipher.
*/
public final void initDecrypt(Key key, ModeParameterSpec modeParams,
AlgorithmParameterSpec cipherParams) throws InvalidKeyException,
InvalidAlgorithmParameterException {
initModeAndPadding();
opMode = DECRYPT_MODE;
buffer = new byte[0];
paramSpec = cipherParams;
if (!(key instanceof SecretKey)) {
throw new InvalidKeyException("unsupported type");
}
mode.initDecrypt((SecretKey) key, modeParams, cipherParams);
modeBlockSize = mode.blockSize;
paddingScheme.setBlockSize(modeBlockSize);
initialized = true;
}
/**
* Continue a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized), processing another data part.
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @return a new buffer with the result (maybe an empty byte array)
*/
public final byte[] update(byte[] input, int inOff, int inLen) {
// if the cipher is not initialized or input is empty, return an empty
// byte array
if (!initialized || input == null || inLen <= 0) {
return new byte[0];
}
// concatenate buffer and input (only if buffer is not empty)
int bufLen = buffer.length;
int newInLen, newInOff;
byte[] newInput;
if (bufLen == 0) {
newInOff = inOff;
newInLen = inLen;
newInput = input;
} else {
newInLen = bufLen + inLen;
newInOff = 0;
newInput = new byte[newInLen];
System.arraycopy(buffer, 0, newInput, 0, bufLen);
System.arraycopy(input, inOff, newInput, bufLen, inLen);
}
// compute number of blocks to process and remaining bytes
int numBlocks = newInLen / modeBlockSize;
int numBytes = numBlocks * modeBlockSize;
int remaining = newInLen - numBytes;
if (opMode == DECRYPT_MODE && remaining == 0) {
remaining = modeBlockSize;
numBlocks--;
numBytes -= modeBlockSize;
}
byte[] output = new byte[numBytes];
int outOff = 0;
// process whole blocks
for (int block = 0; block < numBlocks; block++) {
if (opMode == ENCRYPT_MODE) {
mode.nextChunkEncrypt(newInput, newInOff, output, outOff);
} else if (opMode == DECRYPT_MODE) {
mode.nextChunkDecrypt(newInput, newInOff, output, outOff);
}
newInOff += modeBlockSize;
outOff += modeBlockSize;
}
// copy unprocessed bytes to buffer
buffer = new byte[remaining];
System.arraycopy(newInput, newInOff, buffer, 0, remaining);
return output;
}
/**
* Continue a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized), processing another data part.
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @param output
* the output buffer
* @param outOff
* the offset where the result is stored
* @return the length of the output
* @throws ShortBufferException
* if the output buffer is too small to hold the result.
*/
public final int update(byte[] input, int inOff, int inLen, byte[] output,
int outOff) throws ShortBufferException {
// if the cipher is not initialized or input is empty return 0
if (!initialized || input == null || inLen <= 0) {
return 0;
}
// compute number of bytes to process
int newInLen = buffer.length + inLen;
int remaining = newInLen % modeBlockSize;
if (opMode == DECRYPT_MODE && remaining == 0) {
remaining = modeBlockSize;
}
int numBytes = newInLen - remaining;
if (output.length - outOff < numBytes) {
throw new ShortBufferException("output");
}
byte[] update = update(input, inOff, inLen);
System.arraycopy(update, 0, output, outOff, update.length);
return update.length;
}
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @return a new buffer with the result
* @throws IllegalBlockSizeException
* if the total input length is not a multiple of the block
* size (for encryption when no padding is used or for
* decryption).
* @throws BadPaddingException
* if unpadding fails.
*/
public final byte[] doFinal(byte[] input, int inOff, int inLen)
throws IllegalBlockSizeException, BadPaddingException {
byte[] output = new byte[0];
if (input == null && buffer == null) {
return output;
}
byte[] update = update(input, inOff, inLen);
int updLen = update.length;
int bufLen = buffer.length;
if (opMode == ENCRYPT_MODE) {
int padLen = paddingScheme.padLength(bufLen);
if (padLen == 0) {
return update;
}
output = new byte[updLen + bufLen + padLen];
System.arraycopy(update, 0, output, 0, updLen);
System.arraycopy(buffer, 0, output, updLen, bufLen);
paddingScheme.pad(output, updLen, bufLen);
mode.nextChunkEncrypt(output, updLen, output, updLen);
} else if (opMode == DECRYPT_MODE) {
if (bufLen != modeBlockSize) {
throw new IllegalBlockSizeException(
"ciphertext length is not a multiple of block size");
}
mode.nextChunkDecrypt(buffer, 0, buffer, 0);
int padOffset = paddingScheme.unpad(buffer, 0, modeBlockSize);
output = new byte[updLen + padOffset];
System.arraycopy(update, 0, output, 0, updLen);
System.arraycopy(buffer, 0, output, updLen, padOffset);
}
buffer = null;
mode.reset();
return output;
}
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @param output
* the buffer for the result
* @param outOff
* the offset where the result is stored
* @return the output length
* @throws ShortBufferException
* if the output buffer is too small to hold the result.
* @throws IllegalBlockSizeException
* if the total input length is not a multiple of the block
* size (for encryption when no padding is used or for
* decryption).
* @throws BadPaddingException
* if unpadding fails.
*/
public final int doFinal(byte[] input, int inOff, int inLen, byte[] output,
int outOff) throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException {
byte[] doFinal = doFinal(input, inOff, inLen);
int outLen = doFinal.length;
if (outLen == 0) {
return 0;
}
if (output.length - outOff < outLen) {
throw new ShortBufferException("output");
}
System.arraycopy(doFinal, 0, output, outOff, outLen);
return outLen;
}
/**
* Initialize the block cipher with a secret key and parameters for data
* encryption.
*
* @param key
* the secret key
* @param params
* the parameters
* @throws InvalidKeyException
* if the given key is inappropriate for this cipher.
* @throws InvalidAlgorithmParameterException
* if the given parameters are inappropriate for this
* cipher.
*/
protected abstract void initCipherEncrypt(SecretKey key,
AlgorithmParameterSpec params) throws InvalidKeyException,
InvalidAlgorithmParameterException;
/**
* Initialize the block cipher with a secret key and parameters for data
* decryption.
*
* @param key
* the secret key
* @param params
* the parameters
* @throws InvalidKeyException
* if the given key is inappropriate for this cipher.
* @throws InvalidAlgorithmParameterException
* if the given parameters are inappropriate for this
* cipher.
*/
protected abstract void initCipherDecrypt(SecretKey key,
AlgorithmParameterSpec params) throws InvalidKeyException,
InvalidAlgorithmParameterException;
/**
* Encrypt a single block of data. It has to be assured that the array
* <tt>input</tt> contains a whole block starting at <tt>inOff</tt> and
* that <tt>out</tt> is large enough to hold an encrypted block starting
* at <tt>outOff</tt>.
*
* @param input
* array of bytes which contains the plaintext to be
* encrypted
* @param inOff
* index in array in, where the plaintext block starts
* @param output
* array of bytes which will contain the ciphertext startig
* at outOffset
* @param outOff
* index in array out, where the ciphertext block will start
*/
protected abstract void singleBlockEncrypt(byte[] input, int inOff,
byte[] output, int outOff);
/**
* Decrypt a single block of data. It has to be assured that the array
* <tt>input</tt> contains a whole block starting at <tt>inOff</tt> and
* that <tt>output</tt> is large enough to hold an decrypted block
* starting at <tt>outOff</tt>.
*
* @param input
* array of bytes which contains the ciphertext to be
* decrypted
* @param inOff
* index in array in, where the ciphertext block starts
* @param output
* array of bytes which will contain the plaintext starting
* at outOffset
* @param outOff
* index in array out, where the plaintext block will start
*/
protected abstract void singleBlockDecrypt(byte[] input, int inOff,
byte[] output, int outOff);
/**
* Check if mode and padding are set. If not, instantiate the default ones.
*/
private void initModeAndPadding() {
if (mode == null) {
mode = Registry.getMode();
mode.setBlockCipher(this);
}
if (paddingScheme == null) {
paddingScheme = Registry.getPaddingScheme();
}
}
}

View File

@@ -0,0 +1,729 @@
package de.flexiprovider.api;
import java.security.spec.InvalidParameterSpecException;
import de.flexiprovider.api.exceptions.BadPaddingException;
import de.flexiprovider.api.exceptions.IllegalBlockSizeException;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.InvalidKeyException;
import de.flexiprovider.api.exceptions.InvalidParameterException;
import de.flexiprovider.api.exceptions.NoSuchAlgorithmException;
import de.flexiprovider.api.exceptions.NoSuchModeException;
import de.flexiprovider.api.exceptions.NoSuchPaddingException;
import de.flexiprovider.api.exceptions.ShortBufferException;
import de.flexiprovider.api.keys.Key;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
import de.flexiprovider.api.parameters.AlgorithmParameters;
import de.flexiprovider.common.util.JavaSecureRandomWrapper;
public abstract class Cipher extends javax.crypto.CipherSpi {
/**
* Constant specifying encrypt mode.
*/
public static final int ENCRYPT_MODE = javax.crypto.Cipher.ENCRYPT_MODE;
/**
* Constant specifying decrypt mode.
*/
public static final int DECRYPT_MODE = javax.crypto.Cipher.DECRYPT_MODE;
/**
* The operation mode for this cipher ({@link #ENCRYPT_MODE} or
* {@link #DECRYPT_MODE}).
*/
protected int opMode;
// ****************************************************
// JCA adapter methods
// ****************************************************
/**
* Initialize this cipher object with a proper key and some random seed.
* Before a cipher object is ready for data processing, it has to be
* initialized according to the desired cryptographic operation, which is
* specified by the <tt>opMode</tt> parameter.
* <p>
* If this cipher (including its underlying mode or padding scheme) requires
* any random bytes, it will obtain them from <tt>random</tt>.
* <p>
* Note: If the mode needs an initialization vector, a blank array is used
* in this case.
*
* @param opMode
* the operation mode ({@link #ENCRYPT_MODE} or
* {@link #DECRYPT_MODE})
* @param key
* the key
* @param random
* the random seed
* @throws java.security.InvalidKeyException
* if the key is inappropriate for initializing this cipher.
*/
protected final void engineInit(int opMode, java.security.Key key,
java.security.SecureRandom random)
throws java.security.InvalidKeyException {
try {
engineInit(opMode, key,
(java.security.spec.AlgorithmParameterSpec) null, random);
} catch (java.security.InvalidAlgorithmParameterException e) {
throw new InvalidParameterException(e.getMessage());
}
}
/**
* Initialize this cipher with a key, a set of algorithm parameters, and a
* source of randomness. The cipher is initialized for encryption or
* decryption, depending on the value of <tt>opMode</tt>.
* <p>
* If this cipher (including its underlying mode or padding scheme) requires
* any random bytes, it will obtain them from <tt>random</tt>. Note that
* when a {@link BlockCipher} object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it.
* <p>
* Note: If the mode needs an initialization vector, a try to retrieve it
* from the AlgorithmParametersSpec is made.
*
* @param opMode
* the operation mode ({@link #ENCRYPT_MODE} or
* {@link #DECRYPT_MODE})
* @param key
* the key
* @param algParams
* the algorithm parameters
* @param random
* the random seed
* @throws java.security.InvalidKeyException
* if the key is inappropriate for initializing this block
* cipher.
* @throws java.security.InvalidAlgorithmParameterException
* if the parameters are inappropriate for initializing this
* block cipher.
*/
protected final void engineInit(int opMode, java.security.Key key,
java.security.AlgorithmParameters algParams,
java.security.SecureRandom random)
throws java.security.InvalidKeyException,
java.security.InvalidAlgorithmParameterException {
// if algParams are not specified, initialize without them
if (algParams == null) {
engineInit(opMode, key, random);
return;
}
java.security.spec.AlgorithmParameterSpec paramSpec = null;
try {
paramSpec = algParams.getParameterSpec(Registry
.getAlgParamSpecClass(algParams.getAlgorithm()));
} catch (NoSuchAlgorithmException e) {
throw new InvalidAlgorithmParameterException(
"Unknown algorithm parameters.");
} catch (InvalidParameterSpecException e) {
throw new RuntimeException(
"Internal error: invalid parameters type.");
}
engineInit(opMode, key, paramSpec, random);
}
/**
* Initialize this cipher with a key, a set of algorithm parameters, and a
* source of randomness. The cipher is initialized for one of the following
* four operations: encryption, decryption, key wrapping or key unwrapping,
* depending on the value of opMode. If this cipher (including its
* underlying feedback or padding scheme) requires any random bytes (e.g.,
* for parameter generation), it will get them from random. Note that when a
* Cipher object is initialized, it loses all previously-acquired state. In
* other words, initializing a Cipher is equivalent to creating a new
* instance of that Cipher and initializing it.
*
* @param opMode
* the operation mode ({@link #ENCRYPT_MODE} or
* {@link #DECRYPT_MODE})
* @param key
* the encryption key
* @param params
* the algorithm parameters
* @param javaRand
* the source of randomness
* @throws java.security.InvalidKeyException
* if the given key is inappropriate for initializing this
* cipher
* @throws java.security.InvalidAlgorithmParameterException
* if the given algorithm parameters are inappropriate for
* this cipher, or if this cipher is being initialized for
* decryption and requires algorithm parameters and the
* parameters are null.
*/
protected void engineInit(int opMode, java.security.Key key,
java.security.spec.AlgorithmParameterSpec params,
java.security.SecureRandom javaRand)
throws java.security.InvalidKeyException,
java.security.InvalidAlgorithmParameterException {
if ((params != null) && !(params instanceof AlgorithmParameterSpec)) {
throw new java.security.InvalidAlgorithmParameterException();
}
if ((key == null) || !(key instanceof Key)) {
throw new java.security.InvalidKeyException();
}
this.opMode = opMode;
if (opMode == ENCRYPT_MODE) {
SecureRandom flexiRand = new JavaSecureRandomWrapper(javaRand);
initEncrypt((Key) key, (AlgorithmParameterSpec) params, flexiRand);
} else if (opMode == DECRYPT_MODE) {
initDecrypt((Key) key, (AlgorithmParameterSpec) params);
}
}
/**
* Return the result of the last step of a multi-step en-/decryption
* operation or the result of a single-step en-/decryption operation by
* processing the given input data and any remaining buffered data. The data
* to be processed is given in an input byte array. Beginning at
* inputOffset, only the first inputLen bytes are en-/decrypted, including
* any buffered bytes of a previous update operation. If necessary, padding
* is performed. The result is returned as a output byte array.
*
* @param input
* the byte array holding the data to be processed
* @param inOff
* the offset indicating the start position within the input
* byte array
* @param inLen
* the number of bytes to be processed
* @return the byte array containing the en-/decrypted data
* @throws javax.crypto.IllegalBlockSizeException
* if the ciphertext length is not a multiple of the
* blocklength.
* @throws javax.crypto.BadPaddingException
* if unpadding is not possible.
*/
protected final byte[] engineDoFinal(byte[] input, int inOff, int inLen)
throws javax.crypto.IllegalBlockSizeException,
javax.crypto.BadPaddingException {
return doFinal(input, inOff, inLen);
}
/**
* Perform the last step of a multi-step en-/decryption operation or a
* single-step en-/decryption operation by processing the given input data
* and any remaining buffered data. The data to be processed is given in an
* input byte array. Beginning at inputOffset, only the first inputLen bytes
* are en-/decrypted, including any buffered bytes of a previous update
* operation. If necessary, padding is performed. The result is stored in
* the given output byte array, beginning at outputOffset. The number of
* bytes stored in this byte array are returned.
*
* @param input
* the byte array holding the data to be processed
* @param inOff
* the offset indicating the start position within the input
* byte array
* @param inLen
* the number of bytes to be processed
* @param output
* the byte array for holding the result
* @param outOff
* the offset indicating the start position within the output
* byte array to which the en/decrypted data is written
* @return the number of bytes stored in the output byte array
* @throws javax.crypto.ShortBufferException
* if the output buffer is too short to hold the output.
* @throws javax.crypto.IllegalBlockSizeException
* if the ciphertext length is not a multiple of the
* blocklength.
* @throws javax.crypto.BadPaddingException
* if unpadding is not possible.
*/
protected final int engineDoFinal(byte[] input, int inOff, int inLen,
byte[] output, int outOff)
throws javax.crypto.ShortBufferException,
javax.crypto.IllegalBlockSizeException,
javax.crypto.BadPaddingException {
return doFinal(input, inOff, inLen, output, outOff);
}
/**
* @return the block size (in bytes), or 0 if the underlying algorithm is
* not a block cipher
*/
protected final int engineGetBlockSize() {
return getBlockSize();
}
/**
* Return the key size of the given key object in bits.
*
* @param key
* the key object
* @return the key size in bits of the given key object
* @throws java.security.InvalidKeyException
* if key is invalid.
*/
protected final int engineGetKeySize(java.security.Key key)
throws java.security.InvalidKeyException {
if (!(key instanceof Key)) {
throw new java.security.InvalidKeyException("Unsupported key.");
}
return getKeySize((Key) key);
}
/**
* Return the initialization vector. This is useful in the context of
* password-based encryption or decryption, where the IV is derived from a
* user-provided passphrase.
*
* @return the initialization vector in a new buffer, or <tt>null</tt> if
* the underlying algorithm does not use an IV, or if the IV has not
* yet been set.
*/
protected final byte[] engineGetIV() {
return getIV();
}
/**
* Return the length in bytes that an output buffer would need to be in
* order to hold the result of the next update or doFinal operation, given
* the input length inputLen (in bytes).
* <p>
* This call takes into account any unprocessed (buffered) data from a
* previous update call, and padding.
* <p>
* The actual output length of the next update or doFinal call may be
* smaller than the length returned by this method.
*
* @param inLen
* the input length (in bytes)
* @return the required output buffer size (in bytes)
*/
protected final int engineGetOutputSize(int inLen) {
return getOutputSize(inLen);
}
/**
* Returns the parameters used with this cipher.
* <p>
* The returned parameters may be the same that were used to initialize this
* cipher, or may contain the default set of parameters or a set of randomly
* generated parameters used by the underlying cipher implementation
* (provided that the underlying cipher implementation uses a default set of
* parameters or creates new parameters if it needs parameters but was not
* initialized with any).
*
* @return the parameters used with this cipher, or null if this cipher does
* not use any parameters.
*/
protected final java.security.AlgorithmParameters engineGetParameters() {
final class JavaAlgorithmParameters extends
java.security.AlgorithmParameters {
JavaAlgorithmParameters(AlgorithmParameters params, String algName) {
super(params, null, algName);
}
}
String algName = getName();
AlgorithmParameters params;
try {
params = Registry.getAlgParams(algName);
} catch (NoSuchAlgorithmException e) {
return null;
}
JavaAlgorithmParameters algParams = new JavaAlgorithmParameters(params,
algName);
AlgorithmParameterSpec algParamSpec = getParameters();
if (algParamSpec == null) {
return null;
}
try {
algParams.init(algParamSpec);
} catch (java.security.spec.InvalidParameterSpecException ipse) {
throw new RuntimeException("InvalidParameterSpecException: "
+ ipse.getMessage());
}
return algParams;
}
/**
* Set the mode of this cipher.
*
* @param modeName
* the cipher mode
* @throws java.security.NoSuchAlgorithmException
* if neither the mode with the given name nor the default
* mode can be found
*/
protected final void engineSetMode(String modeName)
throws java.security.NoSuchAlgorithmException {
setMode(modeName);
}
/**
* Set the padding scheme of this cipher.
*
* @param paddingName
* the padding scheme
* @throws javax.crypto.NoSuchPaddingException
* if the requested padding scheme cannot be found.
*/
protected final void engineSetPadding(String paddingName)
throws javax.crypto.NoSuchPaddingException {
setPadding(paddingName);
}
/**
* Return the result of the next step of a multi-step en-/decryption
* operation. The data to be processed is given in an input byte array.
* Beginning at inputOffset, only the first inputLen bytes are
* en-/decrypted. The result is returned as a byte array.
*
* @param input
* the byte array holding the data to be processed
* @param inOff
* the offset indicating the start position within the input
* byte array
* @param inLen
* the number of bytes to be processed
* @return the byte array containing the en-/decrypted data
*/
protected final byte[] engineUpdate(byte[] input, int inOff, int inLen) {
return update(input, inOff, inLen);
}
/**
* Perform the next step of a multi-step en-/decryption operation. The data
* to be processed is given in an input byte array. Beginning at
* inputOffset, only the first inputLen bytes are en-/decrypted. The result
* is stored in the given output byte array, beginning at outputOffset. The
* number of bytes stored in this output byte array are returned.
*
* @param input
* the byte array holding the data to be processed
* @param inOff
* the offset indicating the start position within the input
* byte array
* @param inLen
* the number of bytes to be processed
* @param output
* the byte array for holding the result
* @param outOff
* the offset indicating the start position within the output
* byte array to which the en-/decrypted data is written
* @return the number of bytes that are stored in the output byte array
* @throws javax.crypto.ShortBufferException
* if the output buffer is too short to hold the output.
*/
protected final int engineUpdate(final byte[] input, final int inOff,
final int inLen, byte[] output, final int outOff)
throws javax.crypto.ShortBufferException {
return update(input, inOff, inLen, output, outOff);
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
/**
* Initialize this cipher with a key, a set of algorithm parameters, and a
* source of randomness for encryption.
* <p>
* If this cipher requires any algorithm parameters and paramSpec is null,
* the underlying cipher implementation is supposed to generate the required
* parameters itself (using provider-specific default or random values) if
* it is being initialized for encryption, and raise an
* InvalidAlgorithmParameterException if it is being initialized for
* decryption. The generated parameters can be retrieved using
* engineGetParameters or engineGetIV (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random.
* <p>
* Note that when a {@link BlockCipher} object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it.
*
* @param key
* the encryption key
* @param cipherParams
* the cipher parameters
* @param random
* the source of randomness
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* block cipher.
* @throws InvalidAlgorithmParameterException
* if the parameters are inappropriate for initializing this
* block cipher.
*/
public abstract void initEncrypt(Key key,
AlgorithmParameterSpec cipherParams, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Initialize this cipher with a key, a set of algorithm parameters, and a
* source of randomness for decryption.
* <p>
* If this cipher requires any algorithm parameters and paramSpec is null,
* the underlying cipher implementation is supposed to generate the required
* parameters itself (using provider-specific default or random values) if
* it is being initialized for encryption, and throw an
* {@link InvalidAlgorithmParameterException} if it is being initialized for
* decryption. The generated parameters can be retrieved using
* engineGetParameters or engineGetIV (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from random.
* <p>
* Note that when a {@link BlockCipher} object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it.
*
* @param key
* the encryption key
* @param cipherParams
* the cipher parameters
* @throws InvalidKeyException
* if the given key is inappropriate for initializing this
* block cipher.
* @throws InvalidAlgorithmParameterException
* if the parameters are inappropriate for initializing this
* block cipher.
*/
public abstract void initDecrypt(Key key,
AlgorithmParameterSpec cipherParams) throws InvalidKeyException,
InvalidAlgorithmParameterException;
/**
* @return the name of this cipher
*/
public abstract String getName();
/**
* @return the block size (in bytes), or 0 if the underlying algorithm is
* not a block cipher
*/
public abstract int getBlockSize();
/**
* Returns the length in bytes that an output buffer would need to be in
* order to hold the result of the next update or doFinal operation, given
* the input length inputLen (in bytes).
* <p>
* This call takes into account any unprocessed (buffered) data from a
* previous update call, and padding.
* <p>
* The actual output length of the next update or doFinal call may be
* smaller than the length returned by this method.
*
* @param inputLen
* the input length (in bytes)
* @return the required output buffer size (in bytes)
*/
public abstract int getOutputSize(int inputLen);
/**
* Return the key size of the given key object in bits.
*
* @param key
* the key object
* @return the key size in bits of the given key object
* @throws InvalidKeyException
* if key is invalid.
*/
public abstract int getKeySize(Key key) throws InvalidKeyException;
/**
* Returns the parameters used with this cipher.
* <p>
* The returned parameters may be the same that were used to initialize this
* cipher, or may contain the default set of parameters or a set of randomly
* generated parameters used by the underlying cipher implementation
* (provided that the underlying cipher implementation uses a default set of
* parameters or creates new parameters if it needs parameters but was not
* initialized with any).
*
* @return the parameters used with this cipher, or null if this cipher does
* not use any parameters.
*/
public abstract AlgorithmParameterSpec getParameters();
/**
* Return the initialization vector. This is useful in the context of
* password-based encryption or decryption, where the IV is derived from a
* user-provided passphrase.
*
* @return the initialization vector in a new buffer, or <tt>null</tt> if
* the underlying algorithm does not use an IV, or if the IV has not
* yet been set.
*/
public abstract byte[] getIV();
/**
* Set the mode of this cipher.
*
* @param mode
* the cipher mode
* @throws NoSuchModeException
* if the requested mode cannot be found.
*/
protected abstract void setMode(String mode) throws NoSuchModeException;
/**
* Set the padding mechanism of this cipher.
*
* @param padding
* the padding mechanism
* @throws NoSuchPaddingException
* if the requested padding scheme cannot be found.
*/
protected abstract void setPadding(String padding)
throws NoSuchPaddingException;
/**
* Continue a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized), processing another data part.
*
* @param input
* the input buffer
* @return a new buffer with the result (maybe an empty byte array)
*/
public final byte[] update(byte[] input) {
return update(input, 0, input.length);
}
/**
* Continue a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized), processing another data part.
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @return a new buffer with the result (maybe an empty byte array)
*/
public abstract byte[] update(byte[] input, int inOff, int inLen);
/**
* Continue a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized), processing another data part.
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @param output
* the output buffer
* @param outOff
* the offset where the result is stored
* @return the length of the output
* @throws ShortBufferException
* if the output buffer is too small to hold the result.
*/
public abstract int update(byte[] input, int inOff, int inLen,
byte[] output, int outOff) throws ShortBufferException;
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @return a new buffer with the result
* @throws IllegalBlockSizeException
* if this cipher is a block cipher and the total input
* length is not a multiple of the block size (for
* encryption when no padding is used or for decryption).
* @throws BadPaddingException
* if this cipher is a block cipher and unpadding fails.
*/
public final byte[] doFinal() throws IllegalBlockSizeException,
BadPaddingException {
return doFinal(null, 0, 0);
}
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @param input
* the input buffer
* @return a new buffer with the result
* @throws IllegalBlockSizeException
* if this cipher is a block cipher and the total input
* length is not a multiple of the block size (for
* encryption when no padding is used or for decryption).
* @throws BadPaddingException
* if this cipher is a block cipher and unpadding fails.
*/
public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException,
BadPaddingException {
return doFinal(input, 0, input.length);
}
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @return a new buffer with the result
* @throws IllegalBlockSizeException
* if this cipher is a block cipher and the total input
* length is not a multiple of the block size (for
* encryption when no padding is used or for decryption).
* @throws BadPaddingException
* if this cipher is a block cipher and unpadding fails.
*/
public abstract byte[] doFinal(byte[] input, int inOff, int inLen)
throws IllegalBlockSizeException, BadPaddingException;
/**
* Finish a multiple-part encryption or decryption operation (depending on
* how this cipher was initialized).
*
* @param input
* the input buffer
* @param inOff
* the offset where the input starts
* @param inLen
* the input length
* @param output
* the buffer for the result
* @param outOff
* the offset where the result is stored
* @return the output length
* @throws ShortBufferException
* if the output buffer is too small to hold the result.
* @throws IllegalBlockSizeException
* if this cipher is a block cipher and the total input
* length is not a multiple of the block size (for
* encryption when no padding is used or for decryption).
* @throws BadPaddingException
* if this cipher is a block cipher and unpadding fails.
*/
public abstract int doFinal(byte[] input, int inOff, int inLen,
byte[] output, int outOff) throws ShortBufferException,
IllegalBlockSizeException, BadPaddingException;
}

View File

@@ -0,0 +1,259 @@
package de.flexiprovider.api;
import javax.crypto.KeyAgreementSpi;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.InvalidKeyException;
import de.flexiprovider.api.exceptions.NoSuchAlgorithmException;
import de.flexiprovider.api.exceptions.ShortBufferException;
import de.flexiprovider.api.keys.Key;
import de.flexiprovider.api.keys.PrivateKey;
import de.flexiprovider.api.keys.PublicKey;
import de.flexiprovider.api.keys.SecretKey;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
import de.flexiprovider.common.util.JavaSecureRandomWrapper;
public abstract class KeyAgreement extends KeyAgreementSpi {
// ****************************************************
// JCA adapter methods
// ****************************************************
/**
* JCA adapter for FlexiAPI method init(): initialize this
* <tt>KeyAgreementSpi</tt> with a key and a source of randomness.
*
* @param key
* the secret key of the party initializing the key agreement
* @param javaRand
* the source of randomness
* @throws java.security.InvalidKeyException
* if the key is invalid.
* @throws RuntimeException
* if parameters are required for initialization.
*/
protected final void engineInit(java.security.Key key,
java.security.SecureRandom javaRand)
throws java.security.InvalidKeyException {
if (!(key instanceof PrivateKey)) {
throw new java.security.InvalidKeyException();
}
try {
SecureRandom flexiRand = new JavaSecureRandomWrapper(javaRand);
init((PrivateKey) key, (AlgorithmParameterSpec) null, flexiRand);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException("algorithm parameters required");
}
}
/**
* JCA adapter for FlexiAPI method init(): initialize this
* <tt>KeyAgreementSpi</tt> with a key, algorithm parameters, and a source
* of randomness.
*
* @param key
* the secret key of the party initializing the key agreement
* @param params
* the algorithm parameters
* @param javaRand
* the source of randomness
* @throws java.security.InvalidKeyException
* if the key is invalid.
* @throws java.security.InvalidAlgorithmParameterException
* if the parameters are invalid or null and parameters are
* needed for initialization.
*/
protected final void engineInit(java.security.Key key,
java.security.spec.AlgorithmParameterSpec params,
java.security.SecureRandom javaRand)
throws java.security.InvalidKeyException,
java.security.InvalidAlgorithmParameterException {
if (!(key instanceof PrivateKey)) {
throw new java.security.InvalidKeyException();
}
SecureRandom flexiRand = new JavaSecureRandomWrapper(javaRand);
init((PrivateKey) key, (AlgorithmParameterSpec) params, flexiRand);
}
/**
* JCA adapter for FlexiAPI method {@link #generateSecret()} : generate a
* shared secret and return it as a byte array.
*
* @return the shared secret as byte array.
* @throws IllegalStateException
* if the object is not in doPhase.
*/
protected final byte[] engineGenerateSecret() throws IllegalStateException {
return generateSecret();
}
/**
* JCA adapter for FlexiAPI method {@link #generateSecret(byte[], int)}:
* generate a shared secret and place it into the buffer
* <tt>sharedSecret</tt>, beginning at <tt>offset</tt>.
*
* @param sharedSecret
* the buffer to hold the shared secret
* @param offset
* the offset in <tt>sharedSecret</tt> where the shared
* secret will be stored
* @return the number of bytes written in <tt>sharedSecret</tt>
* @throws IllegalStateException
* if the key agreement scheme has not been initialized
* properly.
* @throws javax.crypto.ShortBufferException
* if <tt>sharedSecret</tt> is too small to to hold the
* shared secret
*/
protected final int engineGenerateSecret(byte[] sharedSecret, int offset)
throws IllegalStateException, javax.crypto.ShortBufferException {
return generateSecret(sharedSecret, offset);
}
/**
* JCA adapter for FlexiAPI method {@link #generateSecret(String)}:
* generate a shared secret via the algorithm specified in
* <tt>algorithm</tt>.
*
* @param algorithm
* the desired algorithm for the generation of the secret
* @return the shared secret
* @throws IllegalStateException
* if the key agreement scheme has not been initialized
* properly.
* @throws java.security.NoSuchAlgorithmException
* if <tt>algorithm</tt> is invalid.
*/
protected final javax.crypto.SecretKey engineGenerateSecret(String algorithm)
throws IllegalStateException,
java.security.NoSuchAlgorithmException {
return generateSecret(algorithm);
}
/**
* JCA adapter for FlexiAPI method {@link #doPhase(PublicKey, boolean)}:
* execute the next phase of this key agreement with the given key that was
* received from one of the other parties involved in this key agreement.
*
* @param key
* the public key of the other party
* @param lastPhase
* <tt>true</tt> if this is the last phase of the key
* agreement. After the last phase only
* <tt>generateSecret</tt> may be called.
* @return the shared secret
* @throws IllegalStateException
* if the key agreement scheme has not been initialized
* properly.
* @throws java.security.InvalidKeyException
* if the key is invalid.
*/
protected final java.security.Key engineDoPhase(java.security.Key key,
boolean lastPhase) throws java.security.InvalidKeyException,
IllegalStateException {
if (!(key instanceof PublicKey)) {
throw new java.security.InvalidKeyException();
}
return doPhase((PublicKey) key, lastPhase);
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
/**
* Initialize this key agreement with a private key, algorithm parameters,
* and a source of randomness.
*
* @param privKey
* the private key of the party initializing the key
* agreement
* @param params
* the algorithm parameters
* @param random
* the source of randomness
* @throws InvalidKeyException
* if the key is invalid.
* @throws InvalidAlgorithmParameterException
* if the parameters are invalid.
*/
public abstract void init(PrivateKey privKey,
AlgorithmParameterSpec params, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Generate a shared secret and return it as a byte array.
*
* @return the shared secret as byte array.
* @throws IllegalStateException
* if the key agreement scheme has not been initialized
* properly.
*/
public abstract byte[] generateSecret() throws IllegalStateException;
/**
* Generate a shared secret and place it into the buffer
* <tt>sharedSecret</tt>, beginning at <tt>offset</tt>.
*
* @param sharedSecret
* the buffer to hold the shared secret
* @param offset
* the offset in <tt>sharedSecret</tt> where the shared
* secret will be stored
* @return the number of bytes written in <tt>sharedSecret</tt>
* @throws IllegalStateException
* if the key agreement scheme has not been initialized
* properly.
* @throws ShortBufferException
* if <tt>sharedSecret</tt> is too small to to hold the
* shared secret
*/
public abstract int generateSecret(byte[] sharedSecret, int offset)
throws IllegalStateException, ShortBufferException;
/**
* Generate a shared secret via the algorithm specified in
* <tt>algorithm</tt>.
*
* @param algorithm
* the desired algorithm for the generation of the secret
* @return the shared secret
* @throws IllegalStateException
* if the key agreement scheme has not been initialized
* properly.
* @throws NoSuchAlgorithmException
* if <tt>algorithm</tt> is invalid.
*/
public abstract SecretKey generateSecret(String algorithm)
throws IllegalStateException, NoSuchAlgorithmException;
/**
* Execute the next phase of this key agreement with the given public key
* that was received from one of the other parties involved in this key
* agreement.
*
* @param pubKey
* the public key of the other party
* @param lastPhase
* <tt>true</tt> if this is the last phase of the key
* agreement. After the last phase only
* <tt>generateSecret</tt> may be called.
* @return the shared secret
* @throws IllegalStateException
* if the key agreement scheme has not been initialized
* properly.
* @throws InvalidKeyException
* if the key is invalid.
*/
public abstract Key doPhase(PublicKey pubKey, boolean lastPhase)
throws InvalidKeyException, IllegalStateException;
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 1998-2003 by The FlexiProvider Group,
* Technische Universitaet Darmstadt
*
* For conditions of usage and distribution please refer to the
* file COPYING in the root directory of this package.
*
*/
package de.flexiprovider.api;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.InvalidKeyException;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
/**
* This class defines a <b>key derivation function</b>. All the abstract
* methods in this class must be implemented by each cryptographic service
* provider who wishes to supply the implementation of a particular Key
* Derivation algorithm. A key derivation function is used to generate a longer
* or shorter secret key, with a second secret shared by both parties. The
* derived secret key may be used by other schemes which use different key
* length, to the normal secret keys.
*
* @author Jochen Hechler
* @author Marcus St<53>gbauer
* @author Martin D<>ring
*/
public abstract class KeyDerivation {
/**
* Initialize this KDF with a secret and parameters.
*
* @param secret
* the secret from which to derive the key
* @param params
* the parameters
* @throws InvalidKeyException
* if the secret is invalid.
* @throws InvalidAlgorithmParameterException
* if the parameters are invalid.
*/
public abstract void init(byte[] secret, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Start the derivation process and return the derived key. If supported by
* the concrete implementation, the derived key will be of the specified
* length.
*
* @param keySize
* the desired length of the derived key
* @return the derived key with the specified length, or <tt>null</tt> if
* the key size is <tt>&lt; 0</tt>.
*/
public abstract byte[] deriveKey(int keySize);
}

View File

@@ -0,0 +1,211 @@
package de.flexiprovider.api;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.InvalidKeyException;
import de.flexiprovider.api.exceptions.ShortBufferException;
import de.flexiprovider.api.keys.SecretKey;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
/**
* This class implements a "message authentication code" (MAC), a method to
* ensure the integrity of data transmitted between two parties who share a
* common secret key.
*
* <p>
* The best way to describe a MAC is as a <i>keyed one-way hash function</i>,
* which looks like:
*
* <blockquote>
* <p>
* <tt>D = MAC(K, M)</tt></blockquote>
*
* <p>
* where <tt>K</tt> is the key, <tt>M</tt> is the message, and <tt>D</tt>
* is the resulting digest. One party will usually send the concatenation
* <tt>M || D</tt> to the other party, who will then verify <tt>D</tt> by
* computing <tt>D'</tt> in a similar fashion. If <tt>D == D'</tt>, then
* the message is assumed to be authentic.
*
* @author Martin D<>ring, Johannes M<>ller
*/
public abstract class Mac extends javax.crypto.MacSpi {
// ****************************************************
// JCA adapter methods
// ****************************************************
protected final int engineGetMacLength() {
return getMacLength();
}
protected void engineInit(java.security.Key key,
java.security.spec.AlgorithmParameterSpec params)
throws java.security.InvalidKeyException,
java.security.InvalidAlgorithmParameterException {
if (!(key instanceof SecretKey)) {
throw new java.security.InvalidKeyException();
}
if ((params != null) && !(params instanceof AlgorithmParameterSpec)) {
throw new java.security.InvalidAlgorithmParameterException();
}
init((SecretKey) key, (AlgorithmParameterSpec) params);
}
protected final void engineUpdate(byte input) {
update(input);
}
protected final void engineUpdate(byte[] input, int offset, int len) {
update(input, offset, len);
}
protected final byte[] engineDoFinal() {
return doFinal();
}
protected final void engineReset() {
reset();
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
/**
* Return the MAC length. This method is guaranteed to return a sane value
* only after the MAC has been initialized.
*
* @return the MAC length
*/
public abstract int getMacLength();
/**
* Initialize this MAC with a key and no parameters.
*
* @param key
* The key to initialize this instance with.
* @throws InvalidKeyException
* If the key is unacceptable.
*/
public final void init(SecretKey key) throws InvalidKeyException {
try {
init(key, null);
} catch (InvalidAlgorithmParameterException iape) {
throw new IllegalArgumentException("This MAC needs parameters");
}
}
/**
* Initialize this MAC with a key and parameters.
*
* @param key
* The key to initialize this instance with.
* @param params
* The algorithm-specific parameters.
* @throws InvalidAlgorithmParameterException
* If the algorithm parameters are unacceptable.
* @throws InvalidKeyException
* If the key is unacceptable.
*/
public abstract void init(SecretKey key, AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException, InvalidKeyException;
/**
* Update the computation with a single byte.
*
* @param input
* The next byte.
*/
public abstract void update(byte input);
/**
* Update the computation with a byte array.
*
* @param input
* The next bytes.
*/
public final void update(byte[] input) {
update(input, 0, input.length);
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
/**
* Update the computation with a portion of a byte array.
*
* @param input
* The next bytes.
* @param offset
* The index in <tt>input</tt> to start.
* @param length
* The number of bytes to update.
*/
public abstract void update(byte[] input, int offset, int length);
/**
* Finishes the computation of a MAC and returns the digest.
*
* <p>
* After this method succeeds, it may be used again as just after a call to
* <tt>init</tt>, and can compute another MAC using the same key and
* parameters.
*
* @return The message authentication code.
*/
public abstract byte[] doFinal();
/**
* Finishes the computation of a MAC with a final byte array (or computes a
* MAC over those bytes only) and returns the digest.
*
* <p>
* After this method succeeds, it may be used again as just after a call to
* <tt>init</tt>, and can compute another MAC using the same key and
* parameters.
*
* @param input
* The bytes to add.
* @return The message authentication code.
*/
public final byte[] doFinal(byte[] input) {
update(input);
return doFinal();
}
/**
* Finishes the computation of a MAC and places the result into the given
* array.
* <p>
* After this method succeeds, it may be used again as just after a call to
* <tt>init</tt>, and can compute another MAC using the same key and
* parameters.
*
* @param output
* The destination for the result.
* @param outOffset
* The index in the output array to start.
* @return the number of bytes stored in output.
* @throws ShortBufferException
* If <tt>output</tt> is not large enough to hold the
* result.
*/
public final int doFinal(byte[] output, int outOffset)
throws ShortBufferException {
if (output.length - outOffset < getMacLength()) {
throw new ShortBufferException();
}
byte[] mac = doFinal();
System.arraycopy(mac, 0, output, outOffset, mac.length);
return mac.length;
}
/**
* Reset this instance. A call to this method returns this instance back to
* the state it was in just after it was initialized.
*/
public abstract void reset();
}

View File

@@ -0,0 +1,143 @@
package de.flexiprovider.api;
import de.flexiprovider.api.exceptions.DigestException;
public abstract class MessageDigest extends java.security.MessageDigestSpi {
// ****************************************************
// JCA adapter methods
// ****************************************************
protected final int engineGetDigestLength() {
return getDigestLength();
}
protected final void engineUpdate(byte input) {
update(input);
}
protected final void engineUpdate(byte[] input, int offset, int len) {
update(input, offset, len);
}
protected final byte[] engineDigest() {
return digest();
}
protected final void engineReset() {
reset();
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
/**
* @return the digest length in bytes
*/
public abstract int getDigestLength();
/**
* Update the digest using the specified byte.
*
* @param input
* the byte to use for the update
*/
public abstract void update(byte input);
/**
* Update the digest using the specified array of bytes, starting at the
* specified offset.
*
* @param input
* the array of bytes to use for the update
*/
public final void update(byte[] input) {
if (input == null) {
return;
}
update(input, 0, input.length);
}
/**
* Update the digest using the specified array of bytes, starting at the
* specified offset.
*
* @param input
* the array of bytes to use for the update
* @param offset
* the offset to start from in the array of bytes
* @param len
* the number of bytes to use, starting at <tt>offset</tt>
*/
public abstract void update(byte[] input, int offset, int len);
/**
* Complete the hash computation by performing final operations such as
* padding. Once {@link #digest()} has been called, the engine should be
* reset (see {@link #reset()}). Resetting is the responsibility of the
* engine implementor.
*
* @return the array of bytes for the resulting hash value.
*/
public abstract byte[] digest();
/**
* Update the digest and complete the hash computation by performing final
* operations such as padding. Once {@link #digest(byte[])} has been called,
* the engine should be reset (see {@link #reset()}). Resetting is the
* responsibility of the engine implementor.
*
* @param input
* the array of bytes to use for the update
* @return the array of bytes for the resulting hash value
*/
public final byte[] digest(byte[] input) {
update(input);
return digest();
}
/**
* Complete the hash computation by performing final operations such as
* padding. Once {@link #digest(byte[], int, int)} has been called, the
* engine should be reset (see {@link #reset()}). Resetting is the
* responsibility of the engine implementor.
*
* @param buf
* the output buffer in which to store the digest
* @param offset
* offset to start from in the output buffer
* @param len
* number of bytes within buf allotted for the digest. Both
* this default implementation and the SUN provider do not
* return partial digests. The presence of this parameter is
* solely for consistency in our API's. If the value of this
* parameter is less than the actual digest length, the
* method will throw a DigestException. This parameter is
* ignored if its value is greater than or equal to the
* actual digest length.
* @return the length of the digest stored in the output buffer.
* @throws DigestException
* if an error occurs.
*/
public final int digest(byte[] buf, int offset, int len)
throws DigestException {
byte[] digest = digest();
if (len < digest.length) {
throw new DigestException("partial digests not returned");
}
if (buf.length - offset < digest.length) {
throw new DigestException("insufficient space in the output "
+ "buffer to store the digest");
}
System.arraycopy(digest, 0, buf, offset, digest.length);
return digest.length;
}
/**
* Reset the digest for further use.
*/
public abstract void reset();
}

View File

@@ -0,0 +1,236 @@
/*
* Copyright (c) 1998-2003 by The FlexiProvider Group,
* Technische Universitaet Darmstadt
*
* For conditions of usage and distribution please refer to the
* file COPYING in the root directory of this package.
*
*/
package de.flexiprovider.api;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.InvalidKeyException;
import de.flexiprovider.api.keys.SecretKey;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
import de.flexiprovider.common.mode.ModeParameterSpec;
/**
* The abstract class Mode is the base for all modes implemented in the package
* cdc. It defines the set of methods which have to be implemented to cooperate
* with the BasicCipher class. Each class that implements such a mode has to
* exist in the package "de.flexiprovider.common.mode" and the classname must be
* the same as the name used in the call of <tt>Cipher.getInstance()</tt>.
* e.g. if you call <tt>Cipher.getInstance("SAFER+/CBC/NoPadding")</tt>, the
* code will look for the class de.flexiprovider.common.mode.CBC
*
* @author Marcus Lippert
* @author Ralf-Philipp Weinmann
*/
public abstract class Mode {
/**
* Reference to the underlying block cipher
*/
private BlockCipher blockCipher;
/**
* The initialization vector
*/
protected byte[] iv;
/**
* The block size of the mode
*/
protected int blockSize;
/**
* Set the {@link BlockCipher} to use with this mode.
*
* @param blockCipher
* the block cipher
*/
final void setBlockCipher(BlockCipher blockCipher) {
this.blockCipher = blockCipher;
}
/*---------------------------------------------------
* Mode specific abstract methods
---------------------------------------------------*/
/**
* Initialize the Mode object for encryption and compute the mode block
* size. This value usually depends on the block size of the used block
* cipher. It is supposed that all block ciphers return a sane value via
* {@link BlockCipher#getCipherBlockSize()} after initialization.
*
* @param key
* the key used for encryption
* @param modeParams
* additional mode parameters
* @param cipherParams
* additional algorithm parameters
* @throws InvalidKeyException
* if the key is inappropriate for initializing the
* underlying block cipher.
* @throws InvalidAlgorithmParameterException
* if the parameters are inappropriate for initializing the
* underlying block cipher.
*/
protected abstract void initEncrypt(SecretKey key,
ModeParameterSpec modeParams, AlgorithmParameterSpec cipherParams)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Initialize the Mode object for decryption and compute the mode block
* size. This value usually depends on the block size of the used block
* cipher. It is supposed that all block ciphers return a sane value via
* {@link BlockCipher#getCipherBlockSize()} after initialization.
*
* @param key
* the key used for decryption
* @param modeParams
* additional mode parameters
* @param cipherParams
* additional algorithm parameters
* @throws InvalidKeyException
* if the key is inappropriate for initializing the
* underlying block cipher.
* @throws InvalidAlgorithmParameterException
* if the parameters are inappropriate for initializing the
* underlying block cipher.
*/
protected abstract void initDecrypt(SecretKey key,
ModeParameterSpec modeParams, AlgorithmParameterSpec cipherParams)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Encrypt the next data block. Any special features of the Mode should be
* implemented here.
*
* @param input
* input data buffer
* @param inOff
* input data offset
* @param output
* output data buffer
* @param outOff
* output data offset
*/
protected abstract void nextChunkEncrypt(final byte[] input,
final int inOff, byte[] output, final int outOff);
/**
* Decrypt the next data block. Any special features of the Mode should be
* implemented here.
*
* @param input
* input data buffer
* @param inOff
* input data offset
* @param output
* output data buffer
* @param outOff
* output data offset
*/
protected abstract void nextChunkDecrypt(final byte[] input,
final int inOff, byte[] output, final int outOff);
/**
* reset() is called after doFinal() in order to prepare the mode for the
* next operation.
*/
protected abstract void reset();
/*---------------------------------------------------
* Adapter classes to BlockCipher
---------------------------------------------------*/
/**
* Initialize the block cipher for encryption.
*
* @param key
* the secret key to use for encryption
* @param cipherParams
* the parameters
* @throws InvalidKeyException
* if the given key is inappropriate for this cipher.
* @throws InvalidAlgorithmParameterException
* if the given parameters are inappropriate for this
* cipher.
*/
protected final void initCipherEncrypt(SecretKey key,
AlgorithmParameterSpec cipherParams) throws InvalidKeyException,
InvalidAlgorithmParameterException {
blockCipher.initCipherEncrypt(key, cipherParams);
}
/**
* Initialize the block cipher for decryption.
*
* @param key
* the secret key to use for decryption
* @param cipherParams
* the parameters
* @throws InvalidKeyException
* if the given key is inappropriate for this cipher.
* @throws InvalidAlgorithmParameterException
* if the given parameters are inappropriate for this
* cipher.
*/
protected final void initCipherDecrypt(SecretKey key,
AlgorithmParameterSpec cipherParams) throws InvalidKeyException,
InvalidAlgorithmParameterException {
blockCipher.initCipherDecrypt(key, cipherParams);
}
/**
* Return the block size of the underlying cipher. It is supposed that all
* block ciphers return a sane value via
* {@link BlockCipher#getCipherBlockSize()} after initialization.
*
* @return the block size of the underlying cipher
*/
protected final int getCipherBlockSize() {
return blockCipher.getCipherBlockSize();
}
/**
* Encrypt a single block with the cipher engine.
*
* @param input
* array of bytes which contains the plaintext to be
* encrypted
* @param inOff
* index in array in, where the plaintext block starts
* @param output
* array of bytes which will contain the ciphertext startig
* at outOffset
* @param outOff
* index in array out, where the ciphertext block will start
*/
protected final void singleBlockEncrypt(byte[] input, int inOff,
byte[] output, int outOff) {
blockCipher.singleBlockEncrypt(input, inOff, output, outOff);
}
/**
* Decrypt a single block with the cipher engine.
*
* @param input
* array of bytes which contains the ciphertext to be
* decrypted
* @param inOff
* index in array in, where the ciphertext block starts
* @param output
* array of bytes which will contain the plaintext starting
* at outOffset
* @param outOff
* index in array out, where the plaintext block will start
*/
protected final void singleBlockDecrypt(byte[] input, int inOff,
byte[] output, int outOff) {
blockCipher.singleBlockDecrypt(input, inOff, output, outOff);
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 1998-2003 by The FlexiProvider Group,
* Technische Universitaet Darmstadt
*
* For conditions of usage and distribution please refer to the
* file COPYING in the root directory of this package.
*
*/
package de.flexiprovider.api;
import de.flexiprovider.api.exceptions.BadPaddingException;
/**
* To encrypt a plaintext with a block cipher the input is divided into blocks
* whose length depends on the encryption algorithm used. To ensure that the
* block size will divide the length of the input, the last block is padded to
* the needed length. Vice versa, when decrypting a ciphertext, the padding has
* to be removed.
* <p>
* To make a new padding scheme available, one has to write a subclass of
* <tt>de.flexiprovider.common.padding.PaddingScheme</tt> in order to allow a
* blockcipher to use it. This subclass has to exist in the package
* <tt>de.flexiprovider.common.padding</tt> and the class name must be the
* same as the name used in the call of Cipher.getInstance(). E.g., if you call
* Cipher.getInstance("SAFER+/CBC/NoPadding"), then there must exist a class
* <tt>de.flexiprovider.common.padding.NoPadding</tt>.
*
* @author Christoph Ender
* @author Christoph Sesterhenn
* @author Marcus Lippert
* @author Martin Strese
*/
public abstract class PaddingScheme {
/**
* Block size used for padding
*/
protected int blockSize = -1;
/**
* Tell the padding scheme the block size to which input will be padded.
*
* @param blockSize
* length of one block
*/
final void setBlockSize(int blockSize) {
if (blockSize > 0) {
this.blockSize = blockSize;
}
}
/**
* Return the number of bytes which will be appended to the the plaintext
* during padding.
*
* @param inLen
* the length of the plaintext to be padded
* @return the number of padding bytes (may be 0)
*/
protected abstract int padLength(int inLen);
/**
* Pad the input to make its length divisible by the the block length. The
* padding is written to the same buffer which is used for input. The caller
* has to ensure that the input array is large enough to hold the padding
* bytes.
*
* @param input
* byte array containing the plaintext to be padded
* @param inOff
* index where the plaintext starts
* @param inLen
* length of the plaintext
* @throws BadPaddingException
* if the input buffer is too small to hold the padding
* bytes.
*/
protected abstract void pad(byte[] input, int inOff, int inLen)
throws BadPaddingException;
/**
* Given the plaintext that includes the padding bytes, unpad the plaintext
* and return the index indicating where the padding bytes start.
*
* @param input
* byte array containing the padded plaintext
* @param inOff
* index where the plaintext starts
* @param inLen
* size of the plaintext
* @return index in the array where the padding bytes start
* @throws BadPaddingException
* if unpadding fails.
*/
protected abstract int unpad(byte[] input, int inOff, int inLen)
throws BadPaddingException;
}

View File

@@ -0,0 +1,804 @@
package de.flexiprovider.api;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.NoSuchAlgorithmException;
import de.flexiprovider.api.exceptions.NoSuchModeException;
import de.flexiprovider.api.exceptions.NoSuchPaddingException;
import de.flexiprovider.api.exceptions.RegistrationException;
import de.flexiprovider.api.keys.KeyFactory;
import de.flexiprovider.api.keys.KeyPairGenerator;
import de.flexiprovider.api.keys.SecretKeyFactory;
import de.flexiprovider.api.keys.SecretKeyGenerator;
import de.flexiprovider.api.parameters.AlgorithmParameterGenerator;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
import de.flexiprovider.api.parameters.AlgorithmParameters;
import de.flexiprovider.common.mode.CBC;
import de.flexiprovider.common.mode.CFB;
import de.flexiprovider.common.mode.CFBParameterSpec;
import de.flexiprovider.common.mode.CTR;
import de.flexiprovider.common.mode.ECB;
import de.flexiprovider.common.mode.ModeParamGenParameterSpec;
import de.flexiprovider.common.mode.ModeParameterGenerator;
import de.flexiprovider.common.mode.ModeParameterSpec;
import de.flexiprovider.common.mode.ModeParameters;
import de.flexiprovider.common.mode.OFB;
import de.flexiprovider.common.mode.OFBParameterSpec;
import de.flexiprovider.common.padding.NoPadding;
import de.flexiprovider.common.padding.OneAndZeroesPadding;
import de.flexiprovider.common.padding.PKCS5Padding;
import de.flexiprovider.common.util.DefaultPRNG;
/**
* This class is responsible for the registration and instantiation of all
* cryptographic algorithms of the FlexiProvider. It provides methods for adding
* registrations of algorithms and methods for instantiating registered
* algorithms.
*
* @author Johannes M<>ller
* @author Martin D<>ring
*/
public abstract class Registry {
/* algorithm type constants */
/**
* Constant for asymmetric block ciphers
*/
public static final int ASYMMETRIC_BLOCK_CIPHER = 0;
/**
* Constant for asymmetric hybrid ciphers
*/
public static final int ASYMMETRIC_HYBRID_CIPHER = 1;
/**
* Constant for symmetric block ciphers
*/
public static final int BLOCK_CIPHER = 2;
/**
* Constant for modes of operation
*/
public static final int MODE = 3;
/**
* Constant for padding schemes
*/
public static final int PADDING_SCHEME = 4;
/**
* Constant for generic ciphers
*/
public static final int CIPHER = 5;
/**
* Constant for message authentication codes (MACs)
*/
public static final int MAC = 6;
/**
* Constant for message digests (hash functions)
*/
public static final int MESSAGE_DIGEST = 7;
/**
* Constant for PRNGs
*/
public static final int SECURE_RANDOM = 8;
/**
* Constant for digital signatures
*/
public static final int SIGNATURE = 9;
/**
* Constant for algorithm parameter specifications
*/
public static final int ALG_PARAM_SPEC = 10;
/**
* Constant for algorithm parameters (used to encode and decode parameter
* specifications)
*/
public static final int ALG_PARAMS = 11;
/**
* Constant for algorithm parameter generators
*/
public static final int ALG_PARAM_GENERATOR = 12;
/**
* Constant for secret key generators
*/
public static final int SECRET_KEY_GENERATOR = 13;
/**
* Constant for key pair generators
*/
public static final int KEY_PAIR_GENERATOR = 14;
/**
* Constant for secret key factories
*/
public static final int SECRET_KEY_FACTORY = 15;
/**
* Constant for key factories
*/
public static final int KEY_FACTORY = 16;
/**
* Constant for key derivations
*/
public static final int KEY_DERIVATION = 17;
/**
* Constant for key agreements
*/
public static final int KEY_AGREEMENT = 18;
/* hash tables for the different algorithm types */
private static final Hashtable asymBlockCiphers = new Hashtable();
private static final Hashtable asymHybridCiphers = new Hashtable();
private static final Hashtable blockCiphers = new Hashtable();
private static final Hashtable modes = new Hashtable();
private static final Hashtable paddingSchemes = new Hashtable();
private static final Hashtable ciphers = new Hashtable();
private static final Hashtable macs = new Hashtable();
private static final Hashtable messageDigests = new Hashtable();
private static final Hashtable secureRandoms = new Hashtable();
private static final Hashtable signatures = new Hashtable();
private static final Hashtable algParamSpecs = new Hashtable();
private static final Hashtable algParams = new Hashtable();
private static final Hashtable algParamGenerators = new Hashtable();
private static final Hashtable secretKeyGenerators = new Hashtable();
private static final Hashtable keyPairGenerators = new Hashtable();
private static final Hashtable secretKeyFactories = new Hashtable();
private static final Hashtable keyFactories = new Hashtable();
private static final Hashtable keyDerivations = new Hashtable();
private static final Hashtable keyAgreements = new Hashtable();
// array holding all hash tables (indexed by algorithm type)
private static final Hashtable[] hashtables = { asymBlockCiphers,
asymHybridCiphers, blockCiphers, modes, paddingSchemes, ciphers,
macs, messageDigests, secureRandoms, signatures, algParamSpecs,
algParams, algParamGenerators, secretKeyGenerators,
keyPairGenerators, secretKeyFactories, keyFactories,
keyDerivations, keyAgreements };
// array holding all algorithm types (used for registration type checking)
private static final Class[] algClasses = { AsymmetricBlockCipher.class,
AsymmetricHybridCipher.class, BlockCipher.class, Mode.class,
PaddingScheme.class, Cipher.class, Mac.class, MessageDigest.class,
SecureRandom.class, Signature.class, AlgorithmParameterSpec.class,
AlgorithmParameters.class, AlgorithmParameterGenerator.class,
SecretKeyGenerator.class, KeyPairGenerator.class,
SecretKeyFactory.class, KeyFactory.class, KeyDerivation.class,
KeyAgreement.class };
// hash table for standard algorithm parameters
private static final Hashtable standardAlgParams = new Hashtable();
static {
add(ALG_PARAM_SPEC, CFBParameterSpec.class, "CFB");
add(ALG_PARAM_SPEC, OFBParameterSpec.class, "OFB");
add(ALG_PARAM_SPEC, ModeParameterSpec.class, new String[] { "Mode",
"IV" });
add(ALG_PARAMS, ModeParameters.class, new String[] { "Mode", "IV" });
add(ALG_PARAM_SPEC, ModeParamGenParameterSpec.class, new String[] {
"ModeParamGen", "IVParamGen" });
add(ALG_PARAM_GENERATOR, ModeParameterGenerator.class, new String[] {
"Mode", "IV" });
add(MODE, ECB.class, "ECB");
add(MODE, CBC.class, "CBC");
add(MODE, OFB.class, "OFB");
add(MODE, CFB.class, "CFB");
add(MODE, CTR.class, "CTR");
add(PADDING_SCHEME, NoPadding.class, "NoPadding");
add(PADDING_SCHEME, OneAndZeroesPadding.class, "OneAndZeroesPadding");
add(PADDING_SCHEME, PKCS5Padding.class, "PKCS5Padding");
}
/**
* Register an algorithm of the given type under the given name.
*
* @param type
* the algorithm type
* @param algClass
* the class implementing the algorithm
* @param algName
* the name for the algorithm
* @throws RegistrationException
* if the expected and actual algorithm types do not match or an
* algorithm is already registered under the given name.
*/
public static final void add(int type, Class algClass, String algName) {
add(type, algClass, new String[] { algName });
}
/**
* Register an algorithm of the given type under the given names.
*
* @param type
* the algorithm type
* @param algClass
* the class implementing the algorithm
* @param algNames
* the names for the algorithm
* @throws RegistrationException
* if the expected and actual algorithm types do not match or an
* algorithm is already registered under one of the given names.
*/
public static final void add(int type, Class algClass, String[] algNames) {
Hashtable table = getHashtable(type);
// trivial cases
if ((table == null) || (algClass == null) || (algNames == null)
|| (algNames.length == 0)) {
return;
}
// type checking
Class expClass = algClasses[type];
if (!expClass.isAssignableFrom(algClass)) {
throw new RegistrationException(
"expected and actual algorithm types do not match");
}
// register first name
table.put(algNames[0], algClass);
// register additional names (aliases)
for (int i = 1; i < algNames.length; i++) {
table.put(algNames[i], algNames[0]);
}
}
/**
* Return all algorithms of the given type.
*
* @param type
* the algorithm type
* @return an {@link Enumeration} of all algorithms contained in the hash
* table
*/
public static final Enumeration getAlgorithms(int type) {
Hashtable table = getHashtable(type);
if (table == null) {
return null;
}
return table.keys();
}
/**
* Return all names of the given algorithm and type.
*
* @param type
* the algorithm type
* @param name
* (one of the) names of the algorithm
* @return a {@link Vector} containing all names of the algorithm
*/
public static final Vector getNames(int type, String name) {
Hashtable table = getHashtable(type);
if (table == null) {
return null;
}
Enumeration algorithms = getAlgorithms(type);
Object target = resolveAlias(table, name);
Vector result = new Vector();
while (algorithms.hasMoreElements()) {
String key = (String) algorithms.nextElement();
if (resolveAlias(table, key).equals(target)) {
result.addElement(key);
}
}
return result;
}
/**
* Return an instance of the specified asymmetric block cipher.
*
* @param algName
* the name of the asymmetric block cipher
* @return a new {@link AsymmetricBlockCipher} object implementing the
* chosen algorithm
* @throws NoSuchAlgorithmException
* if the asymmetric block cipher cannot be found.
*/
public static final AsymmetricBlockCipher getAsymmetricBlockCipher(
String algName) throws NoSuchAlgorithmException {
return (AsymmetricBlockCipher) getInstance(asymBlockCiphers, algName);
}
/**
* Return an instance of the specified asymmetric hybrid cipher.
*
* @param algName
* the name of the asymmetric hybrid cipher
* @return a new {@link AsymmetricHybridCipher} object implementing the
* chosen algorithm
* @throws NoSuchAlgorithmException
* if the asymmetric hybrid cipher cannot be found.
*/
public static final AsymmetricHybridCipher getAsymmetricHybridCipher(
String algName) throws NoSuchAlgorithmException {
return (AsymmetricHybridCipher) getInstance(asymHybridCiphers, algName);
}
/**
* Try to find an algorithm with the specified name inside the corresponding
* hashtable and return an instance of the algorithm.
*
* @param transformation
* the transformation (either of the form 'algorithm' or
* 'algorithm/mode/padding')
* @return block cipher object
* @throws NoSuchAlgorithmException
* if the block cipher or mode cannot be found.
* @throws NoSuchPaddingException
* if the padding scheme cannot be found.
*/
public static final BlockCipher getBlockCipher(String transformation)
throws NoSuchAlgorithmException, NoSuchPaddingException {
String algName, modeName = null, paddingName = null;
int endIndex = transformation.indexOf('/');
if (endIndex < 0) {
// transformation is of the form 'algorithm'
algName = transformation;
} else {
// transformation is of the form 'algorithm/mode/padding'
// get 'algorithm'
algName = transformation.substring(0, endIndex);
// get 'mode/padding'
String modePadding = transformation.substring(endIndex + 1);
endIndex = modePadding.indexOf("/");
if (endIndex == -1) {
// if no padding is specified
throw new NoSuchAlgorithmException(
"Badly formed transformation: only 'algorithm' "
+ "or 'algorithm/mode/padding' allowed.");
}
// get 'mode'
modeName = modePadding.substring(0, endIndex);
// get 'padding'
paddingName = modePadding.substring(endIndex + 1);
// if even more information is provided, transformation is invalid
if (paddingName.indexOf("/") != -1) {
throw new NoSuchAlgorithmException(
"Badly formed transformation: only 'algorithm' "
+ "or 'algorithm/mode/padding' allowed.");
}
}
BlockCipher result = (BlockCipher) getInstance(blockCiphers, algName);
if(modeName != null)
result.setMode(modeName);
if(paddingName != null)
result.setPadding(paddingName);
return result;
}
/**
* @return an instance of the default mode (CBC)
*/
protected static final Mode getMode() {
return new CBC();
}
/**
* Return an instance of the specified mode.
*
* @param modeName
* the name of the mode
* @return a new {@link Mode} object implementing the chosen algorithm
* @throws NoSuchModeException
* if the mode cannot be found.
*/
protected static final Mode getMode(String modeName)
throws NoSuchModeException {
try {
return (Mode) getInstance(modes, modeName);
} catch (NoSuchAlgorithmException e) {
throw new NoSuchModeException(e.getMessage());
}
}
/**
* @return an instance of the default padding scheme (PKCS5Padding)
*/
protected static final PaddingScheme getPaddingScheme() {
return new PKCS5Padding();
}
/**
* Return an instance of the specified padding scheme.
*
* @param paddingName
* the name of the padding scheme
* @return a new {@link PaddingScheme} object implementing the chosen
* algorithm
* @throws NoSuchPaddingException
* if the padding scheme cannot be found.
*/
protected static final PaddingScheme getPaddingScheme(String paddingName)
throws NoSuchPaddingException {
try {
return (PaddingScheme) getInstance(paddingSchemes, paddingName);
} catch (NoSuchAlgorithmException e) {
throw new NoSuchPaddingException(e.getMessage());
}
}
/**
* Return an instance of the specified cipher.
*
* @param algName
* the name of the cipher
* @return a new {@link Cipher} object implementing the chosen algorithm
* @throws NoSuchAlgorithmException
* if the cipher cannot be found.
*/
public static final Cipher getCipher(String algName)
throws NoSuchAlgorithmException {
return (Cipher) getInstance(ciphers, algName);
}
/**
* Return an instance of the specified message authentication code (MAC).
*
* @param algName
* the name of the MAC
* @return a new {@link Mac} object implementing the chosen algorithm
* @throws NoSuchAlgorithmException
* if the MAC cannot be found.
*/
public static final Mac getMAC(String algName)
throws NoSuchAlgorithmException {
return (Mac) getInstance(macs, algName);
}
/**
* Return an instance of the specified message digest.
*
* @param algName
* the name of the message digest
* @return a new {@link MessageDigest} object implementing the chosen
* algorithm
* @throws NoSuchAlgorithmException
* if the message digest cannot be found.
*/
public static final MessageDigest getMessageDigest(String algName)
throws NoSuchAlgorithmException {
return (MessageDigest) getInstance(messageDigests, algName);
}
/**
* Return an instance of the specified source of randomness.
*
* @param algName
* the name of the source of randomness
* @return a new {@link SecureRandom} object implementing the chosen
* algorithm
* @throws NoSuchAlgorithmException
* if the source of randomness cannot be found.
*/
public static final SecureRandom getSecureRandom(String algName)
throws NoSuchAlgorithmException {
return (SecureRandom) getInstance(secureRandoms, algName);
}
/**
* @return the default secure random
* @throws RuntimeException
* if the default secure random cannot be instantiated.
*/
public static final SecureRandom getSecureRandom() {
return new DefaultPRNG();
}
/**
* Return an instance of the specified signature.
*
* @param algName
* the name of the signature
* @return a new {@link Signature} object implementing the chosen algorithm
* @throws NoSuchAlgorithmException
* if the signature cannot be found.
*/
public static final Signature getSignature(String algName)
throws NoSuchAlgorithmException {
return (Signature) getInstance(signatures, algName);
}
/**
* Return the algorithm parameter specification class corresponding to the
* given algorithm name.
*
* @param algName
* the algorithm name
* @return the corresponding algorithm parameter specification class
* @throws NoSuchAlgorithmException
* if the parameters class cannot be found.
*/
public static final Class getAlgParamSpecClass(String algName)
throws NoSuchAlgorithmException {
Class algorithmClass = (Class) resolveAlias(algParamSpecs, algName);
if (algorithmClass == null) {
throw new NoSuchAlgorithmException(algName);
}
return algorithmClass;
}
/**
* Return an instance of the algorithm parameter specification class
* corresponding to the given algorithm name.
*
* @param paramName
* the name of the standard algorithm parameters
* @return the standard algorithm parameters
* @throws InvalidAlgorithmParameterException
* if the parameters cannot be found.
*/
public static final AlgorithmParameterSpec getAlgParamSpec(String paramName)
throws InvalidAlgorithmParameterException {
try {
return (AlgorithmParameterSpec) getInstance(algParamSpecs,
paramName);
} catch (NoSuchAlgorithmException e) {
throw new InvalidAlgorithmParameterException(
"Unknown parameters: '" + paramName + "'.");
}
}
/**
* Register a list of (names of) standardized algorithm parameters for the
* given algorithm. Additionally, each parameter set has to be registered
* separately using the {@link #add(int, Class, String)} or
* {@link #add(int, Class, String[])} method with the
* {@link #ALG_PARAM_SPEC} type.
*
* @param algName
* the name of the algorithm
* @param paramNames
* the names of the standardized algorithm parameters suitable
* for the specified algorithm
*/
public static final void addStandardAlgParams(String algName,
String[] paramNames) {
addStandardAlgParams(new String[] { algName }, paramNames);
}
/**
* Register a list of standardized algorithm parameters for the given list
* of algorithms. Additionally, each parameter set has to be registered
* separately using the {@link #add(int, Class, String)} or
* {@link #add(int, Class, String[])} method with the
* {@link #ALG_PARAM_SPEC} type.
*
* @param algNames
* the names of the algorithms
* @param paramNames
* the names of the standardized algorithm parameters suitable
* for the specified algorithm
*/
public static final void addStandardAlgParams(String[] algNames,
String[] paramNames) {
if ((algNames == null) || (paramNames == null)) {
return;
}
// build vector containing the parameter set names
Vector params = new Vector(paramNames.length);
for (int i = 0; i < paramNames.length; i++) {
params.addElement(paramNames[i]);
}
// register first name
standardAlgParams.put(algNames[0], params);
// register additional names (aliases)
for (int i = 1; i < algNames.length; i++) {
standardAlgParams.put(algNames[i], algNames[0]);
}
}
/**
* Return the set of standardized algorithm parameters registered for the
* given algorithm, or <tt>null</tt> if no parameters are registered for the
* given algorithm.
*
* @param algName
* the algorithm name
* @return the {@link Vector} of standardized algorithms parameters for the
* specified algorithm, or <tt>null</tt> if no parameters are
* registered for the algorithm
*/
public static final Vector getStandardAlgParams(String algName) {
return (Vector) resolveAlias(standardAlgParams, algName);
}
/**
* Return an instance of the specified algorithm parameters.
*
* @param algName
* the name of the algorithm parameters
* @return a new {@link AlgorithmParameters} object implementing the chosen
* algorithm
* @throws NoSuchAlgorithmException
* if the algorithm parameters cannot be found.
*/
public static final AlgorithmParameters getAlgParams(String algName)
throws NoSuchAlgorithmException {
return (AlgorithmParameters) getInstance(algParams, algName);
}
/**
* Return an instance of the specified algorithm parameter generator.
*
* @param algName
* the name of the algorithm parameter generator
* @return a new {@link AlgorithmParameterGenerator} object implementing the
* chosen algorithm
* @throws NoSuchAlgorithmException
* if the algorithm parameter generator cannot be found.
*/
public static final AlgorithmParameterGenerator getAlgParamGenerator(
String algName) throws NoSuchAlgorithmException {
return (AlgorithmParameterGenerator) getInstance(algParamGenerators,
algName);
}
/**
* Return an instance of the specified secret key generator.
*
* @param algName
* the name of the secret key generator
* @return a new {@link SecretKeyGenerator} object implementing the chosen
* algorithm
* @throws NoSuchAlgorithmException
* if the secret key generator cannot be found.
*/
public static final SecretKeyGenerator getSecretKeyGenerator(String algName)
throws NoSuchAlgorithmException {
return (SecretKeyGenerator) getInstance(secretKeyGenerators, algName);
}
/**
* Return an instance of the specified key pair generator.
*
* @param algName
* the name of the key pair generator
* @return a new {@link KeyPairGenerator} object implementing the chosen
* algorithm
* @throws NoSuchAlgorithmException
* if the key pair generator cannot be found.
*/
public static final KeyPairGenerator getKeyPairGenerator(String algName)
throws NoSuchAlgorithmException {
return (KeyPairGenerator) getInstance(keyPairGenerators, algName);
}
/**
* Return an instance of the specified secret key factory.
*
* @param algName
* the name of the secret key factory
* @return a new {@link SecretKeyFactory} object implementing the chosen
* algorithm
* @throws NoSuchAlgorithmException
* if the secret key factory cannot be found.
*/
public static final SecretKeyFactory getSecretKeyFactory(String algName)
throws NoSuchAlgorithmException {
return (SecretKeyFactory) getInstance(secretKeyFactories, algName);
}
/**
* Return an instance of the specified key factory.
*
* @param algName
* the name of the key factory
* @return a new {@link KeyFactory} object implementing the chosen algorithm
* @throws NoSuchAlgorithmException
* if the key factory cannot be found.
*/
public static final KeyFactory getKeyFactory(String algName)
throws NoSuchAlgorithmException {
return (KeyFactory) getInstance(keyFactories, algName);
}
/**
* Return an instance of the specified key derivation function.
*
* @param algName
* the name of the key derivation function
* @return a new {@link KeyDerivation} object implementing the chosen
* algorithm
* @throws NoSuchAlgorithmException
* if the key derivation cannot be found.
*/
public static final KeyDerivation getKeyDerivation(String algName)
throws NoSuchAlgorithmException {
return (KeyDerivation) getInstance(keyDerivations, algName);
}
/**
* Return an instance of the specified key agreement scheme.
*
* @param algName
* the name of the key agreement scheme
* @return a new {@link KeyAgreement} object implementing the chosen
* algorithm
* @throws NoSuchAlgorithmException
* if the key agreement scheme cannot be found.
*/
public static final KeyAgreement getKeyAgreement(String algName)
throws NoSuchAlgorithmException {
return (KeyAgreement) getInstance(keyAgreements, algName);
}
private static Hashtable getHashtable(int type) {
if (type > hashtables.length) {
return null;
}
return hashtables[type];
}
private static Object resolveAlias(Hashtable table, String name) {
Object value = name;
do {
String algName = (String) value;
value = table.get(algName);
} while (value != null && (value instanceof String));
return value;
}
/**
* Try to find an algorithm with the specified name inside the corresponding
* hashtable and return an instance of the algorithm.
*
* @param table
* hashtable containing the algorithm
* @param name
* the algorithm name
* @return a new object implementing the chosen algorithm, or <tt>null</tt>
* if the algorithm name is <tt>null</tt>
* @throws NoSuchAlgorithmException
* if the algorithm cannot be found.
*/
private static Object getInstance(Hashtable table, String name)
throws NoSuchAlgorithmException {
if (name == null) {
return null;
}
Class algClass = (Class) resolveAlias(table, name);
if (algClass == null) {
throw new NoSuchAlgorithmException(name);
}
try {
return algClass.newInstance();
} catch (InstantiationException e) {
throw new RegistrationException("Instantiation exception: "
+ e.getMessage());
} catch (IllegalAccessException e) {
throw new RegistrationException("Illegal access exception: "
+ e.getMessage());
}
}
}

View File

@@ -0,0 +1,59 @@
package de.flexiprovider.api;
import de.flexiprovider.common.math.FlexiBigInt;
import de.flexiprovider.common.math.IntegerFunctions;
import de.flexiprovider.common.util.BigEndianConversions;
import de.flexiprovider.common.util.LittleEndianConversions;
public abstract class SecureRandom extends java.security.SecureRandomSpi {
protected final byte[] engineGenerateSeed(int numBytes) {
return generateSeed(numBytes);
}
protected final void engineNextBytes(byte[] bytes) {
nextBytes(bytes);
}
protected final void engineSetSeed(byte[] seed) {
setSeed(seed);
}
public abstract byte[] generateSeed(int numBytes);
public abstract void nextBytes(byte[] bytes);
public abstract void setSeed(byte[] seed);
public final int nextInt() {
byte[] intBytes = new byte[4];
nextBytes(intBytes);
return BigEndianConversions.OS2IP(intBytes);
}
public final int nextInt(int upperBound) {
int result;
int octL = IntegerFunctions.ceilLog256(upperBound);
do {
byte[] intBytes = new byte[octL];
nextBytes(intBytes);
result = BigEndianConversions.OS2IP(intBytes, 0, octL);
} while (result < 0 || result >= upperBound);
return result;
}
public final long nextLong(long upperBound){
int octL = IntegerFunctions.ceilLog256(upperBound);
int bitLength=IntegerFunctions.floorLog(FlexiBigInt.valueOf(upperBound))+1;
int difference=octL*8-bitLength;
long result;
do {
byte[] intBytes = new byte[octL];
nextBytes(intBytes);
result = LittleEndianConversions.toLong(intBytes);
result>>>=difference;
} while (result < 0 || result >= upperBound);
return result;
}
}

View File

@@ -0,0 +1,314 @@
/*
* Copyright (c) 1998-2003 by The FlexiProvider Group,
* Technische Universitaet Darmstadt
*
* For conditions of usage and distribution please refer to the
* file COPYING in the root directory of this package.
*
*/
package de.flexiprovider.api;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.InvalidKeyException;
import de.flexiprovider.api.exceptions.SignatureException;
import de.flexiprovider.api.keys.PrivateKey;
import de.flexiprovider.api.keys.PublicKey;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
import de.flexiprovider.common.util.JavaSecureRandomWrapper;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for
* the <tt>Signature</tt> class, which is used to provide the functionality of
* a digital signature algorithm. Digital signatures are used for authentication
* and integrity assurance of digital data. .
* <p>
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation of a
* particular signature algorithm.
*
* @author Martin D<>ring, Johannes M<>ller
*/
public abstract class Signature extends java.security.SignatureSpi {
// ****************************************************
// JCA adapter methods
// ****************************************************
/**
* @deprecated
*/
protected final Object engineGetParameter(String param)
throws java.security.InvalidParameterException {
// method is deprecated
return null;
}
/**
* @deprecated
*/
protected final void engineSetParameter(String param, Object value)
throws java.security.InvalidParameterException {
// method is deprecated
}
protected final void engineInitSign(java.security.PrivateKey privateKey)
throws java.security.InvalidKeyException {
if ((privateKey == null) || !(privateKey instanceof PrivateKey)) {
throw new java.security.InvalidKeyException();
}
initSign((PrivateKey) privateKey);
}
protected final void engineInitSign(java.security.PrivateKey privateKey,
java.security.SecureRandom javaRand)
throws java.security.InvalidKeyException {
if ((privateKey == null) || !(privateKey instanceof PrivateKey)) {
throw new java.security.InvalidKeyException();
}
SecureRandom flexiRand = new JavaSecureRandomWrapper(javaRand);
initSign((PrivateKey) privateKey, flexiRand);
}
protected final void engineInitVerify(java.security.PublicKey publicKey)
throws java.security.InvalidKeyException {
if ((publicKey == null) || !(publicKey instanceof PublicKey)) {
throw new java.security.InvalidKeyException();
}
initVerify((PublicKey) publicKey);
}
protected void engineSetParameter(
java.security.spec.AlgorithmParameterSpec params)
throws java.security.InvalidAlgorithmParameterException {
if (params != null && !(params instanceof AlgorithmParameterSpec)) {
throw new java.security.InvalidAlgorithmParameterException();
}
setParameters((AlgorithmParameterSpec) params);
}
protected final void engineUpdate(byte b)
throws java.security.SignatureException {
update(b);
}
protected final void engineUpdate(byte[] b, int off, int len)
throws java.security.SignatureException {
update(b, off, len);
}
protected final byte[] engineSign() throws java.security.SignatureException {
return sign();
}
protected final boolean engineVerify(byte[] sigBytes)
throws java.security.SignatureException {
return verify(sigBytes);
}
protected final boolean engineVerify(byte[] sigBytes, int offset, int length)
throws java.security.SignatureException {
return verify(sigBytes, offset, length);
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
/**
* Initialize the signature with the specified private key for signing
* operations.
*
* @param privKey
* the private key of the identity whose signature will be
* generated.
* @throws InvalidKeyException
* if the key is invalid for initializing the signature.
*/
public final void initSign(PrivateKey privKey) throws InvalidKeyException {
initSign(privKey, Registry.getSecureRandom());
}
/**
* Initialize the signature with the specified private key and source of
* randomness for signing operations.
*
* @param privKey
* the private key of the identity whose signature will be
* generated.
* @param random
* the source of randomness
* @throws InvalidKeyException
* if the key is invalid for initializing the signature.
*/
public abstract void initSign(PrivateKey privKey, SecureRandom random)
throws InvalidKeyException;
/**
* Initialize the signature with the specified public key for verification
* operations.
*
* @param pubKey
* the public key of the identity whose signature is going to
* be verified
* @throws InvalidKeyException
* if the key is invalid for initializing the signature.
*/
public abstract void initVerify(PublicKey pubKey)
throws InvalidKeyException;
/**
* Initialize the signature with the specified parameters.
*
* @param params
* the parameters
* @throws InvalidAlgorithmParameterException
* if the given parameters are inappropriate for this
* signature.
*/
public abstract void setParameters(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException;
/**
* Update the data to be signed or verified using the specified byte.
*
* @param input
* the data byte
* @throws SignatureException
* if the engine is not initialized properly.
*/
public abstract void update(byte input) throws SignatureException;
/**
* Update the data to be signed or verified using the specified byte array.
*
* @param input
* the data byte array
* @throws SignatureException
* if the engine is not initialized properly.
*/
public final void update(byte[] input) throws SignatureException {
update(input, 0, input.length);
}
/**
* Update the data to be signed or verified, using the specified byte array
* of the specified length, starting at the specified offset.
*
* @param input
* the data byte array
* @param inOff
* the offset to start from in the array of bytes
* @param inLen
* the number of bytes to use, starting at <tt>inOff</tt>
* @throws SignatureException
* if the engine is not initialized properly
*/
public abstract void update(byte[] input, int inOff, int inLen)
throws SignatureException;
/**
* Return the signature of all the data updated so far.
*
* @return the signature
* @throws SignatureException
* if the engine is not initialized properly.
*/
public abstract byte[] sign() throws SignatureException;
/**
* Update the data to be signed and return the signature of all the data
* updated so far.
*
* @param input
* the data byte array
* @return the signature
* @throws SignatureException
* if the engine is not initialized properly.
*/
public final byte[] sign(byte[] input) throws SignatureException {
update(input);
return sign();
}
/**
* Verify the passed-in signature of the specified message.
*
* @param signature
* the signature
* @return <tt>true</tt> if the signature is valid, <tt>false</tt>
* otherwise.
* @throws SignatureException
* if the engine is not initialized properly or the
* passed-in signature is improperly encoded or of the wrong
* type.
*/
public abstract boolean verify(byte[] signature) throws SignatureException;
/**
* Update the data to be verified and verify the passed-in signature.
*
* @param input
* the data byte array
* @param signature
* the signature
* @return <tt>true</tt> if the signature is valid, <tt>false</tt>
* otherwise.
* @throws SignatureException
* if the engine is not initialized properly or the
* passed-in signature is improperly encoded or of the wrong
* type.
*/
public final boolean verify(byte[] input, byte[] signature)
throws SignatureException {
update(input);
return verify(signature);
}
/**
* Verify the passed-in signature.
*
* @param signature
* the signature
* @param sigOff
* the offset where the signature starts
* @param sigLen
* the length of the signature
* @return <tt>true</tt> if the signature is valid, <tt>false</tt>
* otherwise.
* @throws SignatureException
* if the engine is not initialized properly or the
* passed-in signature is improperly encoded or of the wrong
* type.
*/
public final boolean verify(byte[] signature, int sigOff, int sigLen)
throws SignatureException {
byte[] sig = new byte[sigLen];
System.arraycopy(signature, sigOff, sig, 0, sigLen);
return verify(sig);
}
/**
* Update the data to be verified and verify the passed-in signature.
*
* @param input
* the data byte array
* @param signature
* the signature
* @param sigOff
* the offset where the signature starts
* @param sigLen
* the length of the signature
* @return <tt>true</tt> if the signature is valid, <tt>false</tt>
* otherwise.
* @throws SignatureException
* if the engine is not initialized properly or the
* passed-in signature is improperly encoded or of the wrong
* type.
*/
public final boolean verify(byte[] input, byte[] signature, int sigOff,
int sigLen) throws SignatureException {
update(input);
return verify(signature, sigOff, sigLen);
}
}

View File

@@ -0,0 +1,13 @@
package de.flexiprovider.api.exceptions;
public class BadPaddingException extends javax.crypto.BadPaddingException {
public BadPaddingException() {
super();
}
public BadPaddingException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,9 @@
package de.flexiprovider.api.exceptions;
public class DigestException extends java.security.DigestException {
public DigestException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,10 @@
package de.flexiprovider.api.exceptions;
public class IllegalBlockSizeException extends
javax.crypto.IllegalBlockSizeException {
public IllegalBlockSizeException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,14 @@
package de.flexiprovider.api.exceptions;
public class InvalidAlgorithmParameterException extends
java.security.InvalidAlgorithmParameterException {
public InvalidAlgorithmParameterException() {
super();
}
public InvalidAlgorithmParameterException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,13 @@
package de.flexiprovider.api.exceptions;
public class InvalidKeyException extends java.security.InvalidKeyException {
public InvalidKeyException() {
super();
}
public InvalidKeyException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,14 @@
package de.flexiprovider.api.exceptions;
public class InvalidKeySpecException extends
java.security.spec.InvalidKeySpecException {
public InvalidKeySpecException() {
super();
}
public InvalidKeySpecException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,10 @@
package de.flexiprovider.api.exceptions;
public class InvalidParameterException extends
java.security.InvalidParameterException {
public InvalidParameterException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,10 @@
package de.flexiprovider.api.exceptions;
public class InvalidParameterSpecException extends
java.security.spec.InvalidParameterSpecException {
public InvalidParameterSpecException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,10 @@
package de.flexiprovider.api.exceptions;
public class NoSuchAlgorithmException extends
java.security.NoSuchAlgorithmException {
public NoSuchAlgorithmException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,20 @@
package de.flexiprovider.api.exceptions;
/**
* Exception used to indicate that a mode of operation cannot be found.
*
* @author Martin D<>ring
*/
public class NoSuchModeException extends NoSuchAlgorithmException {
/**
* Constructor.
*
* @param msg
* the error message
*/
public NoSuchModeException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,9 @@
package de.flexiprovider.api.exceptions;
public class NoSuchPaddingException extends javax.crypto.NoSuchPaddingException {
public NoSuchPaddingException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,29 @@
package de.flexiprovider.api.exceptions;
/**
* Exception used to indicate registration errors (used by the
* {@link de.flexiprovider.api.Registry Registry} class). Since this exception
* is thrown during static initialization, it extends {@link RuntimeException}.
*
* @author Martin D<>ring
*/
public class RegistrationException extends RuntimeException {
/**
* Default constructor.
*/
public RegistrationException() {
super();
}
/**
* Constructor.
*
* @param s
* the error message
*/
public RegistrationException(String s) {
super(s);
}
}

View File

@@ -0,0 +1,13 @@
package de.flexiprovider.api.exceptions;
public class ShortBufferException extends javax.crypto.ShortBufferException {
public ShortBufferException() {
super();
}
public ShortBufferException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,9 @@
package de.flexiprovider.api.exceptions;
public class SignatureException extends java.security.SignatureException {
public SignatureException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,7 @@
package de.flexiprovider.api.keys;
public interface Key extends java.security.Key {
// empty
}

View File

@@ -0,0 +1,189 @@
package de.flexiprovider.api.keys;
import de.flexiprovider.api.exceptions.InvalidKeyException;
import de.flexiprovider.api.exceptions.InvalidKeySpecException;
import de.flexiprovider.pki.PKCS8EncodedKeySpec;
import de.flexiprovider.pki.X509EncodedKeySpec;
public abstract class KeyFactory extends java.security.KeyFactorySpi {
// ****************************************************
// JCA adapter methods
// ****************************************************
/**
* JCA adapter for FlexiAPI method generatePublic(): generates a public key
* object from the provided key specification (key material).
*
* @param keySpec
* the specification (key material) of the public key
* @return the public key
* @throws java.security.spec.InvalidKeySpecException
* if the given key specification is inappropriate for this
* key factory to produce a public key.
*/
protected java.security.PublicKey engineGeneratePublic(
java.security.spec.KeySpec keySpec)
throws java.security.spec.InvalidKeySpecException {
if (keySpec != null && !(keySpec instanceof KeySpec)) {
if (keySpec instanceof java.security.spec.X509EncodedKeySpec) {
KeySpec encKeySpec = new X509EncodedKeySpec(
(java.security.spec.X509EncodedKeySpec) keySpec);
return generatePublic(encKeySpec);
}
throw new java.security.spec.InvalidKeySpecException();
}
return generatePublic((KeySpec) keySpec);
}
/**
* JCA adapter for FlexiAPI method generatePrivate(): generate a private key
* object from the provided key specification (key material).
*
* @param keySpec
* the specification (key material) of the private key
* @return the private key
* @throws java.security.spec.InvalidKeySpecException
* if the given key specification is inappropriate for this
* key factory to produce a private key.
*/
protected java.security.PrivateKey engineGeneratePrivate(
java.security.spec.KeySpec keySpec)
throws java.security.spec.InvalidKeySpecException {
if (keySpec != null && !(keySpec instanceof KeySpec)) {
if (keySpec instanceof java.security.spec.PKCS8EncodedKeySpec) {
KeySpec encKeySpec = new PKCS8EncodedKeySpec(
(java.security.spec.PKCS8EncodedKeySpec) keySpec);
return generatePrivate(encKeySpec);
}
throw new java.security.spec.InvalidKeySpecException();
}
return generatePrivate((KeySpec) keySpec);
}
/**
* JCA adapter for FlexiAPI method getKeySpec(): return a specification (key
* material) of the given key object. <tt>keySpec</tt> identifies the
* specification class in which the key material should be returned. It
* could, for example, be <tt>DSAPublicKeySpec.class</tt>, to indicate
* that the key material should be returned in an instance of the
* <tt>DSAPublicKeySpec</tt> class.
*
* @param key
* the key
* @param keySpec
* the specification class in which the key material should
* be returned
* @return the underlying key specification (key material) in an instance of
* the requested specification class
* @throws java.security.spec.InvalidKeySpecException
* if the requested key specification is inappropriate for
* the given key, or the given key cannot be dealt with
* (e.g., the given key has an unrecognized format).
*/
protected final java.security.spec.KeySpec engineGetKeySpec(
java.security.Key key, Class keySpec)
throws java.security.spec.InvalidKeySpecException {
if (!(key instanceof Key)) {
throw new java.security.spec.InvalidKeySpecException();
}
return getKeySpec((Key) key, keySpec);
}
/**
* JCA adapter for FlexiAPI method translateKey(): translate a key object,
* whose provider may be unknown or potentially untrusted, into a
* corresponding key object of this key factory.
*
* @param key
* the key whose provider is unknown or untrusted
* @return the translated key
* @throws java.security.InvalidKeyException
* if the given key cannot be processed by this key factory.
*/
protected final java.security.Key engineTranslateKey(java.security.Key key)
throws java.security.InvalidKeyException {
if (!(key instanceof Key)) {
throw new java.security.InvalidKeyException();
}
return translateKey((Key) key);
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
/**
* Generate a public key object from the provided key specification (key
* material).
*
* @param keySpec
* the specification (key material) of the public key
* @return the public key
* @throws InvalidKeySpecException
* if the given key specification is inappropriate for this
* key factory to produce a public key.
*/
public abstract PublicKey generatePublic(KeySpec keySpec)
throws InvalidKeySpecException;
/**
* Generate a private key object from the provided key specification (key
* material).
*
* @param keySpec
* the specification (key material) of the private key
* @return the private key
* @throws InvalidKeySpecException
* if the given key specification is inappropriate for this
* key factory to produce a private key.
*/
public abstract PrivateKey generatePrivate(KeySpec keySpec)
throws InvalidKeySpecException;
/**
* Return a specification (key material) of the given key object.
* <tt>keySpec</tt> identifies the specification class in which the key
* material should be returned. It could, for example, be
* <tt>DSAPublicKeySpec.class</tt>, to indicate that the key material
* should be returned in an instance of the <tt>DSAPublicKeySpec</tt>
* class.
*
* @param key
* the key
* @param keySpec
* the specification class in which the key material should
* be returned
* @return the underlying key specification (key material) in an instance of
* the requested specification class
* @throws InvalidKeySpecException
* if the requested key specification is inappropriate for
* the given key, or the given key cannot be dealt with
* (e.g., the given key has an unrecognized format).
*/
public abstract KeySpec getKeySpec(Key key, Class keySpec)
throws InvalidKeySpecException;
/**
* Translate a key object, whose provider may be unknown or potentially
* untrusted, into a corresponding key object of this key factory.
*
* @param key
* the key whose provider is unknown or untrusted
* @return the translated key
* @throws InvalidKeyException
* if the given key cannot be processed by this key factory.
*/
public abstract Key translateKey(Key key) throws InvalidKeyException;
}

View File

@@ -0,0 +1,47 @@
package de.flexiprovider.api.keys;
/**
* This class is a simple holder for a key pair (a public key and a private
* key). It does not enforce any security, and, when initialized, should be
* treated like a private key.
*/
public final class KeyPair {
java.security.KeyPair pair;
/**
* Construct a key pair from the given public key and private key.
* <p>
* Note that this constructor only stores references to the public and
* private key components in the generated key pair. This is safe, because
* <tt>Key</tt> objects are immutable.
*
* @param publicKey
* the public key.
*
* @param privateKey
* the private key.
*/
public KeyPair(PublicKey publicKey, PrivateKey privateKey) {
pair = new java.security.KeyPair(publicKey, privateKey);
}
/**
* Return a reference to the public key component of this key pair.
*
* @return a reference to the public key.
*/
public PublicKey getPublic() {
return (PublicKey) pair.getPublic();
}
/**
* Return a reference to the private key component of this key pair.
*
* @return a reference to the private key.
*/
public PrivateKey getPrivate() {
return (PrivateKey) pair.getPrivate();
}
}

View File

@@ -0,0 +1,132 @@
package de.flexiprovider.api.keys;
import de.flexiprovider.api.SecureRandom;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.exceptions.InvalidParameterException;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
import de.flexiprovider.common.util.JavaSecureRandomWrapper;
public abstract class KeyPairGenerator extends
java.security.KeyPairGeneratorSpi {
// ****************************************************
// JCA adapter methods
// ****************************************************
/**
* JCA adapter for FlexiAPI method
* {@link #initialize(AlgorithmParameterSpec, SecureRandom)}: initialize
* the key pair generator using the specified parameter set and source of
* randomness.
*
* @param params
* the parameter set used to generate the keys
* @param javaRand
* the source of randomness for this generator
* @throws java.security.InvalidAlgorithmParameterException
* if the given parameters are inappropriate for this key
* pair generator.
*/
public void initialize(java.security.spec.AlgorithmParameterSpec params,
java.security.SecureRandom javaRand)
throws java.security.InvalidAlgorithmParameterException {
if (params != null && !(params instanceof AlgorithmParameterSpec)) {
throw new java.security.InvalidAlgorithmParameterException();
}
SecureRandom flexiRand = new JavaSecureRandomWrapper(javaRand);
initialize((AlgorithmParameterSpec) params, flexiRand);
}
// ****************************************************
// JCA adapter methods
// ****************************************************
/**
* Initialize the key pair generator for a certain key size using a default
* parameter set and the <tt>SecureRandom</tt> implementation of the
* highest-priority installed provider as the source of randomness. (If none
* of the installed providers supply an implementation of
* <tt>SecureRandom</tt>, a system-provided source of randomness is
* used.)
*
* @param keysize
* the keysize. This is an algorithm-specific metric, such as
* modulus length, specified in number of bits.
* @param javaRand
* the source of randomness for this generator
* @throws InvalidParameterException
* if the <tt>keysize</tt> is not supported by this
* KeyPairGenerator object.
*/
public final void initialize(int keysize,
java.security.SecureRandom javaRand)
throws InvalidParameterException {
SecureRandom flexiRand = new JavaSecureRandomWrapper(javaRand);
initialize(keysize, flexiRand);
}
/**
* JCA adapter to FlexiAPI method {@link #genKeyPair()}: generate a key
* pair. Unless an initialization method is called using a KeyPairGenerator
* interface, algorithm-specific defaults will be used. This will generate a
* new key pair every time it is called.
*
* @return a newly generated <tt>KeyPair</tt>
*/
public final java.security.KeyPair generateKeyPair() {
return genKeyPair().pair;
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
/**
* Initialize the key pair generator using the specified parameter set and
* the <tt>SecureRandom</tt> implementation of the highest-priority
* installed provider as the source of randomness. (If none of the installed
* providers supply an implementation of <tt>SecureRandom</tt>, a
* system-provided source of randomness is used.).
*
* @param params
* the parameter set used to generate the keys
* @param random
* a source of randomness
* @throws InvalidAlgorithmParameterException
* if the given parameters are inappropriate for this key
* pair generator.
*/
public abstract void initialize(AlgorithmParameterSpec params,
SecureRandom random) throws InvalidAlgorithmParameterException;
/**
* Initialize the key pair generator for a certain keysize using a default
* parameter set and the <tt>SecureRandom</tt> implementation of the
* highest-priority installed provider as the source of randomness. (If none
* of the installed providers supply an implementation of
* <tt>SecureRandom</tt>, a system-provided source of randomness is
* used.)
*
* @param keysize
* the keysize. This is an algorithm-specific metric, such as
* modulus length, specified in number of bits.
* @param random
* the source of randomness for this generator
* @throws InvalidParameterException
* if the <tt>keysize</tt> is not supported by this
* KeyPairGenerator object.
*/
public abstract void initialize(int keysize, SecureRandom random)
throws InvalidParameterException;
/**
* Generate a key pair. Unless an initialization method is called using a
* KeyPairGenerator interface, algorithm-specific defaults will be used.
* This will generate a new key pair every time it is called.
*
* @return a newly generated {@link KeyPair}
*/
public abstract KeyPair genKeyPair();
}

View File

@@ -0,0 +1,11 @@
package de.flexiprovider.api.keys;
/**
* A (transparent) specification of the key material that constitutes a
* cryptographic key.
*/
public interface KeySpec extends java.security.spec.KeySpec {
// empty
}

View File

@@ -0,0 +1,53 @@
package de.flexiprovider.api.keys;
import codec.asn1.ASN1Exception;
import codec.asn1.ASN1ObjectIdentifier;
import codec.asn1.ASN1Type;
import codec.pkcs8.PrivateKeyInfo;
import de.flexiprovider.common.util.ASN1Tools;
import de.flexiprovider.pki.AlgorithmIdentifier;
public abstract class PrivateKey implements Key, java.security.PrivateKey {
/**
* Return the encoding format, PKCS #8.
*
* @return "PKCS#8"
*/
public final String getFormat() {
return "PKCS#8";
}
/**
* Return the key in its primary encoding format, PKCS #8.
*
* @return the PKCS #8 encoded key.
*/
public final byte[] getEncoded() {
AlgorithmIdentifier aid;
try {
aid = new AlgorithmIdentifier(getOID(), getAlgParams());
} catch (ASN1Exception asn1e) {
throw new RuntimeException("ASN1Exception: " + asn1e.getMessage());
}
PrivateKeyInfo spki = new PrivateKeyInfo(aid, getKeyData());
return ASN1Tools.derEncode(spki);
}
/**
* @return the OID to encode in the SubjectPublicKeyInfo structure
*/
protected abstract ASN1ObjectIdentifier getOID();
/**
* @return the algorithm parameters to encode in the SubjectPublicKeyInfo
* structure
*/
protected abstract ASN1Type getAlgParams();
/**
* @return the keyData to encode in the SubjectPublicKeyInfo structure
*/
protected abstract byte[] getKeyData();
}

View File

@@ -0,0 +1,53 @@
package de.flexiprovider.api.keys;
import codec.asn1.ASN1Exception;
import codec.asn1.ASN1ObjectIdentifier;
import codec.asn1.ASN1Type;
import codec.x509.SubjectPublicKeyInfo;
import de.flexiprovider.common.util.ASN1Tools;
import de.flexiprovider.pki.AlgorithmIdentifier;
public abstract class PublicKey implements Key, java.security.PublicKey {
/**
* Return the encoding format, X.509.
*
* @return "X.509"
*/
public final String getFormat() {
return "X.509";
}
/**
* Return the key in its primary encoding format, X.509.
*
* @return the X.509 encoded key.
*/
public final byte[] getEncoded() {
AlgorithmIdentifier aid;
try {
aid = new AlgorithmIdentifier(getOID(), getAlgParams());
} catch (ASN1Exception asn1e) {
throw new RuntimeException("ASN1Exception: " + asn1e.getMessage());
}
SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo(aid, getKeyData());
return ASN1Tools.derEncode(spki);
}
/**
* @return the OID to encode in the SubjectPublicKeyInfo structure
*/
protected abstract ASN1ObjectIdentifier getOID();
/**
* @return the algorithm parameters to encode in the SubjectPublicKeyInfo
* structure
*/
protected abstract ASN1Type getAlgParams();
/**
* @return the keyData to encode in the SubjectPublicKeyInfo structure
*/
protected abstract byte[] getKeyData();
}

View File

@@ -0,0 +1,7 @@
package de.flexiprovider.api.keys;
public interface SecretKey extends Key, javax.crypto.SecretKey {
// empty
}

View File

@@ -0,0 +1,69 @@
package de.flexiprovider.api.keys;
import javax.crypto.SecretKeyFactorySpi;
import de.flexiprovider.api.exceptions.InvalidKeyException;
import de.flexiprovider.api.exceptions.InvalidKeySpecException;
public abstract class SecretKeyFactory extends SecretKeyFactorySpi {
// ****************************************************
// JCA adapter methods
// ****************************************************
protected javax.crypto.SecretKey engineGenerateSecret(
java.security.spec.KeySpec keySpec)
throws java.security.spec.InvalidKeySpecException {
if (keySpec == null) {
throw new java.security.spec.InvalidKeySpecException();
}
if (!(keySpec instanceof KeySpec)) {
if (keySpec instanceof javax.crypto.spec.SecretKeySpec) {
javax.crypto.spec.SecretKeySpec javaSpec = (javax.crypto.spec.SecretKeySpec) keySpec;
KeySpec secretKeySpec = new SecretKeySpec(
javaSpec.getEncoded(), javaSpec.getAlgorithm());
return generateSecret(secretKeySpec);
}
throw new java.security.spec.InvalidKeySpecException();
}
return generateSecret((KeySpec) keySpec);
}
protected java.security.spec.KeySpec engineGetKeySpec(
javax.crypto.SecretKey key, Class keySpec)
throws java.security.spec.InvalidKeySpecException {
if ((key == null) || (keySpec == null) || !(key instanceof SecretKey)) {
throw new java.security.spec.InvalidKeySpecException();
}
return getKeySpec((SecretKey) key, keySpec);
}
protected javax.crypto.SecretKey engineTranslateKey(
javax.crypto.SecretKey key)
throws java.security.InvalidKeyException {
if ((key == null) || !(key instanceof SecretKey)) {
throw new java.security.InvalidKeyException();
}
return translateKey((SecretKey) key);
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
public abstract SecretKey generateSecret(KeySpec keySpec)
throws InvalidKeySpecException;
public abstract KeySpec getKeySpec(SecretKey key, Class keySpec)
throws InvalidKeySpecException;
public abstract SecretKey translateKey(SecretKey key)
throws InvalidKeyException;
}

View File

@@ -0,0 +1,64 @@
package de.flexiprovider.api.keys;
import de.flexiprovider.api.Registry;
import de.flexiprovider.api.SecureRandom;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.api.parameters.AlgorithmParameterSpec;
import de.flexiprovider.common.util.JavaSecureRandomWrapper;
public abstract class SecretKeyGenerator extends javax.crypto.KeyGeneratorSpi {
// ****************************************************
// JCA adapter methods
// ****************************************************
protected final javax.crypto.SecretKey engineGenerateKey() {
return generateKey();
}
protected final void engineInit(java.security.SecureRandom javaRand) {
init(new JavaSecureRandomWrapper(javaRand));
}
protected final void engineInit(int keysize,
java.security.SecureRandom javaRand) {
init(keysize, new JavaSecureRandomWrapper(javaRand));
}
protected void engineInit(java.security.spec.AlgorithmParameterSpec params,
java.security.SecureRandom javaRand)
throws java.security.InvalidAlgorithmParameterException {
if (params != null && !(params instanceof AlgorithmParameterSpec)) {
throw new java.security.InvalidAlgorithmParameterException();
}
init((AlgorithmParameterSpec) params, new JavaSecureRandomWrapper(
javaRand));
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
public abstract SecretKey generateKey();
public final void init() {
init(Registry.getSecureRandom());
}
public abstract void init(SecureRandom random);
public final void init(int keySize) {
init(keySize, Registry.getSecureRandom());
}
public abstract void init(int keySize, SecureRandom random);
public final void init(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException {
init(params, Registry.getSecureRandom());
}
public abstract void init(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException;
}

View File

@@ -0,0 +1,14 @@
package de.flexiprovider.api.keys;
public class SecretKeySpec extends javax.crypto.spec.SecretKeySpec implements
KeySpec {
public SecretKeySpec(byte[] key, String algorithm) {
super(key, algorithm);
}
public SecretKeySpec(byte[] key, int offset, int len, String algorithm) {
super(key, offset, len, algorithm);
}
}

View File

@@ -0,0 +1,133 @@
package de.flexiprovider.api.parameters;
import de.flexiprovider.api.SecureRandom;
import de.flexiprovider.api.exceptions.InvalidAlgorithmParameterException;
import de.flexiprovider.common.mode.ModeParameterSpec;
import de.flexiprovider.common.util.JavaSecureRandomWrapper;
public abstract class AlgorithmParameterGenerator extends
java.security.AlgorithmParameterGeneratorSpi {
// ****************************************************
// JCA adapter methods
// ****************************************************
/**
* JCA adapter for FlexiAPI method {@link #generateParameters()}: generate
* parameters.
*
* @return the generated parameters
*/
protected final java.security.AlgorithmParameters engineGenerateParameters() {
/**
* JCA adapter class, used to translate from {@link AlgorithmParameters}
* to {@link java.security.AlgorithmParameters}.
*/
final class JCAAlgorithmParameters extends
java.security.AlgorithmParameters {
private JCAAlgorithmParameters(AlgorithmParameters params) {
super(params, null, null);
}
}
JCAAlgorithmParameters algParams = new JCAAlgorithmParameters(
getAlgorithmParameters());
try {
algParams.init(generateParameters());
} catch (java.security.spec.InvalidParameterSpecException ipse) {
throw new RuntimeException("InvalidParameterSpecException: "
+ ipse.getMessage());
}
return algParams;
}
/**
* JCA adapter for FlexiAPI methods init(): initialize the parameter
* generator with a key size and a source of randomness.
*
* @param keySize
* the key size
* @param javaRand
* the source of randomness
*/
protected final void engineInit(int keySize,
java.security.SecureRandom javaRand) {
SecureRandom flexiRand = new JavaSecureRandomWrapper(javaRand);
init(keySize, flexiRand);
}
/**
* JCA adapter for FlexiAPI methods init(): initialize the parameter
* generator with a parameter specification and a source of randomness.
*
* @param genParamSpec
* the parameter specification
* @param javaRand
* the source of randomness
* @throws java.security.InvalidAlgorithmParameterException
* if the given parameters are invalid.
*/
protected final void engineInit(
java.security.spec.AlgorithmParameterSpec genParamSpec,
java.security.SecureRandom javaRand)
throws java.security.InvalidAlgorithmParameterException {
SecureRandom flexiRand = new JavaSecureRandomWrapper(javaRand);
ModeParameterSpec paramSpec;
if (genParamSpec instanceof javax.crypto.spec.IvParameterSpec) {
paramSpec = new ModeParameterSpec(
(javax.crypto.spec.IvParameterSpec) genParamSpec);
init(paramSpec, flexiRand);
} else {
if (!(genParamSpec instanceof AlgorithmParameterSpec)) {
throw new java.security.InvalidAlgorithmParameterException();
}
init((AlgorithmParameterSpec) genParamSpec, flexiRand);
}
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
/**
* @return an instance of the {@link AlgorithmParameters} class
* corresponding to the generated parameters
*/
protected abstract AlgorithmParameters getAlgorithmParameters();
/**
* Initialize the parameter generator with a key size and a source of
* randomness.
*
* @param keySize
* the key size
* @param random
* the source of randomness
*/
public abstract void init(int keySize, SecureRandom random);
/**
* Initialize the parameter generator with a parameter specification and a
* source of randomness.
*
* @param genParamSpec
* the parameter specification
* @param random
* the source of randomness
* @throws InvalidAlgorithmParameterException
* if the given parameters are invalid.
*/
public abstract void init(AlgorithmParameterSpec genParamSpec,
SecureRandom random) throws InvalidAlgorithmParameterException;
/**
* Generate parameters.
*
* @return the generated parameters
*/
public abstract AlgorithmParameterSpec generateParameters();
}

View File

@@ -0,0 +1,15 @@
package de.flexiprovider.api.parameters;
/**
* A (transparent) specification of cryptographic parameters.
* <p>
* This interface contains no methods or constants. Its only purpose is to group
* (and provide type safety for) all parameter specifications. All parameter
* specifications must implement this interface.
*/
public interface AlgorithmParameterSpec extends
java.security.spec.AlgorithmParameterSpec {
// empty
}

View File

@@ -0,0 +1,221 @@
package de.flexiprovider.api.parameters;
import java.io.IOException;
import de.flexiprovider.api.exceptions.InvalidParameterSpecException;
/**
* This class defines the interface used to manage algorithm parameters.
*
* @see de.flexiprovider.api.parameters.AlgorithmParameterSpec
*/
public abstract class AlgorithmParameters extends
java.security.AlgorithmParametersSpi {
// ****************************************************
// JCA adapter methods
// ****************************************************
/**
* JCA adapter for FlexiAPI method {@link #init(AlgorithmParameterSpec)}:
* initialize this parameters object using the parameters specified in
* <tt>paramSpec</tt>.
*
* @param params
* the parameter specification
* @throws java.security.spec.InvalidParameterSpecException
* if <tt>paramSpec</tt> is inappropriate for
* initialization.
*/
protected void engineInit(java.security.spec.AlgorithmParameterSpec params)
throws java.security.spec.InvalidParameterSpecException {
if ((params == null) || !(params instanceof AlgorithmParameterSpec)) {
throw new java.security.spec.InvalidParameterSpecException();
}
init((AlgorithmParameterSpec) params);
}
/**
* JCA adapter for FlexiAPI method {@link #init(byte[])}: import the
* specified parameters and decode them according to the primary decoding
* format for parameters. The primary decoding format for parameters is
* ASN.1, if an ASN.1 specification for this type of parameters exists.
*
* @param params
* the encoded parameters
* @throws IOException
* on decoding errors.
*/
protected final void engineInit(byte[] params) throws IOException {
init(params);
}
/**
* JCA adapter for FlexiAPI method {@link #init(byte[], String)}: import
* the specified parameters and decode them according to the specified
* decoding format. If <tt>format</tt> is null, the primary decoding
* format for parameters is used. The primary decoding format is ASN.1, if
* an ASN.1 specification for these parameters exists.
*
* @param params
* the encoded parameters
* @param format
* the decoding format
* @throws IOException
* on decoding errors.
*/
protected final void engineInit(byte[] params, String format)
throws IOException {
init(params, format);
}
/**
* JCA adapter for FlexiAPI method {@link #getEncoded()}: return the
* parameters in their primary encoding format. The primary encoding format
* for parameters is ASN.1, if an ASN.1 specification for this type of
* parameters exists.
*
* @return the parameters encoded in their primary encoding format
* @throws IOException
* on encoding errors.
*/
protected final byte[] engineGetEncoded() throws IOException {
return getEncoded();
}
/**
* JCA adapter for FlexiAPI method {@link #getEncoded(String)}: return the
* parameters in the specified encoding format. If <tt>format</tt> is
* null, the primary decoding format is used. The primary encoding format
* for parameters is ASN.1, if an ASN.1 specification for this type of
* parameters exists.
*
* @param format
* the encoding format
* @return the parameters encoded in the specified encoding format
* @throws IOException
* on encoding errors.
*/
protected final byte[] engineGetEncoded(String format) throws IOException {
return getEncoded(format);
}
/**
* JCA adapter for FlexiAPI method {@link #getParameterSpec(Class)}: return
* a (transparent) specification of this parameters object.
* <tt>paramSpec</tt> identifies the specification class in which the
* parameters should be returned. It could, for example, be
* {@link java.security.spec.DSAParameterSpec}<tt>.class</tt> , to
* indicate that the parameters should be returned in an instance of the
* {@link java.security.spec.DSAParameterSpec} class.
*
* @param paramSpec
* the the specification class in which the parameters should
* be returned
* @return the parameter specification
* @throws java.security.spec.InvalidParameterSpecException
* if the requested parameter specification is inappropriate
* for this parameter object.
*/
protected java.security.spec.AlgorithmParameterSpec engineGetParameterSpec(
Class paramSpec)
throws java.security.spec.InvalidParameterSpecException {
if (!(AlgorithmParameterSpec.class.isAssignableFrom(paramSpec))) {
throw new java.security.spec.InvalidParameterSpecException(
"Unsupported parameter specification.");
}
return getParameterSpec(paramSpec);
}
/**
* JCA adapter for FlexiAPI method {@link #toString()}.
*
* @return a human readable form of this parameters object
*/
protected final String engineToString() {
return toString();
}
// ****************************************************
// FlexiAPI methods
// ****************************************************
/**
* Initialize the parameters with the given parameter specification.
*
* @param paramSpec
* the parameter specification
* @throws InvalidParameterSpecException
* if the parameter specification is <tt>null</tt> or of
* an unsupported type.
*/
public abstract void init(AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException;
/**
* Import the given encoded parameters and decode them according to the
* primary encoding format (ASN.1).
*
* @param encParams
* the encoded parameters
* @throws IOException
* on decoding errors.
*/
public abstract void init(byte[] encParams) throws IOException;
/**
* Import the given encoded parameters and decode them according to the
* specified encoding format.
*
* @param encParams
* the encoded parameters
* @param format
* the encoding format
* @throws IOException
* on decoding errors or if the encoding format is
* <tt>null</tt> or not supported.
*/
public abstract void init(byte[] encParams, String format)
throws IOException;
/**
* Encode the parameters according to the primary encoding format (ASN.1).
*
* @return the encoded parameters
* @throws IOException
* on encoding errors.
*/
public abstract byte[] getEncoded() throws IOException;
/**
* Encode the parameters according to the specified encoding format.
*
* @param format
* the encoding format
* @return the encoded parameters
* @throws IOException
* on encoding errors or if the encoding format is
* <tt>null</tt> or not supported.
*/
public abstract byte[] getEncoded(String format) throws IOException;
/**
* Return a transparent specification of the parameters.
*
* @param paramSpec
* the desired parameter specification type
* @return the parameter specification
* @throws InvalidParameterSpecException
* if the parameter specification type is <tt>null</tt> or
* or not supported
*/
public abstract AlgorithmParameterSpec getParameterSpec(Class paramSpec)
throws InvalidParameterSpecException;
/**
* @return a human readable form of the parameters
*/
public abstract String toString();
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 1998-2003 by The FlexiProvider Group,
* Technische Universitaet Darmstadt
*
* For conditions of usage and distribution please refer to the
* file COPYING in the root directory of this package.
*
*/
package de.flexiprovider.common.exceptions;
/**
* This exception is the parentclass of all exceptions, that relate to the ec -
* arithmetic.
*
* @author Birgit Henhapl
* @see de.flexiprovider.common.math.ellipticcurves.Point
* @see de.flexiprovider.common.math.ellipticcurves.PointGFP
*/
public class ECException extends RuntimeException {
private static final String diagnostic = "An ec-specific exception was thrown";
/**
* Default constructor. Calls super-constructor with the message "An
* ec-specific exception was thrown".
*/
public ECException() {
super(diagnostic);
}
/**
* Constructor with the message "An ec-specific exception was thrown:
* <em>cause</em>"
*
* @param cause
* String specifying cause of exception
*/
public ECException(String cause) {
super(diagnostic + ": " + cause);
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 1998-2003 by The FlexiProvider Group,
* Technische Universitaet Darmstadt
*
* For conditions of usage and distribution please refer to the
* file COPYING in the root directory of this package.
*
*/
package de.flexiprovider.common.exceptions;
import de.flexiprovider.common.math.FlexiBigInt;
/**
* This exception is thrown, if the square root modulo a prime of a nonquadratic
* residue is to be calculated.
*
* @author Birgit Henhapl
* @see de.flexiprovider.common.math.ellipticcurves.Point
* @see de.flexiprovider.common.math.ellipticcurves.PointGFP
*/
public class NoQuadraticResidueException extends ECException {
/**
* Default constructor. Calls super-constructor with no message.
*/
public NoQuadraticResidueException() {
super();
}
/**
* Constructs NoQuadraticResidueException with the message:<br>
* NoQuadraticResidueException:<br>
* a = <tt>a</tt> is not a quadratic residue mod p = <tt>p</tt>.
*
* @param a
* the value to calculate the square root from
* @param p
* characteristic of the underlying field
*/
public NoQuadraticResidueException(FlexiBigInt a, FlexiBigInt p) {
super("NoQuadraticResidueException:\na = " + a + " is not"
+ "a quadratic residue mod p = " + p + ".");
}
}

View File

@@ -0,0 +1,224 @@
package de.flexiprovider.common.math;
import java.math.BigInteger;
import de.flexiprovider.api.SecureRandom;
public final class FlexiBigInt {
private class JavaSecureRandom extends java.security.SecureRandom {
JavaSecureRandom(SecureRandom flexiRand) {
super(flexiRand, null);
}
}
public BigInteger bigInt;
public FlexiBigInt(byte[] val) {
bigInt = new BigInteger(val);
}
public FlexiBigInt(String val) {
bigInt = new BigInteger(val);
}
public FlexiBigInt(int signum, byte[] magnitude) {
bigInt = new BigInteger(signum, magnitude);
}
public FlexiBigInt(String val, int radix) {
bigInt = new BigInteger(val, radix);
}
public FlexiBigInt(int numBits, SecureRandom flexiRand) {
JavaSecureRandom javaRand = new JavaSecureRandom(flexiRand);
bigInt = new BigInteger(numBits, javaRand);
}
public FlexiBigInt(int bitLength, int certainty, SecureRandom flexiRand) {
JavaSecureRandom javaRand = new JavaSecureRandom(flexiRand);
bigInt = new BigInteger(bitLength, certainty, javaRand);
}
public FlexiBigInt(BigInteger bigInt) {
this.bigInt = bigInt;
}
public static FlexiBigInt valueOf(long val) {
return new FlexiBigInt(BigInteger.valueOf(val));
}
public static final FlexiBigInt ZERO = new FlexiBigInt(BigInteger.ZERO);
public static final FlexiBigInt ONE = valueOf(1);
public FlexiBigInt add(FlexiBigInt addend) {
return new FlexiBigInt(bigInt.add(addend.bigInt));
}
public FlexiBigInt subtract(FlexiBigInt minuend) {
return new FlexiBigInt(bigInt.subtract(minuend.bigInt));
}
public FlexiBigInt multiply(FlexiBigInt factor) {
return new FlexiBigInt(bigInt.multiply(factor.bigInt));
}
public FlexiBigInt divide(FlexiBigInt divisor) {
return new FlexiBigInt(bigInt.divide(divisor.bigInt));
}
public FlexiBigInt[] divideAndRemainder(FlexiBigInt divisor) {
BigInteger[] dar = bigInt.divideAndRemainder(divisor.bigInt);
return new FlexiBigInt[] { new FlexiBigInt(dar[0]),
new FlexiBigInt(dar[1]) };
}
public FlexiBigInt remainder(FlexiBigInt divisor) {
return new FlexiBigInt(bigInt.remainder(divisor.bigInt));
}
public FlexiBigInt pow(int exponent) {
return new FlexiBigInt(bigInt.pow(exponent));
}
public FlexiBigInt gcd(FlexiBigInt val) {
return new FlexiBigInt(bigInt.gcd(val.bigInt));
}
public FlexiBigInt abs() {
return new FlexiBigInt(bigInt.abs());
}
public FlexiBigInt negate() {
return new FlexiBigInt(bigInt.negate());
}
public int signum() {
return bigInt.signum();
}
public FlexiBigInt mod(FlexiBigInt modulus) {
return new FlexiBigInt(bigInt.mod(modulus.bigInt));
}
public FlexiBigInt modPow(FlexiBigInt exponent, FlexiBigInt modulus) {
return new FlexiBigInt(bigInt.modPow(exponent.bigInt, modulus.bigInt));
}
public FlexiBigInt modInverse(FlexiBigInt modulus) {
return new FlexiBigInt(bigInt.modInverse(modulus.bigInt));
}
public FlexiBigInt shiftLeft(int n) {
return new FlexiBigInt(bigInt.shiftLeft(n));
}
public FlexiBigInt shiftRight(int n) {
return new FlexiBigInt(bigInt.shiftRight(n));
}
public FlexiBigInt and(FlexiBigInt val) {
return new FlexiBigInt(bigInt.and(val.bigInt));
}
public FlexiBigInt or(FlexiBigInt val) {
return new FlexiBigInt(bigInt.or(val.bigInt));
}
public FlexiBigInt xor(FlexiBigInt val) {
return new FlexiBigInt(bigInt.xor(val.bigInt));
}
public FlexiBigInt not() {
return new FlexiBigInt(bigInt.not());
}
public FlexiBigInt andNot(FlexiBigInt val) {
return new FlexiBigInt(bigInt.andNot(val.bigInt));
}
public boolean testBit(int n) {
return bigInt.testBit(n);
}
public FlexiBigInt setBit(int n) {
return new FlexiBigInt(bigInt.setBit(n));
}
public FlexiBigInt clearBit(int n) {
return new FlexiBigInt(bigInt.clearBit(n));
}
public FlexiBigInt flipBit(int n) {
return new FlexiBigInt(bigInt.flipBit(n));
}
public int getLowestSetBit() {
return bigInt.getLowestSetBit();
}
public int bitLength() {
return bigInt.bitLength();
}
public int bitCount() {
return bigInt.bitCount();
}
public boolean isProbablePrime(int certainty) {
return bigInt.isProbablePrime(certainty);
}
public int compareTo(FlexiBigInt other) {
return bigInt.compareTo(other.bigInt);
}
public FlexiBigInt min(FlexiBigInt other) {
return new FlexiBigInt(bigInt.min(other.bigInt));
}
public FlexiBigInt max(FlexiBigInt other) {
return new FlexiBigInt(bigInt.max(other.bigInt));
}
public boolean equals(Object other) {
if (!(other instanceof FlexiBigInt)) {
return false;
}
return bigInt.equals(((FlexiBigInt) other).bigInt);
}
public int hashCode() {
return bigInt.hashCode();
}
public String toString(int radix) {
return bigInt.toString(radix);
}
public String toString() {
return bigInt.toString();
}
public byte[] toByteArray() {
return bigInt.toByteArray();
}
public int intValue() {
return bigInt.intValue();
}
public long longValue() {
return bigInt.longValue();
}
public float floatValue() {
return bigInt.floatValue();
}
public double doubleValue() {
return bigInt.doubleValue();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,278 @@
package de.flexiprovider.common.math;
/**
* Class of number-theory related functions providing J2ME conform
* implementations of functions contained in the java.lang.Math package but not
* provided for J2ME.
*
*
* @author Johannes Braun
*
*/
public final class MathFunctions {
private MathFunctions(){
//empty
}
/**
* Compute <tt>e<sup>exponent</sup></tt>
* J2ME conform implementation of the "Math.exp" function.
* @param exponent
* the exponent
* @return <tt>e<sup>exponent</sup></tt>
*/
public static double exp(double exponent) {
double d = exponent;
boolean negative = false;
double result = 1;
int iterations = 20;
if (d < 0) {
negative = true;
d *= -1;
}
if (d >= 1) {
int temp = (int) d;
double a=Math.E;
while (temp > 0) {
if ((temp & 1) == 1) {
result *=a;
}
a *= a;
temp >>>= 1;
}
if ((d - Math.floor(d)) == 0) {
if (negative) {
return 1 / result;
} else {
return result;
}
}
}
double temp = d - Math.floor(d);
double den = 1;
double num = 1;
double result2 = 1;
for (int i = 1; i < iterations; i++) {
den *= i;
num *= temp;
result2 += num / den;
}
if (negative) {
return 1 / (result * result2);
} else {
return result * result2;
}
}
/**
* calculate the logarithm to the base 2.
*
* @param x
* any double value
* @return log_2(x)
*/
public static double log(double x) {
if(x<=0)
throw new ArithmeticException("log(x) only defined for positive values");
if(x>0&&x<1){
double d= 1/x;
double result=-log(d);
return result;
}
int tmp=0;
double tmp2=1;
double d=x;
while(d>2){
d=d/2;
tmp+=1;
tmp2*=2;
}
double rem = x / tmp2;
rem = logBKM(rem);
return (double) tmp + rem;
}
/**
* calculate the logarithm to the base 2.
*
* @param x
* any long value >=1
* @return log_2(x)
*/
public static double log(long x) {
if(x<=0)
throw new ArithmeticException("log(x) only defined for positive values");
int tmp = IntegerFunctions.floorLog(FlexiBigInt.valueOf(x));
long tmp2 = 1l << tmp;
double rem = (double) x / (double) tmp2;
rem = logBKM(rem);
return (double) tmp + rem;
}
/**
* BKM Algorithm to calculate logarithms to the base 2.
*
* @param arg
* a double value with 1<= arg<= 4.768462058
*
* @return log_2(arg)
*/
private static double logBKM(double arg) {
if(arg<=0)
throw new ArithmeticException("logBKM(x) only defined for positive values");
double ae[] = // A_e[k] = log_2 (1 + 0.5^k)
{
1.0000000000000000000000000000000000000000000000000000000000000000000000000000,
0.5849625007211561814537389439478165087598144076924810604557526545410982276485,
0.3219280948873623478703194294893901758648313930245806120547563958159347765589,
0.1699250014423123629074778878956330175196288153849621209115053090821964552970,
0.0874628412503394082540660108104043540112672823448206881266090643866965081686,
0.0443941193584534376531019906736094674630459333742491317685543002674288465967,
0.0223678130284545082671320837460849094932677948156179815932199216587899627785,
0.0112272554232541203378805844158839407281095943600297940811823651462712311786,
0.0056245491938781069198591026740666017211096815383520359072957784732489771013,
0.0028150156070540381547362547502839489729507927389771959487826944878598909400,
0.0014081943928083889066101665016890524233311715793462235597709051792834906001,
0.0007042690112466432585379340422201964456668872087249334581924550139514213168,
0.0003521774803010272377989609925281744988670304302127133979341729842842377649,
0.0001760994864425060348637509459678580940163670081839283659942864068257522373,
0.0000880524301221769086378699983597183301490534085738474534831071719854721939,
0.0000440268868273167176441087067175806394819146645511899503059774914593663365,
0.0000220136113603404964890728830697555571275493801909791504158295359319433723,
0.0000110068476674814423006223021573490183469930819844945565597452748333526464,
0.0000055034343306486037230640321058826431606183125807276574241540303833251704,
0.0000027517197895612831123023958331509538486493412831626219340570294203116559,
0.0000013758605508411382010566802834037147561973553922354232704569052932922954,
0.0000006879304394358496786728937442939160483304056131990916985043387874690617,
0.0000003439652607217645360118314743718005315334062644619363447395987584138324,
0.0000001719826406118446361936972479533123619972434705828085978955697643547921,
0.0000000859913228686632156462565208266682841603921494181830811515318381744650,
0.0000000429956620750168703982940244684787907148132725669106053076409624949917,
0.0000000214978311976797556164155504126645192380395989504741781512309853438587,
0.0000000107489156388827085092095702361647949603617203979413516082280717515504,
0.0000000053744578294520620044408178949217773318785601260677517784797554422804,
0.0000000026872289172287079490026152352638891824761667284401180026908031182361,
0.0000000013436144592400232123622589569799954658536700992739887706412976115422,
0.0000000006718072297764289157920422846078078155859484240808550018085324187007,
0.0000000003359036149273187853169587152657145221968468364663464125722491530858,
0.0000000001679518074734354745159899223037458278711244127245990591908996412262,
0.0000000000839759037391617577226571237484864917411614198675604731728132152582,
0.0000000000419879518701918839775296677020135040214077417929807824842667285938,
0.0000000000209939759352486932678195559552767641474249812845414125580747434389,
0.0000000000104969879676625344536740142096218372850561859495065136990936290929,
0.0000000000052484939838408141817781356260462777942148580518406975851213868092,
0.0000000000026242469919227938296243586262369156865545638305682553644113887909,
0.0000000000013121234959619935994960031017850191710121890821178731821983105443,
0.0000000000006560617479811459709189576337295395590603644549624717910616347038,
0.0000000000003280308739906102782522178545328259781415615142931952662153623493,
0.0000000000001640154369953144623242936888032768768777422997704541618141646683,
0.0000000000000820077184976595619616930350508356401599552034612281802599177300,
0.0000000000000410038592488303636807330652208397742314215159774270270147020117,
0.0000000000000205019296244153275153381695384157073687186580546938331088730952,
0.0000000000000102509648122077001764119940017243502120046885379813510430378661,
0.0000000000000051254824061038591928917243090559919209628584150482483994782302,
0.0000000000000025627412030519318726172939815845367496027046030028595094737777,
0.0000000000000012813706015259665053515049475574143952543145124550608158430592,
0.0000000000000006406853007629833949364669629701200556369782295210193569318434,
0.0000000000000003203426503814917330334121037829290364330169106716787999052925,
0.0000000000000001601713251907458754080007074659337446341494733882570243497196,
0.0000000000000000800856625953729399268240176265844257044861248416330071223615,
0.0000000000000000400428312976864705191179247866966320469710511619971334577509,
0.0000000000000000200214156488432353984854413866994246781519154793320684126179,
0.0000000000000000100107078244216177339743404416874899847406043033792202127070,
0.0000000000000000050053539122108088756700751579281894640362199287591340285355,
0.0000000000000000025026769561054044400057638132352058574658089256646014899499,
0.0000000000000000012513384780527022205455634651853807110362316427807660551208,
0.0000000000000000006256692390263511104084521222346348012116229213309001913762,
0.0000000000000000003128346195131755552381436585278035120438976487697544916191,
0.0000000000000000001564173097565877776275512286165232838833090480508502328437,
0.0000000000000000000782086548782938888158954641464170239072244145219054734086,
0.0000000000000000000391043274391469444084776945327473574450334092075712154016,
0.0000000000000000000195521637195734722043713378812583900953755962557525252782,
0.0000000000000000000097760818597867361022187915943503728909029699365320287407,
0.0000000000000000000048880409298933680511176764606054809062553340323879609794,
0.0000000000000000000024440204649466840255609083961603140683286362962192177597,
0.0000000000000000000012220102324733420127809717395445504379645613448652614939,
0.0000000000000000000006110051162366710063906152551383735699323415812152114058,
0.0000000000000000000003055025581183355031953399739107113727036860315024588989,
0.0000000000000000000001527512790591677515976780735407368332862218276873443537,
0.0000000000000000000000763756395295838757988410584167137033767056170417508383,
0.0000000000000000000000381878197647919378994210346199431733717514843471513618,
0.0000000000000000000000190939098823959689497106436628681671067254111334889005,
0.0000000000000000000000095469549411979844748553534196582286585751228071408728,
0.0000000000000000000000047734774705989922374276846068851506055906657137209047,
0.0000000000000000000000023867387352994961187138442777065843718711089344045782,
0.0000000000000000000000011933693676497480593569226324192944532044984865894525,
0.0000000000000000000000005966846838248740296784614396011477934194852481410926,
0.0000000000000000000000002983423419124370148392307506484490384140516252814304,
0.0000000000000000000000001491711709562185074196153830361933046331030629430117,
0.0000000000000000000000000745855854781092537098076934460888486730708440475045,
0.0000000000000000000000000372927927390546268549038472050424734256652501673274,
0.0000000000000000000000000186463963695273134274519237230207489851150821191330,
0.0000000000000000000000000093231981847636567137259618916352525606281553180093,
0.0000000000000000000000000046615990923818283568629809533488457973317312233323,
0.0000000000000000000000000023307995461909141784314904785572277779202790023236,
0.0000000000000000000000000011653997730954570892157452397493151087737428485431,
0.0000000000000000000000000005826998865477285446078726199923328593402722606924,
0.0000000000000000000000000002913499432738642723039363100255852559084863397344,
0.0000000000000000000000000001456749716369321361519681550201473345138307215067,
0.0000000000000000000000000000728374858184660680759840775119123438968122488047,
0.0000000000000000000000000000364187429092330340379920387564158411083803465567,
0.0000000000000000000000000000182093714546165170189960193783228378441837282509,
0.0000000000000000000000000000091046857273082585094980096891901482445902524441,
0.0000000000000000000000000000045523428636541292547490048446022564529197237262,
0.0000000000000000000000000000022761714318270646273745024223029238091160103901};
int n= 53;
double x = 1;
double y = 0;
double z;
double s = 1;
int k;
for (k = 0; k < n; k++) {
z = x + x * s;
if (z <= arg) {
x = z;
y += ae[k];
}
s *= 0.5;
}
return y;
}
/**
* round a double value to its nearest long integer value
* @param d
* the double to be rounded
* @return the nearest long integer
*/
public static long round(double d){
return (long)((d >= 0) ? Math.floor(d+0.5) : Math.ceil(d-0.5));
}
/**
* round a double value to a specified number of decimal places
* @param d
* the double to be rounded
* @param digits
* the number of remaining decimal places after rounding
* @return the rounded double
*/
public static double round(double d, int digits) {
int m = IntegerFunctions.pow(10, digits);
double d2 = d * m;
double res =(d >= 0) ? Math.floor(d2+0.5) : Math.ceil(d2-0.5);
return res / m;
}
}

Some files were not shown because too many files have changed in this diff Show More