v1.1.0: add case for known primitive-only values
This commit is contained in:
parent
01384daa80
commit
bf359477a9
20
README.md
20
README.md
|
@ -71,14 +71,22 @@ Note: `value` will be a `Uint8Array`, not a hex string.
|
||||||
|
|
||||||
### Optimistic Parsing
|
### Optimistic Parsing
|
||||||
|
|
||||||
This is a dumbed-down, minimal ASN1 parser.
|
This is a dumbed-down, minimal ASN1 parser
|
||||||
|
(though quite clever in its simplicity).
|
||||||
|
|
||||||
Rather than incorporating knowledge of each possible x509 schema
|
There are some ASN.1 types (at least Bit String and Octet String,
|
||||||
to know whether to traverse deeper into a value container,
|
possibly others) that can be treated either as primitive values or
|
||||||
it always tries to dive in (and backs out when parsing fails).
|
as container types base on the schema being used.
|
||||||
|
|
||||||
It is possible that it will produce false positives, but not likely
|
Rather than incorporating knowledge of each possible x509 schema,
|
||||||
in real-world scenarios (PEM, x509, CSR, etc).
|
this parser will return values for types that are _always_ values,
|
||||||
|
it recurse on types that are _always_ containers and, for ambigiuous
|
||||||
|
types, it will first try to recurse and, on error, will fall back to
|
||||||
|
returning a value.
|
||||||
|
|
||||||
|
In theory, it is possible that it will produce false positives,
|
||||||
|
but that would be highly unlikely in real-world scenarios
|
||||||
|
(PEM, x509, PKCS#1, SEC1, PKCS#8, SPKI, PKIX, CSR, etc).
|
||||||
|
|
||||||
I'd be interested to hear if you encounter such a case.
|
I'd be interested to hear if you encounter such a case.
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,12 @@ var PEM = exports.PEM;
|
||||||
|
|
||||||
ASN1.ELOOP = "uASN1.js Error: iterated over 15+ elements (probably a malformed file)";
|
ASN1.ELOOP = "uASN1.js Error: iterated over 15+ elements (probably a malformed file)";
|
||||||
ASN1.EDEEP = "uASN1.js Error: element nested 20+ layers deep (probably a malformed file)";
|
ASN1.EDEEP = "uASN1.js Error: element nested 20+ layers deep (probably a malformed file)";
|
||||||
// Container Types are Sequence 0x30, Octect String 0x04, Array? (0xA0, 0xA1)
|
// Container Types are Sequence 0x30, Container Array? (0xA0, 0xA1)
|
||||||
// Value Types are Integer 0x02, Bit String 0x03, Null 0x05, Object ID 0x06,
|
// Value Types are Integer 0x02, Null 0x05, Object ID 0x06, Value Array? (0x82)
|
||||||
|
// Bit String (0x03) and Octet String (0x04) may be values or containers
|
||||||
// Sometimes Bit String is used as a container (RSA Pub Spki)
|
// Sometimes Bit String is used as a container (RSA Pub Spki)
|
||||||
ASN1.CTYPES = [ 0x30, 0x31, 0xa0, 0xa1 ];
|
ASN1.CTYPES = [ 0x30, 0x31, 0xa0, 0xa1 ];
|
||||||
|
ASN1.VTYPES = [ 0x02, 0x05, 0x06, 0x82 ];
|
||||||
ASN1.parse = function parseAsn1(buf, depth, ws) {
|
ASN1.parse = function parseAsn1(buf, depth, ws) {
|
||||||
if (!ws) { ws = ''; }
|
if (!ws) { ws = ''; }
|
||||||
if (!depth) { depth = 0; }
|
if (!depth) { depth = 0; }
|
||||||
|
@ -81,23 +83,21 @@ ASN1.parse = function parseAsn1(buf, depth, ws) {
|
||||||
return asn1;
|
return asn1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to fail if we know for sure that it's bad
|
// Recurse into types that are _always_ containers
|
||||||
if (-1 !== ASN1.CTYPES.indexOf(asn1.type)) {
|
if (-1 !== ASN1.CTYPES.indexOf(asn1.type)) { return parseChildren(); }
|
||||||
return parseChildren();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Return types that are _always_ values
|
||||||
asn1.value = buf.slice(index, index + adjustedLen);
|
asn1.value = buf.slice(index, index + adjustedLen);
|
||||||
try {
|
if (-1 !== ASN1.VTYPES.indexOf(asn1.type)) { return asn1; }
|
||||||
return parseChildren(true);
|
|
||||||
} catch(e) {
|
// For ambigious / unknown types, recurse and return on failure
|
||||||
// leaving iterable array as a matter of convenience
|
// (and return child array size to zero)
|
||||||
asn1.children = [];
|
try { return parseChildren(true); }
|
||||||
return asn1;
|
catch(e) { asn1.children.length = 0; return asn1; }
|
||||||
}
|
|
||||||
};
|
};
|
||||||
ASN1._replacer = function (k, v) {
|
ASN1._replacer = function (k, v) {
|
||||||
if ('type' === k) { return '0x' + Enc.numToHex(v); }
|
if ('type' === k) { return '0x' + Enc.numToHex(v); }
|
||||||
if ('value' === k) { return '0x' + Enc.bufToHex(v.data || v); }
|
if (v && 'value' === k) { return '0x' + Enc.bufToHex(v.data || v); }
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,9 @@ rMjgyCokrnjDft6Y/YnA4A50yZe7CnFsqeDcpnPbubP6cpYiVcnevNIYyg==
|
||||||
var $input = document.querySelector('.js-input');
|
var $input = document.querySelector('.js-input');
|
||||||
|
|
||||||
function convert() {
|
function convert() {
|
||||||
console.log('change');
|
console.log('keyup');
|
||||||
var pem = PEM.parseBlock(document.querySelector('.js-input').value);
|
var pem = PEM.parseBlock(document.querySelector('.js-input').value);
|
||||||
var hex = Enc.bufToHex(pem.der);
|
var hex = Enc.bufToHex(pem.der);
|
||||||
console.log(hex);
|
|
||||||
document.querySelector('.js-hex').innerText = hex
|
document.querySelector('.js-hex').innerText = hex
|
||||||
.match(/.{2}/g).join(' ').match(/.{1,24}/g).join(' ').match(/.{1,50}/g).join('\n');
|
.match(/.{2}/g).join(' ').match(/.{1,24}/g).join(' ').match(/.{1,50}/g).join('\n');
|
||||||
var json = ASN1.parse(pem.der);
|
var json = ASN1.parse(pem.der);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "asn1-parser",
|
"name": "asn1-parser",
|
||||||
"version": "1.0.2",
|
"version": "1.1.0",
|
||||||
"description": "An ASN.1 parser in less than 100 lines of Vanilla JavaScript, part of the Bluecrypt suite.",
|
"description": "An ASN.1 parser in less than 100 lines of Vanilla JavaScript, part of the Bluecrypt suite.",
|
||||||
"homepage": "https://git.coolaj86.com/coolaj86/asn1-parser.js",
|
"homepage": "https://git.coolaj86.com/coolaj86/asn1-parser.js",
|
||||||
"main": "asn1-parser.js",
|
"main": "asn1-parser.js",
|
||||||
|
|
Loading…
Reference in New Issue