Major merge with Classpath.
Removed many duplicate files. * HACKING: Updated.x * classpath: Imported new directory. * standard.omit: New file. * Makefile.in, aclocal.m4, configure: Rebuilt. * sources.am: New file. * configure.ac: Run Classpath configure script. Moved code around to support. Disable xlib AWT peers (temporarily). * Makefile.am (SUBDIRS): Added 'classpath' (JAVAC): Removed. (AM_CPPFLAGS): Added more -I options. (BOOTCLASSPATH): Simplified. Completely redid how sources are built. Include sources.am. * include/Makefile.am (tool_include__HEADERS): Removed jni.h. * include/jni.h: Removed (in Classpath). * scripts/classes.pl: Updated to look at built classes. * scripts/makemake.tcl: New file. * testsuite/libjava.jni/jni.exp (gcj_jni_compile_c_to_so): Added -I options. (gcj_jni_invocation_compile_c_to_binary): Likewise. From-SVN: r102082
This commit is contained in:
@@ -1,317 +0,0 @@
|
||||
/* BitString.java -- Java representation of the BIT STRING type.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.security.der;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Immutable representation of a bit string, which is equivalent to a
|
||||
* byte array except some number of the rightmost bits are ignored. For
|
||||
* example, this could be the bit string:
|
||||
*
|
||||
* <pre> 00010101 11101101 11010xxx</pre>
|
||||
*
|
||||
* <p>Where the "xxx" represents three bits that should be ignored, and
|
||||
* can have any value.
|
||||
*
|
||||
* @author Casey Marshall (csm@gnu.org)
|
||||
*/
|
||||
public class BitString implements Cloneable, Comparable
|
||||
{
|
||||
|
||||
// Fields.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** The bits themselves. */
|
||||
private final byte[] bytes;
|
||||
|
||||
/**
|
||||
* The exportable byte array. This array has the ignored bits
|
||||
* removed.
|
||||
*/
|
||||
private transient byte[] externBytes;
|
||||
|
||||
/** The number of bits ignored at the end of the byte array. */
|
||||
private final int ignoredBits;
|
||||
|
||||
/** This bit string as a boolean array. */
|
||||
private transient boolean[] boolVal;
|
||||
|
||||
// Constructors.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a new bit string, shifting the given byte array if needed.
|
||||
*
|
||||
* @param bytes The byte array holding the bit string.
|
||||
* @param ignoredBits The number of bits to ignore.
|
||||
* @param doShift Pass true in this parameter if the byte array has
|
||||
* not yet been shifted left by <i>ignoredBits</i>.
|
||||
* @throws IllegalArgumentException If <i>ignoredBits</i> is negative
|
||||
* or greater than 7.
|
||||
* @throws NullPointerException If <i>bytes</i> is null.
|
||||
*/
|
||||
public BitString(byte[] bytes, int ignoredBits, boolean doShift)
|
||||
{
|
||||
this(bytes, 0, bytes.length, ignoredBits, doShift);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new bit string, shifting the given byte array if needed.
|
||||
*
|
||||
* @param bytes The byte array holding the bit string.
|
||||
* @param offset The offset where the meaningful bytes begin.
|
||||
* @param length The number of meaningful bytes.
|
||||
* @param ignoredBits The number of bits to ignore.
|
||||
* @param doShift Pass true in this parameter if the byte array has
|
||||
* not yet been shifted left by <i>ignoredBits</i>.
|
||||
* @throws IllegalArgumentException If <i>ignoredBits</i> is negative
|
||||
* or greater than 7.
|
||||
* @throws NullPointerException If <i>bytes</i> is null.
|
||||
*/
|
||||
public BitString(byte[] bytes, int offset, int length,
|
||||
int ignoredBits, boolean doShift)
|
||||
{
|
||||
if (ignoredBits < 0 || ignoredBits > 7)
|
||||
throw new IllegalArgumentException();
|
||||
if (bytes == null)
|
||||
throw new NullPointerException();
|
||||
if (doShift && ignoredBits > 0)
|
||||
{
|
||||
this.externBytes = new byte[length];
|
||||
System.arraycopy(bytes, offset, externBytes, 0, length);
|
||||
this.bytes = new BigInteger(externBytes).shiftLeft(ignoredBits)
|
||||
.toByteArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.bytes = new byte[length];
|
||||
System.arraycopy(bytes, offset, this.bytes, 0, length);
|
||||
}
|
||||
this.ignoredBits = ignoredBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new bit string.
|
||||
*
|
||||
* @param bytes The byte array holding the bit string.
|
||||
* @param offset The offset where the meaningful bytes begin.
|
||||
* @param length The number of meaningful bytes.
|
||||
* @param ignoredBits The number of bits to ignore.
|
||||
* @throws IllegalArgumentException If <i>ignoredBits</i> is negative
|
||||
* or greater than 7.
|
||||
* @throws NullPointerException If <i>bytes</i> is null.
|
||||
*/
|
||||
public BitString(byte[] bytes, int offset, int length, int ignoredBits)
|
||||
{
|
||||
this(bytes, offset, length, ignoredBits, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new bit string.
|
||||
*
|
||||
* @param bytes The byte array holding the bit string.
|
||||
* @param ignoredBits The number of bits to ignore.
|
||||
* @throws IllegalArgumentException If <i>ignoredBits</i> is negative
|
||||
* or greater than 7.
|
||||
* @throws NullPointerException If <i>bytes</i> is null.
|
||||
*/
|
||||
public BitString(byte[] bytes, int ignoredBits)
|
||||
{
|
||||
this(bytes, 0, bytes.length, ignoredBits, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new bit string.
|
||||
*
|
||||
* @param bytes The byte array holding the bit string.
|
||||
* @param offset The offset where the meaningful bytes begin.
|
||||
* @param length The number of meaningful bytes.
|
||||
* @throws NullPointerException If <i>bytes</i> is null.
|
||||
*/
|
||||
public BitString(byte[] bytes, int offset, int length)
|
||||
{
|
||||
this(bytes, offset, length, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new bit string.
|
||||
*
|
||||
* @param bytes The byte array holding the bit string.
|
||||
* @throws NullPointerException If <i>bytes</i> is null.
|
||||
*/
|
||||
public BitString(byte[] bytes)
|
||||
{
|
||||
this(bytes, 0, bytes.length, 0, false);
|
||||
}
|
||||
|
||||
// Instance methods.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return this bit string as a byte array, with the ignored bits
|
||||
* trimmed off. The byte array is cloned every time this method is
|
||||
* called to prevent modification.
|
||||
*
|
||||
* @return The trimmed byte array.
|
||||
*/
|
||||
public byte[] toByteArray()
|
||||
{
|
||||
if (ignoredBits == 0)
|
||||
return (byte[]) bytes.clone();
|
||||
if (externBytes == null)
|
||||
externBytes = new BigInteger(bytes).shiftRight(ignoredBits).toByteArray();
|
||||
return (byte[]) externBytes.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this bit string as a byte array, with the ignored bits
|
||||
* present. The byte array is cloned every time this method is
|
||||
* called to prevent modification.
|
||||
*
|
||||
* @return The byte array.
|
||||
*/
|
||||
public byte[] getShiftedByteArray()
|
||||
{
|
||||
return (byte[]) bytes.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of ignored bits.
|
||||
*
|
||||
* @return The number of ignored bits.
|
||||
*/
|
||||
public int getIgnoredBits()
|
||||
{
|
||||
return ignoredBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size, in bits, of this bit string.
|
||||
*
|
||||
* @return The size of this bit string.
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
return (bytes.length << 3) - ignoredBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this bit string as a boolean array. The value returned is of
|
||||
* size {@link #size()}, and each <code>true</code> value
|
||||
* corresponding to each "1" in this bit string. The boolean array is
|
||||
* cloned before it is returned.
|
||||
*
|
||||
* @return The boolean array.
|
||||
*/
|
||||
public boolean[] toBooleanArray()
|
||||
{
|
||||
if (boolVal == null)
|
||||
{
|
||||
boolVal = new boolean[size()];
|
||||
for (int i = 0, j = 7, k = 0; i < boolVal.length; i++)
|
||||
{
|
||||
boolVal[i] = (bytes[k] & 1 << j--) != 0;
|
||||
if (j < 0)
|
||||
{
|
||||
j = 7;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (boolean[]) boolVal.clone();
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
try
|
||||
{
|
||||
return super.clone();
|
||||
}
|
||||
catch (CloneNotSupportedException cce)
|
||||
{
|
||||
throw new InternalError(cce.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public int compareTo(Object o)
|
||||
{
|
||||
BitString that = (BitString) o;
|
||||
if (this.equals(that))
|
||||
return 0;
|
||||
if (this.bytes.length != that.bytes.length)
|
||||
return (this.bytes.length < that.bytes.length) ? -1 : 1;
|
||||
if (this.ignoredBits != that.ignoredBits)
|
||||
return (this.ignoredBits < that.ignoredBits) ? -1 : 1;
|
||||
for (int i = 0; i < this.bytes.length; i++)
|
||||
if (this.bytes[i] != that.bytes[i])
|
||||
return (this.bytes[i] < that.bytes[i]) ? -1 : 1;
|
||||
return 0; // not reached.
|
||||
}
|
||||
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (!(o instanceof BitString))
|
||||
return false;
|
||||
BitString that = (BitString) o;
|
||||
// True for cloned instances.
|
||||
if (this.bytes == that.bytes && this.ignoredBits == that.ignoredBits)
|
||||
return true;
|
||||
if (this.ignoredBits == that.ignoredBits)
|
||||
return Arrays.equals(this.bytes, that.bytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0, j = 7, k = 0; i < size(); i++)
|
||||
{
|
||||
sb.append((bytes[k] & 1 << j) != 0 ? "1" : "0");
|
||||
j--;
|
||||
if (j < 0)
|
||||
{
|
||||
j = 7;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/* DER.java -- Basic constants in DER sequences.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.security.der;
|
||||
|
||||
/**
|
||||
* The set of tags for DER types.
|
||||
*
|
||||
* @author Casey Marshall (csm@gnu.org)
|
||||
*/
|
||||
public interface DER
|
||||
{
|
||||
int UNIVERSAL = 0x00;
|
||||
int APPLICATION = 0x40;
|
||||
int CONTEXT = 0x80;
|
||||
int PRIVATE = 0xC0;
|
||||
|
||||
int CONSTRUCTED = 0x20;
|
||||
|
||||
int ANY = 0x00;
|
||||
int BOOLEAN = 0x01;
|
||||
int INTEGER = 0x02;
|
||||
int BIT_STRING = 0x03;
|
||||
int OCTET_STRING = 0x04;
|
||||
int NULL = 0x05;
|
||||
int OBJECT_IDENTIFIER = 0x06;
|
||||
int REAL = 0x09;
|
||||
int ENUMERATED = 0x0a;
|
||||
int RELATIVE_OID = 0x0d;
|
||||
|
||||
int SEQUENCE = 0x10;
|
||||
int SET = 0x11;
|
||||
|
||||
Object CONSTRUCTED_VALUE = new Object();
|
||||
|
||||
int NUMERIC_STRING = 0x12;
|
||||
int PRINTABLE_STRING = 0x13;
|
||||
int T61_STRING = 0x14;
|
||||
int VIDEOTEX_STRING = 0x15;
|
||||
int IA5_STRING = 0x16;
|
||||
int GRAPHIC_STRING = 0x19;
|
||||
int ISO646_STRING = 0x1A;
|
||||
int GENERAL_STRING = 0x1B;
|
||||
|
||||
int UTF8_STRING = 0x0C;
|
||||
int UNIVERSAL_STRING = 0x1C;
|
||||
int BMP_STRING = 0x1E;
|
||||
|
||||
int UTC_TIME = 0x17;
|
||||
int GENERALIZED_TIME = 0x18;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/* DEREncodingException.java --- DER Encoding Exception
|
||||
Copyright (C) 1999,2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.security.der;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DEREncodingException extends IOException
|
||||
{
|
||||
public DEREncodingException()
|
||||
{
|
||||
super ();
|
||||
}
|
||||
|
||||
public DEREncodingException (String msg)
|
||||
{
|
||||
super (msg);
|
||||
}
|
||||
}
|
||||
@@ -1,437 +0,0 @@
|
||||
/* DERReader.java -- parses ASN.1 DER sequences
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.security.der;
|
||||
|
||||
import gnu.java.security.OID;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* This class decodes DER sequences into Java objects. The methods of
|
||||
* this class do not have knowledge of higher-levels of structure in the
|
||||
* DER stream -- such as ASN.1 constructions -- and it is therefore up
|
||||
* to the calling application to determine if the data are structured
|
||||
* properly by inspecting the {@link DERValue} that is returned.
|
||||
*
|
||||
* @author Casey Marshall (csm@gnu.org)
|
||||
*/
|
||||
public class DERReader implements DER
|
||||
{
|
||||
|
||||
// Fields.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
protected InputStream in;
|
||||
|
||||
protected final ByteArrayOutputStream encBuf;
|
||||
|
||||
// Constructor.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a new DER reader from a byte array.
|
||||
*
|
||||
* @param in The encoded bytes.
|
||||
*/
|
||||
public DERReader(byte[] in)
|
||||
{
|
||||
this(new ByteArrayInputStream(in));
|
||||
}
|
||||
|
||||
public DERReader (byte[] in, int off, int len)
|
||||
{
|
||||
this (new ByteArrayInputStream (in, off, len));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DER readed from an input stream.
|
||||
*
|
||||
* @param in The encoded bytes.
|
||||
*/
|
||||
public DERReader(InputStream in)
|
||||
{
|
||||
if (!in.markSupported())
|
||||
this.in = new BufferedInputStream(in, 16384);
|
||||
else
|
||||
this.in = in;
|
||||
encBuf = new ByteArrayOutputStream(2048);
|
||||
}
|
||||
|
||||
// Class methods.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Convenience method for reading a single primitive value from the
|
||||
* given byte array.
|
||||
*
|
||||
* @param encoded The encoded bytes.
|
||||
* @throws IOException If the bytes do not represent an encoded
|
||||
* object.
|
||||
*/
|
||||
public static DERValue read(byte[] encoded) throws IOException
|
||||
{
|
||||
return new DERReader(encoded).read();
|
||||
}
|
||||
|
||||
// Instance methods.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
public void skip (int bytes) throws IOException
|
||||
{
|
||||
in.skip (bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a single value from the input stream, returning it in a new
|
||||
* {@link DERValue}. By "single value" we mean any single type in its
|
||||
* entirety -- including constructed types such as SEQUENCE and all
|
||||
* the values they contain. Usually it is sufficient to call this
|
||||
* method once to parse and return the top-level structure, then to
|
||||
* inspect the returned value for the proper contents.
|
||||
*
|
||||
* @return The parsed DER structure.
|
||||
* @throws IOException If an error occurs reading from the input
|
||||
* stream.
|
||||
* @throws DEREncodingException If the input does not represent a
|
||||
* valid DER stream.
|
||||
*/
|
||||
public DERValue read() throws IOException
|
||||
{
|
||||
int tag = in.read();
|
||||
if (tag == -1)
|
||||
throw new EOFException();
|
||||
encBuf.write(tag);
|
||||
int len = readLength();
|
||||
DERValue value = null;
|
||||
if ((tag & CONSTRUCTED) == CONSTRUCTED)
|
||||
{
|
||||
in.mark(2048);
|
||||
byte[] encoded = new byte[len];
|
||||
in.read(encoded);
|
||||
encBuf.write(encoded);
|
||||
value = new DERValue(tag, len, CONSTRUCTED_VALUE, encBuf.toByteArray());
|
||||
in.reset();
|
||||
encBuf.reset();
|
||||
return value;
|
||||
}
|
||||
switch (tag & 0xC0)
|
||||
{
|
||||
case UNIVERSAL:
|
||||
value = new DERValue(tag, len, readUniversal(tag, len),
|
||||
encBuf.toByteArray());
|
||||
encBuf.reset();
|
||||
break;
|
||||
case CONTEXT:
|
||||
byte[] encoded = new byte[len];
|
||||
in.read(encoded);
|
||||
encBuf.write(encoded);
|
||||
value = new DERValue(tag, len, encoded, encBuf.toByteArray());
|
||||
encBuf.reset();
|
||||
break;
|
||||
case APPLICATION:
|
||||
// This should not be reached, since (I think) APPLICATION is
|
||||
// always constructed.
|
||||
throw new DEREncodingException("non-constructed APPLICATION data");
|
||||
default:
|
||||
throw new DEREncodingException("PRIVATE class not supported");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected int readLength() throws IOException
|
||||
{
|
||||
int i = in.read();
|
||||
if (i == -1)
|
||||
throw new EOFException();
|
||||
encBuf.write(i);
|
||||
if ((i & ~0x7F) == 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
else if (i < 0xFF)
|
||||
{
|
||||
byte[] octets = new byte[i & 0x7F];
|
||||
in.read(octets);
|
||||
encBuf.write(octets);
|
||||
return new BigInteger(1, octets).intValue();
|
||||
}
|
||||
throw new DEREncodingException();
|
||||
}
|
||||
|
||||
// Own methods.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
private Object readUniversal(int tag, int len) throws IOException
|
||||
{
|
||||
byte[] value = new byte[len];
|
||||
in.read(value);
|
||||
encBuf.write(value);
|
||||
switch (tag & 0x1F)
|
||||
{
|
||||
case BOOLEAN:
|
||||
if (value.length != 1)
|
||||
throw new DEREncodingException();
|
||||
return Boolean.valueOf(value[0] != 0);
|
||||
case NULL:
|
||||
if (len != 0)
|
||||
throw new DEREncodingException();
|
||||
return null;
|
||||
case INTEGER:
|
||||
case ENUMERATED:
|
||||
return new BigInteger(value);
|
||||
case BIT_STRING:
|
||||
byte[] bits = new byte[len - 1];
|
||||
System.arraycopy(value, 1, bits, 0, bits.length);
|
||||
return new BitString(bits, value[0] & 0xFF);
|
||||
case OCTET_STRING:
|
||||
return value;
|
||||
case NUMERIC_STRING:
|
||||
case PRINTABLE_STRING:
|
||||
case T61_STRING:
|
||||
case VIDEOTEX_STRING:
|
||||
case IA5_STRING:
|
||||
case GRAPHIC_STRING:
|
||||
case ISO646_STRING:
|
||||
case GENERAL_STRING:
|
||||
case UNIVERSAL_STRING:
|
||||
case BMP_STRING:
|
||||
case UTF8_STRING:
|
||||
return makeString(tag, value);
|
||||
case UTC_TIME:
|
||||
case GENERALIZED_TIME:
|
||||
return makeTime(tag, value);
|
||||
case OBJECT_IDENTIFIER:
|
||||
return new OID(value);
|
||||
case RELATIVE_OID:
|
||||
return new OID(value, true);
|
||||
default:
|
||||
throw new DEREncodingException("unknown tag " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
private static String makeString(int tag, byte[] value)
|
||||
throws IOException
|
||||
{
|
||||
switch (tag & 0x1F)
|
||||
{
|
||||
case NUMERIC_STRING:
|
||||
case PRINTABLE_STRING:
|
||||
case T61_STRING:
|
||||
case VIDEOTEX_STRING:
|
||||
case IA5_STRING:
|
||||
case GRAPHIC_STRING:
|
||||
case ISO646_STRING:
|
||||
case GENERAL_STRING:
|
||||
return fromIso88591(value);
|
||||
|
||||
case UNIVERSAL_STRING:
|
||||
// XXX The docs say UniversalString is encoded in four bytes
|
||||
// per character, but Java has no support (yet) for UTF-32.
|
||||
//return new String(buf, "UTF-32");
|
||||
case BMP_STRING:
|
||||
return fromUtf16Be(value);
|
||||
|
||||
case UTF8_STRING:
|
||||
return fromUtf8(value);
|
||||
|
||||
default:
|
||||
throw new DEREncodingException("unknown string tag");
|
||||
}
|
||||
}
|
||||
|
||||
private static String fromIso88591(byte[] bytes)
|
||||
{
|
||||
StringBuffer str = new StringBuffer(bytes.length);
|
||||
for (int i = 0; i < bytes.length; i++)
|
||||
str.append((char) (bytes[i] & 0xFF));
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
private static String fromUtf16Be(byte[] bytes) throws IOException
|
||||
{
|
||||
if ((bytes.length & 0x01) != 0)
|
||||
throw new IOException("UTF-16 bytes are odd in length");
|
||||
StringBuffer str = new StringBuffer(bytes.length / 2);
|
||||
for (int i = 0; i < bytes.length; i += 2)
|
||||
{
|
||||
char c = (char) ((bytes[i] << 8) & 0xFF);
|
||||
c |= (char) (bytes[i+1] & 0xFF);
|
||||
str.append(c);
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
private static String fromUtf8(byte[] bytes) throws IOException
|
||||
{
|
||||
StringBuffer str = new StringBuffer((int)(bytes.length / 1.5));
|
||||
for (int i = 0; i < bytes.length; )
|
||||
{
|
||||
char c = 0;
|
||||
if ((bytes[i] & 0xE0) == 0xE0)
|
||||
{
|
||||
if ((i + 2) >= bytes.length)
|
||||
throw new IOException("short UTF-8 input");
|
||||
c = (char) ((bytes[i++] & 0x0F) << 12);
|
||||
if ((bytes[i] & 0x80) != 0x80)
|
||||
throw new IOException("malformed UTF-8 input");
|
||||
c |= (char) ((bytes[i++] & 0x3F) << 6);
|
||||
if ((bytes[i] & 0x80) != 0x80)
|
||||
throw new IOException("malformed UTF-8 input");
|
||||
c |= (char) (bytes[i++] & 0x3F);
|
||||
}
|
||||
else if ((bytes[i] & 0xC0) == 0xC0)
|
||||
{
|
||||
if ((i + 1) >= bytes.length)
|
||||
throw new IOException("short input");
|
||||
c = (char) ((bytes[i++] & 0x1F) << 6);
|
||||
if ((bytes[i] & 0x80) != 0x80)
|
||||
throw new IOException("malformed UTF-8 input");
|
||||
c |= (char) (bytes[i++] & 0x3F);
|
||||
}
|
||||
else if ((bytes[i] & 0xFF) < 0x80)
|
||||
{
|
||||
c = (char) (bytes[i++] & 0xFF);
|
||||
}
|
||||
else
|
||||
throw new IOException("badly formed UTF-8 sequence");
|
||||
str.append(c);
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
private Date makeTime(int tag, byte[] value) throws IOException
|
||||
{
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
String str = makeString(PRINTABLE_STRING, value);
|
||||
|
||||
// Classpath's SimpleDateFormat does not work for parsing these
|
||||
// types of times, so we do this by hand.
|
||||
String date = str;
|
||||
String tz = "";
|
||||
if (str.indexOf("+") > 0)
|
||||
{
|
||||
date = str.substring(0, str.indexOf("+"));
|
||||
tz = str.substring(str.indexOf("+"));
|
||||
}
|
||||
else if (str.indexOf("-") > 0)
|
||||
{
|
||||
date = str.substring(0, str.indexOf("-"));
|
||||
tz = str.substring(str.indexOf("-"));
|
||||
}
|
||||
else if (str.endsWith("Z"))
|
||||
{
|
||||
date = str.substring(0, str.length()-2);
|
||||
tz = "Z";
|
||||
}
|
||||
if (!tz.equals("Z") && tz.length() > 0)
|
||||
calendar.setTimeZone(TimeZone.getTimeZone(tz));
|
||||
else
|
||||
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
if ((tag & 0x1F) == UTC_TIME)
|
||||
{
|
||||
if (date.length() < 10) // must be at least 10 chars long
|
||||
throw new DEREncodingException("cannot parse date");
|
||||
// UTCTime is of the form "yyMMddHHmm[ss](Z|(+|-)hhmm)"
|
||||
try
|
||||
{
|
||||
int year = Integer.parseInt(str.substring(0, 2));
|
||||
if (year < 50)
|
||||
year += 2000;
|
||||
else
|
||||
year += 1900;
|
||||
calendar.set(year,
|
||||
Integer.parseInt(str.substring( 2, 4))-1, // month
|
||||
Integer.parseInt(str.substring( 4, 6)), // day
|
||||
Integer.parseInt(str.substring( 6, 8)), // hour
|
||||
Integer.parseInt(str.substring( 8, 10))); // minute
|
||||
if (date.length() == 12);
|
||||
calendar.set(Calendar.SECOND,
|
||||
Integer.parseInt(str.substring(10, 12)));
|
||||
}
|
||||
catch (NumberFormatException nfe)
|
||||
{
|
||||
throw new DEREncodingException("cannot parse date");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (date.length() < 10) // must be at least 10 chars long
|
||||
throw new DEREncodingException("cannot parse date");
|
||||
// GeneralTime is of the form "yyyyMMddHH[mm[ss[(.|,)SSSS]]]"
|
||||
// followed by "Z" or "(+|-)hh[mm]"
|
||||
try
|
||||
{
|
||||
calendar.set(
|
||||
Integer.parseInt(date.substring(0, 4)), // year
|
||||
Integer.parseInt(date.substring(4, 6))-1, // month
|
||||
Integer.parseInt(date.substring(6, 8)), // day
|
||||
Integer.parseInt(date.substring(8, 10)), 0); // hour, min
|
||||
switch (date.length())
|
||||
{
|
||||
case 19:
|
||||
case 18:
|
||||
case 17:
|
||||
case 16:
|
||||
calendar.set(Calendar.MILLISECOND,
|
||||
Integer.parseInt(date.substring(15)));
|
||||
case 14:
|
||||
calendar.set(Calendar.SECOND,
|
||||
Integer.parseInt(date.substring(12, 14)));
|
||||
case 12:
|
||||
calendar.set(Calendar.MINUTE,
|
||||
Integer.parseInt(date.substring(10, 12)));
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException nfe)
|
||||
{
|
||||
throw new DEREncodingException("cannot parse date");
|
||||
}
|
||||
}
|
||||
return calendar.getTime();
|
||||
}
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
/* DERValue.java -- a value read or written to a DER encoding.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.security.der;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DERValue implements DER
|
||||
{
|
||||
|
||||
// Fields.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
private final int tagClass;
|
||||
private final boolean constructed;
|
||||
private final int tag;
|
||||
private int length;
|
||||
private final Object value;
|
||||
private byte[] encoded;
|
||||
|
||||
// Constructor.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
public DERValue(int tag, int length, Object value, byte[] encoded)
|
||||
{
|
||||
tagClass = tag & 0xC0;
|
||||
this.tag = tag & 0x1F;
|
||||
constructed = (tag & CONSTRUCTED) == CONSTRUCTED;
|
||||
this.length = length;
|
||||
this.value = value;
|
||||
if (encoded != null)
|
||||
this.encoded = (byte[]) encoded.clone();
|
||||
}
|
||||
|
||||
public DERValue(int tag, Object value)
|
||||
{
|
||||
this(tag, 0, value, null);
|
||||
}
|
||||
|
||||
// Instance methods.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
public int getExternalTag()
|
||||
{
|
||||
return tagClass | tag | (constructed ? 0x20 : 0x00);
|
||||
}
|
||||
|
||||
public int getTag()
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
|
||||
public int getTagClass()
|
||||
{
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
public boolean isConstructed()
|
||||
{
|
||||
return constructed;
|
||||
}
|
||||
|
||||
public int getLength()
|
||||
{
|
||||
if (encoded == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
length = DERWriter.write(out, this);
|
||||
encoded = out.toByteArray();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
encoded = new byte[0];
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
public Object getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public Object getValueAs (final int derType) throws IOException
|
||||
{
|
||||
byte[] encoded = getEncoded ();
|
||||
encoded[0] = (byte) derType;
|
||||
return DERReader.read (encoded).getValue ();
|
||||
}
|
||||
|
||||
public byte[] getEncoded()
|
||||
{
|
||||
if (encoded == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
length = DERWriter.write(out, this);
|
||||
encoded = out.toByteArray();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
encoded = new byte[0];
|
||||
}
|
||||
}
|
||||
return (byte[]) encoded.clone();
|
||||
}
|
||||
|
||||
public int getEncodedLength()
|
||||
{
|
||||
if (encoded == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
length = DERWriter.write(out, this);
|
||||
encoded = out.toByteArray();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
encoded = new byte[0];
|
||||
}
|
||||
}
|
||||
return encoded.length;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "DERValue [ tag=" + tag + ", class=" + tagClass + ", constructed="
|
||||
+ constructed + ", value=" + value + " ]";
|
||||
}
|
||||
}
|
||||
@@ -1,349 +0,0 @@
|
||||
/* DERWriter.java -- write Java types in DER format.
|
||||
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.security.der;
|
||||
|
||||
import gnu.java.security.OID;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Methods that allow various Java types to be written as a DER
|
||||
* (Distinguished Encoding Rules) stream to the specified output stream.
|
||||
* DER is used to encode ASN.1 constructions, but this class provides no
|
||||
* methods for interacting with ASN.1. Rather, callers should construct
|
||||
* their output objects properly for whatever ASN.1 construct is being
|
||||
* output.
|
||||
*
|
||||
* <p>This class only defines static methods; there are no instance
|
||||
* variables needed.
|
||||
*
|
||||
* @author Casey Marshall (csm@gnu.org)
|
||||
*/
|
||||
public class DERWriter implements DER
|
||||
{
|
||||
|
||||
// Constructors.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** This class only has static methods. */
|
||||
private DERWriter()
|
||||
{
|
||||
}
|
||||
|
||||
// Class methods.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
public static int write(OutputStream out, DERValue object)
|
||||
throws IOException
|
||||
{
|
||||
out.write(object.getExternalTag());
|
||||
Object value = object.getValue();
|
||||
if (value == null)
|
||||
{
|
||||
writeLength(out, 0);
|
||||
return 0;
|
||||
}
|
||||
if (value instanceof Boolean)
|
||||
return writeBoolean(out, (Boolean) value);
|
||||
else if (value instanceof BigInteger)
|
||||
return writeInteger(out, (BigInteger) value);
|
||||
else if (value instanceof Date)
|
||||
return writeDate(out, object.getExternalTag(), (Date) value);
|
||||
else if (value instanceof String)
|
||||
return writeString(out, object.getExternalTag(), (String) value);
|
||||
else if (value instanceof List)
|
||||
return writeSequence(out, (List) value);
|
||||
else if (value instanceof Set)
|
||||
return writeSet(out, (Set) value);
|
||||
else if (value instanceof BitString)
|
||||
return writeBitString(out, (BitString) value);
|
||||
else if (value instanceof OID)
|
||||
return writeOID(out, (OID) value);
|
||||
else if (value instanceof byte[])
|
||||
{
|
||||
writeLength(out, ((byte[]) value).length);
|
||||
out.write((byte[]) value);
|
||||
return ((byte[]) value).length;
|
||||
}
|
||||
else if (value instanceof DERValue)
|
||||
{
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
write(bout, (DERValue) value);
|
||||
byte[] buf = bout.toByteArray();
|
||||
writeLength(out, buf.length);
|
||||
out.write(buf);
|
||||
return buf.length;
|
||||
}
|
||||
else
|
||||
throw new DEREncodingException("cannot encode " + value.getClass().getName());
|
||||
}
|
||||
|
||||
public static int definiteEncodingSize(int length)
|
||||
{
|
||||
if (length < 128)
|
||||
return 1;
|
||||
else if (length < 256)
|
||||
return 2;
|
||||
else if (length < 65536)
|
||||
return 3;
|
||||
else if (length < 16777216)
|
||||
return 4;
|
||||
else
|
||||
return 5;
|
||||
}
|
||||
|
||||
// Own methods.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Write a BOOLEAN type to the given output stream.
|
||||
*
|
||||
* @param out The sink output stream.
|
||||
* @param b The boolean value to write.
|
||||
*/
|
||||
private static int writeBoolean(OutputStream out, Boolean b)
|
||||
throws IOException
|
||||
{
|
||||
writeLength(out, 1);
|
||||
if (b.booleanValue())
|
||||
out.write(0xFF);
|
||||
else
|
||||
out.write(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an INTEGER type to the given output stream.
|
||||
*
|
||||
* @param out The sink output stream.
|
||||
* @param integer The integer to write.
|
||||
*/
|
||||
private static int writeInteger(OutputStream out, BigInteger integer)
|
||||
throws IOException
|
||||
{
|
||||
byte[] bytes = integer.toByteArray();
|
||||
writeLength(out, bytes.length);
|
||||
out.write(bytes);
|
||||
return bytes.length;
|
||||
}
|
||||
|
||||
private static int writeSequence(OutputStream out, List sequence)
|
||||
throws IOException
|
||||
{
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
for (Iterator i = sequence.iterator(); i.hasNext(); )
|
||||
{
|
||||
write(bout, (DERValue) i.next());
|
||||
}
|
||||
byte[] buf = bout.toByteArray();
|
||||
writeLength(out, buf.length);
|
||||
out.write(buf);
|
||||
return buf.length;
|
||||
}
|
||||
|
||||
private static int writeSet(OutputStream out, Set set)
|
||||
throws IOException
|
||||
{
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
for (Iterator i = set.iterator(); i.hasNext(); )
|
||||
{
|
||||
write(bout, (DERValue) i.next());
|
||||
}
|
||||
byte[] buf = bout.toByteArray();
|
||||
writeLength(out, buf.length);
|
||||
out.write(buf);
|
||||
return buf.length;
|
||||
}
|
||||
|
||||
private static int writeOID(OutputStream out, OID oid)
|
||||
throws IOException
|
||||
{
|
||||
byte[] der = oid.getDER();
|
||||
writeLength(out, der.length);
|
||||
out.write(der);
|
||||
return der.length;
|
||||
}
|
||||
|
||||
private static int writeBitString(OutputStream out, BitString bs)
|
||||
throws IOException
|
||||
{
|
||||
byte[] buf = bs.getShiftedByteArray();
|
||||
out.write(buf.length + 1);
|
||||
out.write(bs.getIgnoredBits());
|
||||
out.write(buf);
|
||||
return buf.length;
|
||||
}
|
||||
|
||||
private static int writeString(OutputStream out, int tag, String str)
|
||||
throws IOException
|
||||
{
|
||||
byte[] b = null;
|
||||
switch (tag & 0x1F)
|
||||
{
|
||||
case NUMERIC_STRING:
|
||||
case PRINTABLE_STRING:
|
||||
case T61_STRING:
|
||||
case VIDEOTEX_STRING:
|
||||
case IA5_STRING:
|
||||
case GRAPHIC_STRING:
|
||||
case ISO646_STRING:
|
||||
case GENERAL_STRING:
|
||||
b = toIso88591(str);
|
||||
break;
|
||||
|
||||
case UNIVERSAL_STRING:
|
||||
case BMP_STRING:
|
||||
b = toUtf16Be(str);
|
||||
break;
|
||||
|
||||
case UTF8_STRING:
|
||||
default:
|
||||
b = toUtf8(str);
|
||||
break;
|
||||
}
|
||||
writeLength(out, b.length);
|
||||
out.write(b);
|
||||
return b.length;
|
||||
}
|
||||
|
||||
private static byte[] toIso88591(String string)
|
||||
{
|
||||
byte[] result = new byte[string.length()];
|
||||
for (int i = 0; i < string.length(); i++)
|
||||
result[i] = (byte) string.charAt(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static byte[] toUtf16Be(String string)
|
||||
{
|
||||
byte[] result = new byte[string.length() * 2];
|
||||
for (int i = 0; i < string.length(); i++)
|
||||
{
|
||||
result[i*2 ] = (byte) ((string.charAt(i) >>> 8) & 0xFF);
|
||||
result[i*2+1] = (byte) (string.charAt(i) & 0xFF);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static byte[] toUtf8(String string)
|
||||
{
|
||||
ByteArrayOutputStream buf =
|
||||
new ByteArrayOutputStream((int)(string.length() * 1.5));
|
||||
for (int i = 0; i < string.length(); i++)
|
||||
{
|
||||
char c = string.charAt(i);
|
||||
if (c < 0x0080)
|
||||
buf.write(c & 0xFF);
|
||||
else if (c < 0x0800)
|
||||
{
|
||||
buf.write(0xC0 | ((c >>> 6) & 0x3F));
|
||||
buf.write(0x80 | (c & 0x3F));
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.write(0xE0 | ((c >>> 12) & 0x0F));
|
||||
buf.write(0x80 | ((c >>> 6) & 0x3F));
|
||||
buf.write(0x80 | (c & 0x3F));
|
||||
}
|
||||
}
|
||||
return buf.toByteArray();
|
||||
}
|
||||
|
||||
private static int writeDate(OutputStream out, int tag, Date date)
|
||||
throws IOException
|
||||
{
|
||||
SimpleDateFormat sdf = null;
|
||||
if ((tag & 0x1F) == UTC_TIME)
|
||||
sdf = new SimpleDateFormat("yyMMddHHmmss'Z'");
|
||||
else
|
||||
sdf = new SimpleDateFormat("yyyyMMddHHmmss'.'SSS'Z'");
|
||||
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
byte[] b = sdf.format(date).getBytes("ISO-8859-1");
|
||||
writeLength(out, b.length);
|
||||
out.write(b);
|
||||
return b.length;
|
||||
}
|
||||
|
||||
// Package method.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
static void writeLength(OutputStream out, int len) throws IOException
|
||||
{
|
||||
if (len < 128)
|
||||
out.write(len);
|
||||
else if (len < 256)
|
||||
{
|
||||
out.write(0x81);
|
||||
out.write(len);
|
||||
}
|
||||
else if (len < 65536)
|
||||
{
|
||||
out.write(0x82);
|
||||
out.write(len >> 8);
|
||||
out.write(len);
|
||||
}
|
||||
else if (len < 16777216)
|
||||
{
|
||||
out.write(0x83);
|
||||
out.write(len >> 16);
|
||||
out.write(len >> 8);
|
||||
out.write(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.write(0x84);
|
||||
out.write(len >> 24);
|
||||
out.write(len >> 16);
|
||||
out.write(len >> 8);
|
||||
out.write(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user