📄 derdecoder.java
字号:
/**
* Decodes a UTCTime from the input stream.
*
* @param obj the element to decode.
* @return the concrete value of this ASN.1 type.
* @exception TagMismatchException 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 Date decodeUTCTime(IType obj) throws IOException {
cat.debug("==> decodeUTCTime()");
Tag tag = obj.tag();
byte[] buffer = readRaw(tag, Tag.UTC_TIME);
Date result = toDate(buffer);
cat.debug("<== decodeUTCTime() --> "+result);
return result;
}
/**
* Decodes a GeneralizedTime from the input stream.
*
* @param obj the element to decode.
* @return the concrete value of this ASN.1 type.
* @exception TagMismatchException 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 Date decodeGeneralizedTime(IType obj) throws IOException {
cat.debug("==> decodeGeneralizedTime()");
Tag tag = obj.tag();
byte[] buffer = readRaw(tag, Tag.GENERALIZED_TIME);
Date result = toFullDate(buffer);
cat.debug("<== decodeGeneralizedTime() --> "+result);
return result;
}
/**
* Decodes a compound type (SEQUENCE/SET [OF]) from the input stream.
*
* @param obj the compound element to decode.
* @return a Decoder that parses the input stream according to the same
* encoding rules as this one.
* @exception TagMismatchException 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 DerLengthMismatchException if a mismatch between the expected
* (parsed) and actual (read) 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 ASNReader decodeStructure(IType obj) throws IOException {
cat.debug("==> decodeStructure()");
Tag tag = obj.tag();
byte[] buffer = readRaw(tag, Tag.SEQUENCE);
DerDecoder result = new DerDecoder(buffer);
cat.debug("<== decodeStructure() --> "+result);
return result;
}
// InputStream methods implementation
// .......................................................................
/**
* Reads the next byte of data from the underlying input stream. The value
* byte is returned as an <tt>int</tt> in the range <tt>0</tt> to <tt>255</tt>.
* Contrary to the normal <tt>java.io.InputStream</tt> contract, if no
* byte is available because the end of the stream has been reached, this
* method throws a <tt>java.io.EOFException</tt>. This method blocks until
* input data is available, the end of the stream is detected, or another
* exception is thrown.
*
* @return the next byte of data.
* @exception java.io.EOFException the end-of-stream was detected.
* @exception java.io.IOException if an I/O error occurs.
*/
public int read() throws IOException {
int result = in.read();
if (result == -1)
throw new EOFException();
return (result & 0xFF);
}
/**
* Closes the underlying input stream and releases any system resources
* associated with it.
*
* @exception java.io.IOException if an I/O error occurs.
*/
public void close() throws IOException {
if (in != null) {
try {
in.close();
} catch (IOException ignored) {
cat.warn("I/O exception while closing the stream: "+ignored.getMessage());
}
in = null;
}
}
/**
* Marks the current position in the underlying input stream. A subsequent
* call to the <tt>reset()</tt> method repositions that stream at the last
* marked position so that subsequent reads re-read the same byte(s).<p>
*
* The <tt>readlimit</tt> arguments tells the underlying input stream to
* allow that many bytes to be read before the mark position gets
* invalidated.<p>
*
* The general contract of <tt>mark()</tt> is that, if the method
* <tt>markSupported()</tt> returns <tt>true</tt>, the stream somehow
* remembers all the bytes read after the call to <tt>mark()</tt> and
* stands ready to supply those same bytes again if and whenever the method
* <tt>reset()</tt> is called. However, the stream is not required to
* remember any data at all if more than <tt>readlimit</tt> bytes are read
* from the stream before <tt>reset()</tt> is called.
*
* @param readlimit the maximum limit of bytes that can be read before the
* mark position becomes invalid.
*/
public void mark(int readlimit) {
in.mark(readlimit);
}
/**
* Repositions the underlying stream to the position at the time the
* <tt>mark()</tt> method was last called on that input stream.
*
* The general contract of <tt>reset()</tt> is:
* <ul>
* <li>If the method <tt>markSupported()</tt> returns <tt>true</tt>, then:
* <ul>
* <li>If the method <tt>mark()</tt> has not been called since the
* stream was created, or the number of bytes read from the stream
* since <tt>mark()</tt> was last called is larger than the argument
* to <tt>mark()</tt> at that last call, then an <tt>IOException</tt>
* might be thrown.</li>
* <li>If such an <tt>IOException</tt> is not thrown, then the stream
* is reset to a state such that all the bytes read since the most
* recent call to <tt>mark()</tt> (or since the start of the file, if
* <tt>mark()</tt> has not been called) will be resupplied to subsequent
* callers of the <tt>read()</tt> method, followed by any bytes that
* otherwise would have been the next input data as of the time of the
* call to <tt>reset()</tt>.</li>
* </ul>
* </li>
* <li>If the method <tt>markSupported()</tt> returns <tt>false</tt>, then:
* <ul>
* <li>The call to <tt>reset()</tt> may throw an <tt>IOException</tt>.
* Specifically if <tt>markpos</tt> is <tt>-1</tt> (no mark has been
* set or the mark has been invalidated), an <tt>IOException</tt> is
* thrown</li>
* <li>If an <tt>IOException</tt> is not thrown, then the stream is
* reset to a fixed state that depends on the particular type of the
* underlying input stream and how it was created. Specifically
* <tt>pos</tt> is set equal to <tt>markpos</tt>. The bytes that will
* be supplied to subsequent callers of the <tt>read()</tt> method
* depend on the particular type of the input stream.</li>
* </ul>
* </li>
* </ul>
*
* @exception IOException if the underlying stream has not been marked or
* if the mark has been invalidated.
*/
public void reset() throws IOException {
in.reset();
}
/**
* Tests if the underlying input stream supports the <tt>mark()</tt> and
* <tt>reset()</tt> methods.
*
* @return true if the underlying input stream supports the <tt>mark()</tt>
* and <tt>reset()</tt> method; false otherwise.
*/
public boolean markSupported() {
return in.markSupported();
}
// Other instance methods
// ........................................................................
private byte[] readRaw(Tag tag, int universalValue) throws IOException {
byte[] buffer = readBytes(tag);
// buffer may contain a TLV of a UNIVERSAL class and a universalValue
// value, or just the value bytes of the type's instance depending on
// (a) if the tag is explicit or implicit, and (b) if it is explicit,
// whether the tag's context is UNIVERSAL or not.
byte[] result;
if (tag.isExplicit() && !tag.isUniversal()) { // it's a TLV
DerDecoder local = new DerDecoder(buffer);
result = local.readBytes(new Tag(universalValue));
} else
result = buffer;
return result;
}
private byte[] readBytes(Tag tag) throws IOException {
int length = readTL(tag);
byte[] result = new byte[length];
int actualLength = read(result);
if (actualLength == -1)
throw new EOFException();
if (actualLength != length)
throw new DerLengthMismatchException(actualLength, length);
return result;
}
// Tag-related methods
// ........................................................................
private int readTL(Tag tag) throws IOException {
if (!isExpectedTag(tag))
throw new TagMismatchException(String.valueOf(tag));
int result = readLength();
return result;
}
private boolean isExpectedTag(Tag tag) throws IOException {
Tag result = getExpectedTag(tag.getClazz(), tag.getValue());
return (result != null);
}
private Tag getExpectedTag(int xClass, int xValue)
throws IOException {
int tClass = -1;
int tValue = -1;
Tag result = null;
try {
cat.debug("==> getExpectedTag("+xClass+", "+xValue+")");
int c = read();
tClass = c & 0xC0;
boolean tConstructed = (c & 0x20) != 0;
tValue = c & 0x1F;
if (tValue == 0x1F) { // multiple bytes for tag number
tValue = 0;
do {
c = read();
tValue += c & 0x3F;
} while ((c & 0x80) != 0);
}
result = new Tag(tClass, tValue, true, tConstructed);
cat.info("Checking for Tag's ["+xClass+" "+xValue+"] found: "+result);
} finally {
if (!eval(tClass, xClass, tValue, xValue))
result = null;
}
cat.debug("<== getExpectedTag() --> "+result+" ["+tClass+", "+tValue+"]");
return result;
}
private Tag readTag() throws IOException {
cat.debug("==> readTag()");
Tag result = null;
int c = read();
int tClass = c & 0xC0;
boolean tConstructed = (c & 0x20) != 0;
int tValue = c & 0x1F;
if (tValue == 0x1F) { // multiple bytes for tag number
c = read();
tValue = c & 0x3F;
while ((c & 0x80) != 0) {
c = read();
tValue += c & 0x3F;
}
}
result = new Tag(tClass, tValue, true, tConstructed);
cat.debug("<== readTag() --> "+result);
return result;
}
// Length-related methods
// .......................................................................
private int readLength() throws IOException {
int result;
int limit = read();
if ((limit & 0x80) == 0)
result = limit;
else {
limit &= 0x7F;
if (limit > 4)
throw new DerObjectTooLargeException();
result = 0;
while (limit-- > 0)
result = (result << 8) | (read() & 0xFF);
}
cat.info("Element length = "+result);
return result;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -