Skip to content

Commit

Permalink
propagate from branch 'it.lapo.asn1js' (head dd18afd1c4344811526fc928…
Browse files Browse the repository at this point in the history
…f3975fe414584018)

            to branch 'it.lapo.asn1js.github-82' (head 27ed876d23a39e4ec2bfd2f6233f38610720add2)
  • Loading branch information
lapo-luchini committed Mar 31, 2024
2 parents 429f752 + 1fcc683 commit be8d97a
Show file tree
Hide file tree
Showing 15 changed files with 666 additions and 62 deletions.
36 changes: 21 additions & 15 deletions asn1.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const
['', ''],
['OUou', 'ŐŰőű'], // Double Acute
['AEIUaeiu', 'ĄĘĮŲąęįų'], // Ogonek
['CDELNRSTZcdelnrstz', 'ČĎĚĽŇŘŠŤŽčďěľňřšťž'] // Caron
['CDELNRSTZcdelnrstz', 'ČĎĚĽŇŘŠŤŽčďěľňřšťž'], // Caron
];

function stringCut(str, len) {
Expand Down Expand Up @@ -77,7 +77,7 @@ class Stream {
if (pos === undefined)
pos = this.pos++;
if (pos >= this.enc.length)
throw 'Requesting byte offset ' + pos + ' on a stream of length ' + this.enc.length;
throw new Error('Requesting byte offset ' + pos + ' on a stream of length ' + this.enc.length);
return (typeof this.enc == 'string') ? this.enc.charCodeAt(pos) : this.enc[pos];
}
hexByte(b) {
Expand Down Expand Up @@ -195,7 +195,7 @@ class Stream {
let s = this.parseStringISO(start, end).str,
m = (shortYear ? reTimeS : reTimeL).exec(s);
if (!m)
return 'Unrecognized time: ' + s;
throw new Error('Unrecognized time: ' + s);
if (shortYear) {
// to avoid querying the timer, use the fixed range [1970, 2069]
// it will conform with ITU X.400 [-10, +40] sliding window until 2030
Expand Down Expand Up @@ -250,7 +250,7 @@ class Stream {
parseBitString(start, end, maxLength) {
let unusedBits = this.get(start);
if (unusedBits > 7)
throw 'Invalid BitString with unusedBits=' + unusedBits;
throw new Error('Invalid BitString with unusedBits=' + unusedBits);
let lenBit = ((end - start - 1) << 3) - unusedBits,
s = '';
for (let i = start + 1; i < end; ++i) {
Expand Down Expand Up @@ -373,7 +373,7 @@ class ASN1Tag {

class ASN1 {
constructor(stream, header, length, tag, tagLen, sub) {
if (!(tag instanceof ASN1Tag)) throw 'Invalid tag value.';
if (!(tag instanceof ASN1Tag)) throw new Error('Invalid tag value.');
this.stream = stream;
this.header = header;
this.length = length;
Expand Down Expand Up @@ -536,15 +536,15 @@ class ASN1 {
if (len === 0) // long form with length 0 is a special case
return null; // undefined length
if (len > 6) // no reason to use Int10, as it would be a huge buffer anyways
throw 'Length over 48 bits not supported at position ' + (stream.pos - 1);
throw new Error('Length over 48 bits not supported at position ' + (stream.pos - 1));
buf = 0;
for (let i = 0; i < len; ++i)
buf = (buf * 256) + stream.get();
return buf;
}
static decode(stream, offset, type = ASN1) {
if (!(type == ASN1 || type.prototype instanceof ASN1))
throw 'Must pass a class that extends ASN1';
throw new Error('Must pass a class that extends ASN1');
if (!(stream instanceof Stream))
stream = new Stream(stream, offset || 0);
let streamStart = new Stream(stream),
Expand All @@ -560,11 +560,11 @@ class ASN1 {
// definite length
let end = start + len;
if (end > stream.enc.length)
throw 'Container at offset ' + start + ' has a length of ' + len + ', which is past the end of the stream';
throw new Error('Container at offset ' + start + ' has a length of ' + len + ', which is past the end of the stream');
while (stream.pos < end)
sub[sub.length] = type.decode(stream);
if (stream.pos != end)
throw 'Content size is not correct for container at offset ' + start;
throw new Error('Content size is not correct for container at offset ' + start);
} else {
// undefined length
try {
Expand All @@ -576,7 +576,7 @@ class ASN1 {
}
len = start - stream.pos; // undefined lengths are represented as negative values
} catch (e) {
throw 'Exception while decoding undefined length content at offset ' + start + ': ' + e;
throw new Error('Exception while decoding undefined length content at offset ' + start + ': ' + e);
}
}
};
Expand All @@ -588,11 +588,17 @@ class ASN1 {
try {
if (tag.tagNumber == 0x03)
if (stream.get() != 0)
throw 'BIT STRINGs with unused bits cannot encapsulate.';
throw new Error('BIT STRINGs with unused bits cannot encapsulate.');
getSub();
for (let i = 0; i < sub.length; ++i)
if (sub[i].tag.isEOC())
throw 'EOC is not supposed to be actual content.';
for (let s of sub) {
if (s.tag.isEOC())
throw new Error('EOC is not supposed to be actual content.');
try {
s.content();
} catch (e) {
throw new Error('Unable to parse content: ' + e);
}
}
} catch (e) {
// but silently ignore when they don't
sub = null;
Expand All @@ -601,7 +607,7 @@ class ASN1 {
}
if (sub === null) {
if (len === null)
throw "We can't skip over an invalid tag with undefined length at offset " + start;
throw new Error("We can't skip over an invalid tag with undefined length at offset " + start);
stream.pos = start + Math.abs(len);
}
return new type(streamStart, header, len, tag, tagLen, sub);
Expand Down
8 changes: 5 additions & 3 deletions defs.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ function translate(def, tn, stats) {
try {
// hope current OIDs contain the type name (will need to parse from RFC itself)
def = Defs.searchType(firstUpper(stats.defs[def.definedBy][1]));
} catch (e) {}
} catch (e) { /*ignore*/ }
while (def?.type == 'defined' || def?.type?.type == 'defined') {
const name = def?.type?.type ? def.type.name : def.name;
def = Object.assign({}, def);
def.type = Defs.searchType(name).type;
}
if (def?.type?.name == 'CHOICE') {
for (let c of def.type.content) {
c = translate(c);
if (tn != c.type.name && tn != c.name)
c = translate(c);
if (tn == c.type.name || tn == c.name) {
def = Object.assign({}, def);
def.type = c.type.name ? c.type : c;
Expand Down Expand Up @@ -109,7 +110,7 @@ class Defs {
} else if (type?.definedBy && stats.defs?.[type.definedBy]?.[1]) { // hope current OIDs contain the type name (will need to parse from RFC itself)
try {
type = Defs.searchType(firstUpper(stats.defs[type.definedBy][1]));
} catch (e) {}
} catch (e) { /*ignore*/ }
}
}
}
Expand All @@ -126,6 +127,7 @@ Defs.RFC = rfc;
Defs.commonTypes = [
[ 'X.509 certificate', '1.3.6.1.5.5.7.0.18', 'Certificate' ],
[ 'CMS / PKCS#7 envelope', '1.2.840.113549.1.9.16.0.14', 'ContentInfo' ],
[ 'PKCS#1 RSA private key', '1.2.840.113549.1.1.0.1', 'RSAPrivateKey' ],
[ 'PKCS#8 encrypted private key', '1.2.840.113549.1.8.1.1', 'EncryptedPrivateKeyInfo' ],
[ 'PKCS#8 private key', '1.2.840.113549.1.8.1.1', 'PrivateKeyInfo' ],
[ 'PKCS#10 certification request', '1.2.840.113549.1.10.1.1', 'CertificationRequest' ],
Expand Down
11 changes: 8 additions & 3 deletions dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ const
o += line;
}
return o;
}
}
},
};

class ASN1DOM extends ASN1 {

Expand Down Expand Up @@ -84,7 +84,12 @@ class ASN1DOM extends ASN1 {
}
}
head.appendChild(DOM.text(typeName));
let content = this.content(contentLength);
let content;
try {
content = this.content(contentLength);
} catch (e) {
content = 'Cannot decode: ' + e;
}
let oid;
if (content !== null) {
let preview = DOM.tag('span', 'preview'),
Expand Down
18 changes: 18 additions & 0 deletions examples/pkcs1.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
PKCS#1 RSA key
$ openssl genrsa -out examples/pkcs8-rsa.pem 1024
$ openssl rsa -in examples/pkcs8-rsa.pem -out examples/pkcs1.pem -traditional
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCmy23ifN9pi5LO4MR3LUhU0v+LZmv78H+jd+R6kFcWZf1qW4yf
KTDkryjjLlIhYqxmzXCqGyaIjj7uJoorWf7KfkxpOuJrh4swJ/WGhCn9i+voW/7T
sOXfDp1yqrEhaQKwdPot1ZAB78TNsecwX/SODTEMCk95jvx1j5cDxPlskwIDAQAB
AoGBAINn4bp+BsVwYMj768y4sDOjyBBbMNfcMbLn0el9rh7HW09fsPnzycFg/iV9
aNdEle6oDAr4OPN8nbeiRVjCHijEnVdHCwAtkKODyuu1ghpZWD0VUC8AEskjX4Bs
Ysl/HjyvvHIRj89gdDFoElgB4GzHKTzeZNJBM5qtUW57zBCBAkEA0A6N5l98MglL
cypWKM7+3DXteWt86mKXYUVF33HY28Z+oUVlU0v8m8XxpoAjkicYnC1JOSSlvWRk
EWlTMgHW5QJBAM06yIHMR6p3apgpwOUp49DbtaQ8NmhCV4NBoFHa+vT2Fk8twOcq
O9OzP4svhKbPNfB4HnxGbmd/+OVT3lySxhcCQHRPPpqD1K0wLwKxrzrfBPDcIOaY
5VsuRIw3KqmQPngWTiIf5lYbi5sVnFLFHZ2Nx58/XcjZKOJopdxp8f1ps9UCQQC3
rOqSsF9bg3DVKllHQAxyepDAolsXSHjGMk/nspJz9mLVDl/dBAFzYLN4QFj6ae0e
gILYOrjIzNHXfQ4/z+SVAkBPebkAzpGFgzVzu6VOGx0Vft/ow3/DKNJSDM58yASp
ootY2TdibrrV/ellNLvuTiku6AEM/8jbHlRsmfxRe0xn
-----END RSA PRIVATE KEY-----
18 changes: 18 additions & 0 deletions examples/pkcs8-rsa.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
PKCS#8 RSA key
$ openssl genrsa -out examples/pkcs8-rsa.pem 1024
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKbLbeJ832mLks7g
xHctSFTS/4tma/vwf6N35HqQVxZl/WpbjJ8pMOSvKOMuUiFirGbNcKobJoiOPu4m
iitZ/sp+TGk64muHizAn9YaEKf2L6+hb/tOw5d8OnXKqsSFpArB0+i3VkAHvxM2x
5zBf9I4NMQwKT3mO/HWPlwPE+WyTAgMBAAECgYEAg2fhun4GxXBgyPvrzLiwM6PI
EFsw19wxsufR6X2uHsdbT1+w+fPJwWD+JX1o10SV7qgMCvg483ydt6JFWMIeKMSd
V0cLAC2Qo4PK67WCGllYPRVQLwASySNfgGxiyX8ePK+8chGPz2B0MWgSWAHgbMcp
PN5k0kEzmq1RbnvMEIECQQDQDo3mX3wyCUtzKlYozv7cNe15a3zqYpdhRUXfcdjb
xn6hRWVTS/ybxfGmgCOSJxicLUk5JKW9ZGQRaVMyAdblAkEAzTrIgcxHqndqmCnA
5Snj0Nu1pDw2aEJXg0GgUdr69PYWTy3A5yo707M/iy+Eps818HgefEZuZ3/45VPe
XJLGFwJAdE8+moPUrTAvArGvOt8E8Nwg5pjlWy5EjDcqqZA+eBZOIh/mVhuLmxWc
UsUdnY3Hnz9dyNko4mil3Gnx/Wmz1QJBALes6pKwX1uDcNUqWUdADHJ6kMCiWxdI
eMYyT+eyknP2YtUOX90EAXNgs3hAWPpp7R6Agtg6uMjM0dd9Dj/P5JUCQE95uQDO
kYWDNXO7pU4bHRV+3+jDf8Mo0lIMznzIBKmii1jZN2JuutX96WU0u+5OKS7oAQz/
yNseVGyZ/FF7TGc=
-----END PRIVATE KEY-----
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ <h1>ASN.1 JavaScript decoder</h1>
<option value="sig-rsa1024-sha1.p7s">PKCS#7/CMS detached signature (old)</option>
<option value="letsencrypt-x3.cer">X.509 certificate: Let's Encrypt X3</option>
<option value="ed25519.cer">X.509 certificate: ed25519 (RFC 8410)</option>
<option value="pkcs1.pem">PKCS#1 RSA key (RFC 8017)</option>
<option value="pkcs8-rsa.pem">PKCS#8 RSA key (RFC 5208)</option>
<option value="pkcs10.pem">PKCS#10 certification request (RFC 2986)</option>
<option value="cmpv2.b64">CMP PKI message (RFC 4210)</option>
</select>
Expand Down
5 changes: 2 additions & 3 deletions oids.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// You can use this code in whatever way you want,
// as long as you don't try to claim you wrote it.
(typeof define != "undefined" ? define : function (factory) { "use strict";
if (typeof module == "object") module.exports = factory();
else window.oids = factory();
if (typeof module == "object") module.exports = factory();
else window.oids = factory();
})(function () {
"use strict";
return {
Expand Down Expand Up @@ -2727,5 +2727,4 @@ return {
"1.3.6.1.4.1.40869.1.1.22.3": { "d": "TWCA EV policy", "c": "TWCA Root Certification Authority" },
"2.16.840.1.113733.1.7.23.6": { "d": "VeriSign EV policy", "c": "VeriSign Class 3 Public Primary Certification Authority" },
"2.16.840.1.114171.500.9": { "d": "Wells Fargo EV policy", "c": "Wells Fargo WellsSecure Public Root Certificate Authority" },
"END": ""
};});
15 changes: 10 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,21 @@
"semi": [ "warn", "always" ],
"quotes": [ "error", "single", { "avoidEscape": true } ],
"no-var": [ "warn" ],
"comma-dangle": [ "error", "never" ]
"comma-dangle": [ "error", "always-multiline" ]
},
"overrides": [
{
"files": [ "defs.js" ],
"parserOptions": {
"ecmaVersion": 2020
}
}, {
"files": [ "test.js", "parseRFC.js", "dumpASN1.js" ],
"parserOptions": {
"ecmaVersion": 2021
},
"rules": {
"strict": [ "error", "global" ],
"comma-dangle": [ "error", "always-multiline" ]
"strict": [ "error", "global" ]
}
}, {
"files": [ "oids.js" ],
Expand All @@ -62,9 +66,10 @@
"quotes": [ "warn", "double" ]
}
}, {
"files": [ "tags.js" ],
"files": [ "tags.js", "rfcdef.js" ],
"rules": {
"comma-dangle": [ "error", "always-multiline" ],
"indent": [ "error", 2, { "ignoredNodes": [ "Program > ExpressionStatement > CallExpression > FunctionExpression > BlockStatement > ExpressionStatement[directive='use strict']:first-child" ] } ],
"comma-dangle": "off",
"quotes": [ "warn", "double" ]
}
}
Expand Down
16 changes: 15 additions & 1 deletion parseRFC.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ const
4210: [
[ /^\s+-- .*\r?\n/mg, '' ], // comments
],
8017: [ // this RFC uses a lot of currently unsupported syntax
[ /ALGORITHM-IDENTIFIER ::= CLASS[^-]+--/, '--' ],
[ /\n +\S+ +ALGORITHM-IDENTIFIER[^\n]+(\n [^\n]+)+\n [}]/g, '' ],

Check failure on line 50 in parseRFC.js

View workflow job for this annotation

GitHub Actions / build (latest)

Spaces are hard to count. Use {6}
[ /AlgorithmIdentifier [{] ALGORITHM-IDENTIFIER:InfoObjectSet [}] ::=(\n [^\n]+)+\n [}]/, 'AlgorithmIdentifier ::= ANY'],

Check failure on line 51 in parseRFC.js

View workflow job for this annotation

GitHub Actions / build (latest)

Spaces are hard to count. Use {6}
[ /algorithm +id-[^,\n]+,/g, 'algorithm ANY,' ],
[ / (sha1 HashAlgorithm|mgf1SHA1 MaskGenAlgorithm|pSpecifiedEmpty PSourceAlgorithm|rSAES-OAEP-Default-Identifier RSAES-AlgorithmIdentifier|rSASSA-PSS-Default-Identifier RSASSA-AlgorithmIdentifier) ::= [{](\n( [^\n]+)?)+\n [}]/g, '' ],

Check failure on line 53 in parseRFC.js

View workflow job for this annotation

GitHub Actions / build (latest)

Spaces are hard to count. Use {4}
[ / ::= AlgorithmIdentifier [{]\s+[{][^}]+[}]\s+[}]/g, ' ::= AlgorithmIdentifier' ],
[ /OCTET STRING[(]SIZE[(]0..MAX[)][)]/g, 'OCTET STRING' ],
[ /emptyString EncodingParameters ::= ''H/g, '' ],

Check failure on line 56 in parseRFC.js

View workflow job for this annotation

GitHub Actions / build (latest)

Spaces are hard to count. Use {4}
[ /[(]CONSTRAINED BY[^)]+[)]/g, '' ],
],
};

// const reWhitespace = /(?:\s|--(?:[}-]?[^\n}-])*(?:\n|--))*/y;
Expand Down Expand Up @@ -349,8 +360,11 @@ class Parser {
} else {
if (id in currentMod.values) // defined in local module
val = currentMod.values[id].value;
else
else try {
val = searchImportedValue(id);
} catch (e) {
this.exception(e.message);
}
}
}
if (v.length) v += '.';
Expand Down
7 changes: 4 additions & 3 deletions release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ mtn automate tags it.lapo.asn1js | \
done | sort -r | awk -v q='"' '
BEGIN {
print "(typeof define != " q "undefined" q " ? define : function (factory) { " q "use strict" q ";";
print " if (typeof module == " q "object" q ") module.exports = factory();";
print " else window.tags = factory();";
print " if (typeof module == " q "object" q ") module.exports = factory();";
print " else window.tags = factory();";
print "})(function () {";
print q "use strict" q ";";
print "return {"
}
{ print " " q $2 q ":" q $1 q "," }
{ print " " q $2 q ": " q $1 q "," }
END { print "};});" }
' > tags.js
chmod 644 examples/*
type gsha256sum >/dev/null && SHA256=gsha256sum || SHA256=sha256sum
$SHA256 -t $FILES | gpg --clearsign > sha256sums.asc
7z a -tzip -mx=9 asn1js.zip $FILES sha256sums.asc
Expand Down
Loading

0 comments on commit be8d97a

Please sign in to comment.