xerdecoder.java
来自「JAVA的加密库之一」· Java 代码 · 共 769 行 · 第 1/2 页
JAVA
769 行
/* $Id: XerDecoder.java,v 1.1.1.1 2001/02/24 04:59:00 raif Exp $
*
* Copyright (C) 1997-2001 The Cryptix Foundation Limited. All rights reserved.
*
* Use, modification, copying and distribution of this software is subject to
* the terms and conditions of the Cryptix General Licence. You should have
* received a copy of the Cryptix General Licence along with this library; if
* not, you can download a copy from http://www.cryptix.org/
*/
package cryptix.asn1.encoding;
import cryptix.asn1.io.*;
import cryptix.asn1.lang.*;
import org.apache.log4j.Category;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.InputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.TimeZone;
/**
* A class to decode ASN.1 specifications according to the XML Encoding Rules.<p>
*
* @version $Revision: 1.1.1.1 $
* @author Raif S. Naffah
*/
public class XerDecoder extends ASNReader {
// Constants and vars
// ........................................................................
static Category cat = Category.getInstance(DerDecoder.class.getName());
/**
* The underlying input stream that supports mark() and reset().
*/
BufferedInputStream in;
// Constructor(s)
// ........................................................................
/**
* Trivial constructor for use by the Factory.
*/
public XerDecoder() {
super();
}
/**
* Private constructor for internal use.
*
* @param ba a byte array to become the underlying stream of the decoder.
*/
private XerDecoder(byte[] ba) {
this.in = new BufferedInputStream(new ByteArrayInputStream(ba), 10240);
}
// Class method(s)
// ........................................................................
/**
* A class method to compare similarity between 2 Tag instances. The
* comparison works on the Tag's class and value fields.
*
* @param tClass the tag's actual (read) class field.
* @param tValue the tag's actual (read) value field.
* @param xClass the expected tag's class field.
* @param xValue the expected tag's value field.
*/
private static final boolean
eval(int tClass, int xClass, int tValue, int xValue) {
cat.info("Comparing ["+tClass+", "+tValue+"] to ["+xClass+", "+xValue+"]");
if (tClass != xClass)
return (false);
if (tClass == Tag.APPLICATION || tClass == Tag.PRIVATE)
return (tValue == xValue);
if (tValue == xValue)
return (true);
if (xValue > 0x20) // compare unstructured values
xValue -= 0x20;
// equate PrintableString, IA5String and T61_STRING
if (xValue == Tag.PrintableString
|| xValue == Tag.IA5_STRING
|| xValue == Tag.T61_STRING)
return (tValue == Tag.PrintableString
|| tValue == Tag.IA5_STRING
|| tValue == Tag.T61_STRING);
// equate SEQUENCE, SEQUENCE OF, SET and SET OF
if (xValue == Tag.SEQUENCE
|| xValue == Tag.SEQUENCE_OF
|| xValue == Tag.SET
|| xValue == Tag.SET_OF)
return (tValue == Tag.SEQUENCE
|| tValue == Tag.SEQUENCE_OF
|| tValue == Tag.SET
|| tValue == Tag.SET_OF);
return (false);
}
private static final Date toDate(byte[] buffer) throws DerFormatException {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
int YY = (buffer[0]-'0')*10 + (buffer[1]-'0');
int MM = (buffer[2]-'0')*10 + (buffer[3]-'0') - 1;
int DD = (buffer[4]-'0')*10 + (buffer[5]-'0');
int hh = (buffer[6]-'0')*10 + (buffer[7]-'0');
int mm = (buffer[8]-'0')*10 + (buffer[9]-'0');
int ss = 0;
YY += YY <= 50 ? 2000 : 1900; // fails for 2051 and later
if (buffer[10] != 'Z') {
ss = (buffer[10]-'0')*10 + (buffer[11]-'0');
if (buffer[12] != 'Z')
throw new DerFormatException(Tag.UTC_TIME);
}
cal.set(YY, MM, DD, hh, mm, ss);
return (cal.getTime());
}
private static final String toOID(byte[] buffer) {
StringBuffer sb = new StringBuffer();
int length = buffer.length;
int i = 0;
if (--length >= 0) { // first byte is special
int b = buffer[i++] & 0xFF;
int first = (b < 40 ? 0 : (b < 80 ? 1 : 2));
int second = (b - first * 40);
sb.append(first).append(".").append(second);
}
while (length > 0) { // handle the rest
sb.append(".");
int sid = 0; // subid
int b;
do {
b = buffer[i++] & 0xFF;
sid = sid << 7 | (b & 0x7F);
} while (--length > 0 && (b & 0x80) == 0x80);
sb.append(sid);
}
String result = sb.toString();
return (result);
}
private static final Boolean toBoolean(byte[] buffer)
throws DerInvalidLengthException {
int length = buffer.length;
if (length != 1)
throw new DerInvalidLengthException(Tag.BOOLEAN, length, 1);
Boolean result = new Boolean(buffer[0] != 0x00);
return (result);
}
private static final void toNull(byte[] buffer)
throws DerInvalidLengthException {
int length = buffer.length;
if (length != 0)
throw new DerInvalidLengthException(Tag.NULL, length, 0);
}
// ASN1InputStream abstract methods implementation
// ........................................................................
/**
* Initialises this instance to decode from the designated input stream.
*
* @param is the designated input stream to decode.
* @exception IllegalStateException if this instance is already initialised
* with an input stream. Caller should close the previous stream before
* invoking this method again on a new input stream.
*/
public void open(InputStream is) {
if (in != null)
throw new IllegalStateException();
this.in = is instanceof BufferedInputStream
? (BufferedInputStream) is
: new BufferedInputStream(is, 10240);
}
/**
* Decodes an ANY from the input stream.
*
* @param obj the element to decode.
* @return the concrete object decoded from the underlying input stream.
* @exception DerObjectTooLargeException if the DER value of the length part
* exceeds 32-bit.
* @exception EOFException if the end-of-stream was encountered while
* decoding the element.
* @exception IOException if any other I/O related exception has occured.
*/
public IType decodeAny(IType obj) throws IOException {
cat.debug("==> decodeAny()");
String name = obj.getName();
Tag tag = null;
try {
tag = readTag();
} catch (EOFException x) {
throw new ASNElementNotFoundException("???");
}
int length = readLength();
byte[] buffer = new byte[length];
int actualLength = read(buffer);
if (actualLength == -1)
throw new EOFException();
if (actualLength != length)
throw new DerLengthMismatchException(actualLength, length);
IType result = null;
if (tag.getClazz() == Tag.UNIVERSAL)
switch (tag.getValue()) {
case Tag.BOOLEAN:
result = new ASNBoolean(name, tag, toBoolean(buffer));
break;
case Tag.INTEGER:
result = new ASNInteger(name, tag, new BigInteger(1, buffer));
break;
case Tag.BIT_STRING:
result = new ASNBitString(name, tag, buffer);
break;
case Tag.OCTET_STRING:
result = new ASNOctetString(name, tag, buffer);
break;
case Tag.NULL:
toNull(buffer); // throws an exception if malformed
result = new ASNNull(name, tag, new Object());
break;
case Tag.OBJECT_IDENTIFIER:
result = new ASNObjectIdentifier(name, tag, toOID(buffer));
break;
case Tag.PrintableString:
result = new ASNPrintableString(name, tag, new String(buffer, "US-ASCII"));
break;
case Tag.UTC_TIME:
result = new ASNUTCTime(name, tag, toDate(buffer));
break;
}
else
result = new ASNAny(name, tag, buffer);
cat.debug("<== decodeAny() --> "+result);
return result;
}
/**
* Decodes an OBJECT IDENTIFIER from the input stream.
*
* @param obj the element to decode.
* @return a String representation of the OID decoded from the stream.
* @exception ASNTagMismatchException if the element in the stream has a
* different tag to the designated one.
* @exception DerObjectTooLargeException if the DER value of the length part
* exceeds 32-bit.
* @exception EOFException if the end-of-stream was encountered while
* decoding the element.
* @exception IOException if any other I/O related exception has occured.
*/
public String decodeObjectIdentifier(IType obj) throws IOException {
cat.debug("==> decodeObjectIdentifier()");
Tag tag = obj.getTag();
byte[] buffer = readRaw(tag, Tag.OBJECT_IDENTIFIER);
String result = toOID(buffer);
cat.debug("<== decodeObjectIdentifier() --> "+result);
return result;
}
/**
* Decodes a NULL from the input stream.
*
* @param obj the element to decode.
* @exception ASNTagMismatchException if the element in the stream has a
* different tag to the designated one.
* @exception DerObjectTooLargeException if the DER value of the length part
* exceeds 32-bit.
* @exception DerInvalidLengthException if a mismatch between the expected
* and parsed size of the element's encoding is detected.
* @exception EOFException if the end-of-stream was encountered while
* decoding the element.
* @exception IOException if any other I/O related exception has occured.
*/
public void decodeNull(IType obj) throws IOException {
cat.debug("==> decodeNull()");
Tag tag = obj.getTag();
byte[] buffer = readRaw(tag, Tag.NULL);
toNull(buffer);
cat.debug("<== decodeNull()");
}
/**
* Decodes a BOOLEAN from the input stream.
*
* @param obj the element to decode.
* @return the concrete value of this ASN.1 type.
* @exception ASNTagMismatchException if the element in the stream has a
* different tag to the designated one.
* @exception DerObjectTooLargeException if the DER value of the length part
* exceeds 32-bit.
* @exception DerInvalidLengthException if a mismatch between the expected
* and parsed size of the element's encoding is detected.
* @exception EOFException if the end-of-stream was encountered while
* decoding the element.
* @exception IOException if any other I/O related exception has occured.
*/
public Boolean decodeBoolean(IType obj) throws IOException {
cat.debug("==> decodeBoolean("+tag+")");
Tag tag = obj.getTag();
byte[] buffer = readRaw(tag, Tag.BOOLEAN);
Boolean result = toBoolean(buffer);
cat.debug("<== decodeBoolean() --> "+result);
return result;
}
/**
* Decodes an INTEGER from the input stream.
*
* @param obj the element to decode.
* @return the concrete value of this ASN.1 type.
* @exception ASNTagMismatchException if the element in the stream has a
* different tag to the designated one.
* @exception DerObjectTooLargeException if the DER value of the length part
* exceeds 32-bit.
* @exception DerInvalidLengthException if a mismatch between the expected
* and parsed size of the element's encoding is detected.
* @exception EOFException if the end-of-stream was encountered while
* decoding the element.
* @exception IOException if any other I/O related exception has occured.
*/
public BigInteger decodeInteger(IType obj) throws IOException {
cat.debug("==> decodeInteger()");
Tag tag = obj.getTag();
byte[] buffer = readRaw(tag, Tag.INTEGER);
BigInteger result = new BigInteger(1, buffer);
cat.debug("<== decodeInteger() --> "+result);
return result;
}
/**
* Decodes a PrintableString from the input stream.
*
* @param tagValue the value of a Tag constant to differentiate between
* the different types of strings.
* @param obj the element to decode.
* @return the concrete value of this ASN.1 type.
* @exception ASNTagMismatchException if the element in the stream has a
* different tag to the designated one.
* @exception DerObjectTooLargeException if the DER value of the length part
* exceeds 32-bit.
* @exception DerInvalidLengthException if a mismatch between the expected
* and parsed size of the element's encoding is detected.
* @exception EOFException if the end-of-stream was encountered while
* decoding the element.
* @exception IOException if any other I/O related exception has occured.
*/
public String decodeString(int tagValue, IType obj) throws IOException {
cat.debug("==> decodeString()");
Tag tag = obj.getTag();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?