// Until DER.sys.mjs is actually used in production code, this is where we have to // import it from. var { DER } = ChromeUtils.importESModule( "resource://gre/modules/psm/DER.sys.mjs"
);
function run_simple_tests() { throws(
() => new DER.DERDecoder("this is not an array"),
/invalid input/, "should throw given non-array input"
);
let testReadByte = new DER.DERDecoder([0x0a, 0x0b]);
equal(testReadByte.readByte(), 0x0a, "should read 0x0a");
equal(testReadByte.readByte(), 0x0b, "should read 0x0b"); throws(
() => testReadByte.readByte(),
/data truncated/, "reading more data than is available should fail"
);
let testReadBytes = new DER.DERDecoder([0x0c, 0x0d, 0x0e]);
deepEqual(
testReadBytes.readBytes(3),
[0x0c, 0x0d, 0x0e], "should read correct sequence of bytes"
);
let testReadNegativeBytes = new DER.DERDecoder([0xff, 0xaf]); throws(
() => testReadNegativeBytes.readBytes(-4),
/invalid length/, "reading a negative number of bytes should fail"
);
let testReadZeroBytes = new DER.DERDecoder([]);
equal(
testReadZeroBytes.readBytes(0).length, 0, "reading zero bytes should result in a zero-length array"
);
let testReadTooManyBytes = new DER.DERDecoder([0xab, 0xcd, 0xef]); throws(
() => testReadTooManyBytes.readBytes(4),
/data truncated/, "reading too many bytes should fail"
);
let testSEQUENCE = new DER.DERDecoder([0x30, 0x01, 0x01]);
let content = testSEQUENCE.readTagAndGetContents(DER.SEQUENCE);
equal(content.length, 1, "content should have length 1");
equal(content[0], 1, "value of content should be [1]");
ok(testSEQUENCE.atEnd(), "testSEQUENCE should be at the end of its input");
testSEQUENCE.assertAtEnd();
// The length purports to be 4 bytes, but there are only 2 available.
let truncatedSEQUENCE = new DER.DERDecoder([0x30, 0x04, 0x00, 0x00]); throws(
() => truncatedSEQUENCE.readTagAndGetContents(DER.SEQUENCE),
/data truncated/, "should get 'data truncated' error"
);
// With 2 bytes of content, there is 1 remaining after reading the content.
let extraDataSEQUENCE = new DER.DERDecoder([0x30, 0x02, 0xab, 0xcd, 0xef]);
content = extraDataSEQUENCE.readTagAndGetContents(DER.SEQUENCE);
equal(content.length, 2, "content should have length 2");
deepEqual(content, [0xab, 0xcd], "value of content should be [0xab, 0xcd]");
ok(
!extraDataSEQUENCE.atEnd(), "extraDataSEQUENCE should not be at the end of its input"
); throws(
() => extraDataSEQUENCE.assertAtEnd(),
/extra data/, "should get 'extra data' error"
);
// The length of 0x81 0x01 is invalid because it could be encoded as just // 0x01, which is shorter.
let invalidLengthSEQUENCE1 = new DER.DERDecoder([0x30, 0x81, 0x01, 0x00]); throws(
() => invalidLengthSEQUENCE1.readTagAndGetContents(DER.SEQUENCE),
/invalid length/, "should get 'invalid length' error"
);
// Similarly, 0x82 0x00 0x01 could be encoded as just 0x01, which is shorter.
let invalidLengthSEQUENCE2 = new DER.DERDecoder([ 0x30, 0x82, 0x00, 0x01, 0x00,
]); throws(
() => invalidLengthSEQUENCE2.readTagAndGetContents(DER.SEQUENCE),
/invalid length/, "should get 'invalid length' error"
);
// Lengths requiring 4 bytes to encode are not supported.
let unsupportedLengthSEQUENCE = new DER.DERDecoder([ 0x30, 0x83, 0x01, 0x01, 0x01,
]); throws(
() => unsupportedLengthSEQUENCE.readTagAndGetContents(DER.SEQUENCE),
/unsupported length/, "should get 'unsupported length' error"
);
// Indefinite lengths are not supported (and aren't DER anyway).
let unsupportedASN1SEQUENCE = new DER.DERDecoder([ 0x30, 0x80, 0x01, 0x00, 0x00,
]); throws(
() => unsupportedASN1SEQUENCE.readTagAndGetContents(DER.SEQUENCE),
/unsupported asn.1/, "should get 'unsupported asn.1' error"
);
let unexpectedTag = new DER.DERDecoder([0x31, 0x01, 0x00]); throws(
() => unexpectedTag.readTagAndGetContents(DER.SEQUENCE),
/unexpected tag/, "should get 'unexpected tag' error"
);
let readTLVTestcase = new DER.DERDecoder([0x02, 0x03, 0x45, 0x67, 0x89]);
let bytes = readTLVTestcase.readTLV();
deepEqual(
bytes,
[0x02, 0x03, 0x45, 0x67, 0x89], "bytes read with readTLV should be equal to expected value"
);
let peekTagTestcase = new DER.DERDecoder([0x30, 0x01, 0x00]);
ok(
peekTagTestcase.peekTag(DER.SEQUENCE), "peekTag should return true for peeking with a SEQUENCE at a SEQUENCE"
);
ok(
!peekTagTestcase.peekTag(DER.SET), "peekTag should return false for peeking with a SET at a SEQUENCE"
);
peekTagTestcase.readTLV();
ok(
!peekTagTestcase.peekTag(DER.SEQUENCE), "peekTag should return false for peeking at a DER with no more data"
);
let tlvChoiceTestcase = new DER.DERDecoder([0x31, 0x02, 0xaa, 0xbb]);
let tlvChoiceContents = tlvChoiceTestcase.readTLVChoice([DER.NULL, DER.SET]);
deepEqual(
tlvChoiceContents,
[0x31, 0x02, 0xaa, 0xbb], "readTLVChoice should return expected bytes"
);
let tlvChoiceNoMatchTestcase = new DER.DERDecoder([0x30, 0x01, 0xff]); throws(
() => tlvChoiceNoMatchTestcase.readTLVChoice([DER.NULL, DER.SET]),
/unexpected tag/, "readTLVChoice should throw if no matching tag is found"
);
}
function run_bit_string_tests() {
let bitstringDER = new DER.DERDecoder([0x03, 0x04, 0x03, 0x01, 0x02, 0xf8]);
let bitstring = bitstringDER.readBIT_STRING();
equal(bitstring.unusedBits, 3, "BIT STRING should have 3 unused bits");
deepEqual(
bitstring.contents,
[0x01, 0x02, 0xf8], "BIT STRING should have expected contents"
);
let bitstringTooManyUnusedBits = new DER.DERDecoder([0x03, 0x02, 0x08, 0x00]); throws(
() => bitstringTooManyUnusedBits.readBIT_STRING(),
/invalid BIT STRING encoding/, "BIT STRING with too many unused bits should throw"
);
// A BIT STRING must have the unused bits byte, and so its length must be at // least one.
let bitstringMissingUnusedBits = new DER.DERDecoder([0x03, 0x00]); throws(
() => bitstringMissingUnusedBits.readBIT_STRING(),
/invalid BIT STRING encoding/, "BIT STRING with missing unused bits (and no contents) should throw"
);
// The minimal BIT STRING is 03 01 00 (zero bits of padding and zero bytes of // content).
let minimalBitstringDER = new DER.DERDecoder([0x03, 0x01, 0x00]);
let minimalBitstring = minimalBitstringDER.readBIT_STRING();
equal(
minimalBitstring.unusedBits, 0, "minimal BIT STRING should have 0 unused bits"
);
equal(
minimalBitstring.contents.length, 0, "minimal BIT STRING should have empty contents"
);
// However, a BIT STRING with zero bytes of content can't have any padding, // because that makes no sense.
let noContentsPaddedBitstringDER = new DER.DERDecoder([0x03, 0x01, 0x03]); throws(
() => noContentsPaddedBitstringDER.readBIT_STRING(),
/invalid BIT STRING encoding/, "BIT STRING with no contents with non-zero padding should throw"
);
}
function run_compound_tests() {
let derBytes = [ 0x30, 0x1a, // SEQUENCE 0x02, 0x02, 0x77, 0xff, // INTEGER 0x06, 0x03, 0x2b, 0x01, 0x01, // OBJECT IDENTIFIER 0x30, 0x07, // SEQUENCE 0x05, 0x00, // NULL 0x02, 0x03, 0x45, 0x46, 0x47, // INTEGER 0x30, 0x06, // SEQUENCE 0x02, 0x02, 0x00, 0xff, // INTEGER 0x05, 0x00,
]; // NULL
let der = new DER.DERDecoder(derBytes);
let contents = new DER.DERDecoder(der.readTagAndGetContents(DER.SEQUENCE));
let firstINTEGER = contents.readTagAndGetContents(DER.INTEGER);
deepEqual(
firstINTEGER,
[0x77, 0xff], "first INTEGER should have expected value"
);
let oid = contents.readTagAndGetContents(DER.OBJECT_IDENTIFIER);
deepEqual(
oid,
[0x2b, 0x01, 0x01], "OBJECT IDENTIFIER should have expected value"
);
let firstNested = new DER.DERDecoder(
contents.readTagAndGetContents(DER.SEQUENCE)
);
let firstNestedNULL = firstNested.readTagAndGetContents(DER.NULL);
equal(
firstNestedNULL.length, 0, "first nested NULL should have expected value (empty array)"
);
let firstNestedINTEGER = firstNested.readTagAndGetContents(DER.INTEGER);
deepEqual(
firstNestedINTEGER,
[0x45, 0x46, 0x47], "first nested INTEGER should have expected value"
);
firstNested.assertAtEnd();
let secondNested = new DER.DERDecoder(
contents.readTagAndGetContents(DER.SEQUENCE)
);
let secondNestedINTEGER = secondNested.readTagAndGetContents(DER.INTEGER);
deepEqual(
secondNestedINTEGER,
[0x00, 0xff], "second nested INTEGER should have expected value"
);
let secondNestedNULL = secondNested.readTagAndGetContents(DER.NULL);
equal(
secondNestedNULL.length, 0, "second nested NULL should have expected value (empty array)"
);
secondNested.assertAtEnd();
contents.assertAtEnd();
der.assertAtEnd();
let invalidDERBytes = [ 0x30, 0x06, // SEQUENCE 0x30, 0x02, // SEQUENCE 0x02, 0x01, // INTEGER (missing data) 0x05, 0x00, // NULL 0x00, 0x00,
]; // (extra data)
let invalidDER = new DER.DERDecoder(invalidDERBytes);
let invalidContents = new DER.DERDecoder(
invalidDER.readTagAndGetContents(DER.SEQUENCE)
);
let invalidContentsContents = new DER.DERDecoder(
invalidContents.readTagAndGetContents(DER.SEQUENCE)
); throws(
() => invalidContentsContents.readTagAndGetContents(DER.INTEGER),
/data truncated/, "should throw due to missing data"
);
let nestedNULL = invalidContents.readTagAndGetContents(DER.NULL);
equal(nestedNULL.length, 0, "nested NULL should have expected value");
invalidContents.assertAtEnd(); throws(
() => invalidDER.assertAtEnd(),
/extra data/, "should throw due to extra data"
);
}
function run_test() {
run_simple_tests();
run_bit_string_tests();
run_compound_tests();
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.