TLVpublic class TLV extends Object Used to represent each Type, Length, Value structure in a DER buffer. |
Fields Summary |
---|
static final int | CONTEXTASN context specific flag used in types (0x80). | static final int | CONSTRUCTEDASN constructed flag used in types (0x20). | static final int | EXPLICITASN constructed flag used in types (0x20). | static final int | ANY_STRING_TYPEANY_STRING type used as a place holder. [UNIVERSAL 0] | static final int | BOOLEAN_TYPEASN BOOLEAN type used in certificate parsing. [UNIVERSAL 1] | static final int | INTEGER_TYPEASN INTEGER type used in certificate parsing. [UNIVERSAL 2] | static final int | BITSTRING_TYPEASN BIT STRING type used in certificate parsing. [UNIVERSAL 3] | static final int | OCTETSTR_TYPEASN OCTET STRING type used in certificate parsing. [UNIVERSAL 4] | static final int | NULL_TYPEASN NULL type used in certificate parsing. [UNIVERSAL 5] | static final int | OID_TYPEASN OBJECT ID type used in certificate parsing. [UNIVERSAL 6] | static final int | UTF8STR_TYPEASN UTF8String type used in certificate parsing. [UNIVERSAL 12] | static final int | SEQUENCE_TYPEASN SEQUENCE type used in certificate parsing.
[UNIVERSAL CONSTRUCTED 16] | static final int | SET_TYPEASN SET type used in certificate parsing.
[UNIVERSAL CONSTRUCTED 17] | static final int | PRINTSTR_TYPEASN PrintableString type used in certificate parsing. [UNIVERSAL 19] | static final int | TELETEXSTR_TYPEASN TELETEX STRING type used in certificate parsing. [UNIVERSAL 20] | static final int | IA5STR_TYPEASN IA5 STRING type used in certificate parsing. [UNIVERSAL 22] | static final int | UCT_TIME_TYPEASN UCT time type used in certificate parsing [UNIVERSAL 23] | static final int | GEN_TIME_TYPEASN Generalized time type used in certificate parsing.
[UNIVERSAL 24] | static final int | UNIVSTR_TYPEASN UniversalString type used in certificate parsing.
[UNIVERSAL 28]. | static final int | BMPSTR_TYPEASN BIT STRING type used in certificate parsing. [UNIVERSAL 30] | static final int | VERSION_TYPEContext specific explicit type for certificate version.
[CONTEXT EXPLICIT 0] | static final int | EXTENSIONS_TYPEContext specific explicit type for certificate extensions.
[CONTEXT EXPLICIT 3] | private static final int | MAX_OID_SIZEOID must fit into byte array of this size. | static char[] | hcHexadecimal digits. | int | typeRaw DER type. | int | lengthNumber of bytes that make up the value. | int | valueOffsetOffset of the value. | TLV | childNon-null for constructed types, the first child TLV. | TLV | nextThe next TLV in the parent sequence. | int | TLSizeSize of tag and length in DER encoding. | byte[] | dataBuffer that contains the DER encoded TLV. |
Constructors Summary |
---|
TLV(byte[] buffer, int offset)Constructs a TLV structure, recursing down for constructed types.
boolean constructed;
int size;
int start = offset;
data = buffer;
type = buffer[offset++] & 0xff;
// recurse for constructed types, bit 6 = 1
constructed = (type & 0x20) == 0x20;
if ((type & 0x1f) == 0x1f) {
// multi byte type, 7 bits per byte, only last byte bit 8 as zero
type = 0;
for (; ; ) {
int temp = buffer[offset++];
type = type << 7;
if (temp >= 0) {
type += temp;
break;
}
// stip off bit 8
temp = temp & 0x7f;
type += temp;
}
}
size = buffer[offset++] & 0xff;
if (size >= 128) {
int sizeLen = size - 128;
// NOTE: for now, all sizes must fit int two bytes
if (sizeLen > 2) {
throw new RuntimeException("TLV size to large");
}
size = 0;
while (sizeLen > 0) {
size = (size << 8) + (buffer[offset++] & 0xff);
sizeLen--;
}
}
TLSize = offset - start;
length = size;
valueOffset = offset;
if (constructed) {
int end;
TLV temp;
end = offset + length;
child = new TLV(buffer, offset);
temp = child;
for (; ; ) {
offset = temp.valueOffset + temp.length;
if (offset >= end) {
break;
}
temp.next = new TLV(buffer, offset);
temp = temp.next;
}
}
| TLV(int tag)Constructs a TLV structure.
type = tag;
| public TLV(int tag, byte[] bytes)Constructs a TLV structure.
type = tag;
length = bytes.length;
data = new byte[length + 4];
int i = putHeader(data, 0);
TLSize = i;
valueOffset = i;
System.arraycopy(bytes, 0, data, i, bytes.length);
|
Methods Summary |
---|
static java.lang.String | OIDtoString(byte[] buffer, int offset, int length)Converts a subsequence of bytes into a printable OID,
a string of decimal digits, each separated by a ".".
StringBuffer result;
int end;
int t;
int x;
int y;
if (length == 0) {
return "";
}
result = new StringBuffer(40);
end = offset + length;
/*
* first byte (t) always represents the first 2 values (x, y).
* t = (x * 40) + y;
*/
t = buffer[offset++] & 0xff;
x = t / 40;
y = t - (x * 40);
result.append(x);
result.append('.");
result.append(y);
x = 0;
while (offset < end) {
// 7 bit per byte, bit 8 = 0 means the end of a value
x = x << 7;
t = buffer[offset++];
if (t >= 0) {
x += t;
result.append('.");
result.append(x);
x = 0;
} else {
x += t & 0x7f;
}
}
return result.toString();
| static byte[] | StringToOID(java.lang.String oid)Converts a printable OID into a subsequence of bytes.
StringTokenizer t = new StringTokenizer(oid, ".");
int[] values = new int[t.countTokens()];
for (int i = 0; i < values.length; i++) {
values[i] = Integer.parseInt(t.nextToken(), 10);
}
byte[] x = new byte[MAX_OID_SIZE];
int i = 0;
x[i++] = (byte) (values[0] * 40 + values[1]);
for (int j = 2; j < values.length; j++) {
int k = values[j];
int p = 0;
while (true) {
p += 1;
k = k >> 7;
if (k == 0) {
break;
}
}
k = values[j];
while (p > 0) {
x[i] = (byte) (k >> ((p - 1) * 7));
if (p == 1) {
x[i] &= 0x7f;
} else {
x[i] |= 0x80;
}
p--;
i++;
}
}
byte[] data = new byte[i];
System.arraycopy(x, 0, data, 0, i);
return data;
| dummyCA.TLV | copy()Creates a copy of this TLV. The value of field next of the new TLV is
null.
return new TLV(getDERData(), 0);
| public static dummyCA.TLV | createUTCTime(java.util.Calendar time)Creates UTCTime TLV structure for given date.
byte[] data = new byte[13];
putDigits(data, 0, time.get(Calendar.YEAR));
putDigits(data, 2, time.get(Calendar.MONTH) + 1);
putDigits(data, 4, time.get(Calendar.DAY_OF_MONTH));
putDigits(data, 6, time.get(Calendar.HOUR_OF_DAY));
putDigits(data, 8, time.get(Calendar.MINUTE));
putDigits(data, 10, time.get(Calendar.SECOND));
data[12] = 0x5a;
return new TLV(UCT_TIME_TYPE, data);
| byte[] | getDERData()Returns DER encoded TLV.
if (data == null) {
byte[] x = new byte[getDERSize()];
int i = putHeader(x, 0);
TLV c = child;
while (c != null) {
byte[] cdata = c.getDERData();
System.arraycopy(cdata, 0, x, i, cdata.length);
i += cdata.length;
c = c.next;
}
if (i != x.length) {
throw new RuntimeException("debug");
}
return x;
}
byte[] x = new byte[length + TLSize];
System.arraycopy(data, valueOffset - TLSize, x, 0, length + TLSize);
return x;
| private int | getDERSize()Returns the size of DER encoded TLV.
if (data == null) {
int size = 0;
TLV c = child;
while (c != null) {
size += c.getDERSize();
c = c.next;
}
length = size;
// length size
if (size < 128) {
size += 1;
} else {
size += 1;
int i = size;
while (i != 0) {
size += 1;
i = i >> 8;
}
}
// tag size - only one byte tags are used
size += 1;
TLSize = size - length;
}
return length + TLSize;
| java.lang.String | getOID()Returns string representation of OID represented by this TLV.
if (type != OID_TYPE) {
throw new IOException("OID expected");
}
return OIDtoString(data, valueOffset, length);
| byte[] | getValue()Returns the value field of this TLV.
if (data == null) {
return copy().getValue();
}
byte[] x = new byte[length];
System.arraycopy(data, valueOffset, x, 0, length);
return x;
| static java.lang.String | hexEncode(byte[] b, int off, int len, int max)Converts a subsequence of bytes in a byte array into a
corresponding string of hexadecimal digits, each separated by a ":".
char[] r;
int v;
int i;
int j;
if ((b == null) || (len == 0)) {
return "";
}
if ((off < 0) || (len < 0)) {
throw new ArrayIndexOutOfBoundsException();
}
r = new char[len * 3];
for (i = 0, j = 0; ; ) {
v = b[off + i] & 0xff;
r[j++] = hc[v >>> 4];
r[j++] = hc[v & 0x0f];
i++;
if (i >= len) {
break;
}
if (i == max) {
r[j++] = ' ";
r[j++] = '+";
break;
}
r[j++] = ':";
}
return (new String(r, 0, j));
| void | print(java.io.PrintStream out)Print the a TLV structure, recursing down for constructed types.
print(out, 0);
| private void | print(java.io.PrintStream out, int level)Prints the a TLV structure, recursing down for constructed types.
for (int i = 0; i < level; i++) {
out.print(" ");
}
byte[] buffer;
if (data != null) {
buffer = data;
} else {
buffer = getDERData();
}
if (child == null) {
out.print("Type: 0x" + Integer.toHexString(type) +
" length: " + length + " value: ");
if (type == PRINTSTR_TYPE ||
type == TELETEXSTR_TYPE ||
type == UTF8STR_TYPE ||
type == IA5STR_TYPE ||
type == UNIVSTR_TYPE) {
try {
out.print(new String(buffer, valueOffset, length,
"UTF-8"));
} catch (UnsupportedEncodingException e) {
// ignore
}
} else if (type == OID_TYPE) {
out.print(OIDtoString(buffer, valueOffset, length));
} else {
out.print(hexEncode(buffer, valueOffset, length, 999999));
}
out.println("");
} else {
if (type == SET_TYPE) {
out.print("Set:");
} else {
out.print("Sequence:");
}
out.println(" (0x" + Integer.toHexString(type) +
" " + length + ")");
child.print(out, level + 1);
}
if (next != null) {
next.print(out, level);
}
| void | print()Print the a TLV structure, recursing down for constructed types.
print(System.out, 0);
| private static void | putDigits(byte[] data, int offset, int value)Places two ASCII encoded decimal digits into byte array.
value = value % 100;
data[offset++] = (byte) (0x30 | (value / 10));
data[offset++] = (byte) (0x30 | (value % 10));
| private int | putHeader(byte[] x, int i)Places tag and length values into the buffer.
x[i++] = (byte) type;
if (length < 128) {
x[i++] = (byte) length;
} else
if (length < 256) {
x[i++] = (byte) 0x81;
x[i++] = (byte) length;
} else {
x[i++] = (byte) 0x82;
x[i++] = (byte) (length >> 8);
x[i++] = (byte) length;
}
return i;
|
|