Skip to content

Commit

Permalink
propagate from branch 'it.lapo.asn1js' (head 2c2471b462a45fe5bbd48c9d…
Browse files Browse the repository at this point in the history
…9347f2df5ab039d9)

            to branch 'it.lapo.asn1js.esm' (head 8fc43cda40cb66f028d050df54b1e506736d094a)
  • Loading branch information
lapo-luchini committed Apr 1, 2024
2 parents ad3d920 + cce28c5 commit 513085b
Show file tree
Hide file tree
Showing 23 changed files with 200 additions and 202 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
node-version: [ 6.4.0, latest ]
node-version: [ 12.20.0, latest ]

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ISC License

Copyright (c) 2008-2022 Lapo Luchini <[email protected]>
Copyright (c) 2008-2024 Lapo Luchini <[email protected]>

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
Expand Down
28 changes: 12 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,43 @@ This package can be installed with either npm or yarn via the following commands

```sh
npm install @lapo/asn1js
# or with yarn
# or other tools
pnpm install @lapo/asn1js
yarn add @lapo/asn1js
```

Assuming a standard javascript bundler is setup you can import it like so:

```js
const ASN1 = require('@lapo/asn1js');
// or with ES modules
import ASN1 from '@lapo/asn1js';
```

A submodule of this package can also be imported:

```js
const Hex = require('@lapo/asn1js/hex');
// or with ES modules
import Hex from '@lapo/asn1js/hex';
```

Usage with RequireJS
Unfortunately until [`require(esm)` gets released](https://joyeecheung.github.io/blog/2024/03/18/require-esm-in-node-js/) it is necessary to use async `import()` when used from CommonJS (legacy NodeJS) code.

Usage on the web
--------------------

Can be [tested on JSFiddle](https://jsfiddle.net/lapo/tmdq35ug/).
Can be [tested on JSFiddle](https://jsfiddle.net/lapo/y6t2wo7q/).

```html
<script type="text/javascript" src="https://unpkg.com/requirejs/require.js"></script>
<script>
require([
'https://unpkg.com/@lapo/asn1js/asn1.js',
'https://unpkg.com/@lapo/asn1js/hex.js'
], function(ASN1, Hex) {
document.body.innerText = ASN1.decode(Hex.decode('06032B6570')).content();
});
import { ASN1} from 'https://unpkg.com/@lapo/[email protected]/asn1.js';
import { Hex } from 'https://unpkg.com/@lapo/[email protected]/hex.js';
document.body.innerText = ASN1.decode(Hex.decode('06032B6570')).content();
</script>
```

ISC license
-----------

ASN.1 JavaScript decoder Copyright (c) 2008-2023 Lapo Luchini <[email protected]>
ASN.1 JavaScript decoder Copyright (c) 2008-2024 Lapo Luchini <[email protected]>

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

Expand All @@ -66,7 +62,7 @@ credits
- extended tag support added by [Péter Budai](https://www.peterbudai.eu/)
- patches by [Gergely Nagy](https://github.com/ngg)
- Relative OID support added by [Mistial Developer](https://github.com/mistial-dev)
- dark mode support added by [Oliver Burgmaier](https://github.com/olibu/)
- dark mode and other UI improvements by [Oliver Burgmaier](https://github.com/olibu/)
- patches by [Nicolai Søborg](https://github.com/NicolaiSoeborg)

links
Expand Down
43 changes: 25 additions & 18 deletions asn1.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ASN.1 JavaScript decoder
// Copyright (c) 2008-2023 Lapo Luchini <[email protected]>
// Copyright (c) 2008-2024 Lapo Luchini <[email protected]>

// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
Expand All @@ -13,15 +13,10 @@
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

(typeof define != 'undefined' ? define : function (factory) { 'use strict';
if (typeof module == 'object') module.exports = factory(function (name) { return require(name); });
else window.asn1 = factory(function (name) { return window[name.substring(2)]; });
})(function (require) {
'use strict';
import { Int10 } from './int10.js';
import { oids } from './oids.js';

const
Int10 = require('./int10'),
oids = require('./oids'),
ellipsis = '\u2026',
reTimeS = /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|(-(?:0\d|1[0-2])|[+](?:0\d|1[0-4]))([0-5]\d)?)?$/,
reTimeL = /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|(-(?:0\d|1[0-2])|[+](?:0\d|1[0-4]))([0-5]\d)?)?$/,
Expand Down Expand Up @@ -83,11 +78,15 @@ class Stream {
hexByte(b) {
return hexDigits.charAt((b >> 4) & 0xF) + hexDigits.charAt(b & 0xF);
}
hexDump(start, end, raw) {
/** Hexadecimal dump.
* @param type 'raw', 'byte' or 'dump' */
hexDump(start, end, type = 'dump') {
let s = '';
for (let i = start; i < end; ++i) {
if (type == 'byte' && i > start)
s += ' ';
s += this.hexByte(this.get(i));
if (raw !== true)
if (type == 'dump')
switch (i & 0xF) {
case 0x7: s += ' '; break;
case 0xF: s += '\n'; break;
Expand Down Expand Up @@ -371,7 +370,7 @@ class ASN1Tag {
}
}

class ASN1 {
export class ASN1 {
constructor(stream, header, length, tag, tagLen, sub) {
if (!(tag instanceof ASN1Tag)) throw new Error('Invalid tag value.');
this.stream = stream;
Expand Down Expand Up @@ -490,7 +489,16 @@ class ASN1 {
}
toPrettyString(indent) {
if (indent === undefined) indent = '';
let s = indent + this.typeName() + ' @' + this.stream.pos;
let s = indent;
if (this.def) {
if (this.def.id)
s += this.def.id + ' ';
if (this.def.name && this.def.name != this.typeName().replace(/_/g, ' '))
s+= this.def.name + ' ';
if (this.def.mismatch)
s += '[?] ';
}
s += this.typeName() + ' @' + this.stream.pos;
if (this.length >= 0)
s += '+';
s += this.length;
Expand Down Expand Up @@ -522,9 +530,12 @@ class ASN1 {
posLen() {
return this.stream.pos + this.tagLen;
}
toHexString() {
return this.stream.hexDump(this.posStart(), this.posEnd(), true);
/** Hexadecimal dump of the node.
* @param type 'raw', 'byte' or 'dump' */
toHexString(type = 'raw') {
return this.stream.hexDump(this.posStart(), this.posEnd(), type);
}
/** Base64 dump of the node. */
toB64String() {
return this.stream.b64Dump(this.posStart(), this.posEnd());
}
Expand Down Expand Up @@ -614,7 +625,3 @@ class ASN1 {
}

}

return ASN1;

});
14 changes: 2 additions & 12 deletions base64.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Base64 JavaScript decoder
// Copyright (c) 2008-2023 Lapo Luchini <[email protected]>
// Copyright (c) 2008-2024 Lapo Luchini <[email protected]>

// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
Expand All @@ -13,18 +13,12 @@
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

(typeof define != 'undefined' ? define : function (factory) { 'use strict';
if (typeof module == 'object') module.exports = factory();
else window.base64 = factory();
})(function () {
'use strict';

const
haveU8 = (typeof Uint8Array == 'function');

let decoder; // populated on first usage

class Base64 {
export class Base64 {

static decode(a) {
let isString = (typeof a == 'string');
Expand Down Expand Up @@ -107,7 +101,3 @@ class Base64 {
}

Base64.re = /-----BEGIN [^-]+-----([A-Za-z0-9+/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+/=\s]+)====|^([A-Za-z0-9+/=\s]+)$/;

return Base64;

});
60 changes: 60 additions & 0 deletions context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const
id = (elem) => document.getElementById(elem),
contextMenu = id('contextmenu'),
btnHideTree = id('btnHideTree'),
btnCopyHex = id('btnCopyHex'),
btnCopyB64 = id('btnCopyB64'),
btnCopyTree = id('btnCopyTree'),
btnCopyValue = id('btnCopyValue');

export function bindContextMenu(node) {
const type = node.asn1.typeName();
const valueEnabled = type != 'SET' && type != 'SEQUENCE';
node.onclick = function (event) {
contextMenu.style.left = event.pageX + 'px';
contextMenu.style.top = event.pageY + 'px';
contextMenu.style.visibility = 'visible';
contextMenu.node = this;
btnHideTree.innerText = (node.className == 'node') ? 'Hide subtree' : 'Show subtree';
btnHideTree.style.display = node.className.startsWith('node') ? 'block' : 'none';
btnCopyValue.style.display = valueEnabled ? 'block' : 'none';
event.stopPropagation();
};
};

function close() {
contextMenu.style.visibility = 'hidden';
}

contextMenu.onmouseleave = close;

btnHideTree.onclick = function (event) {
event.stopPropagation();
const node = contextMenu.node;
node.className = (node.className == 'node collapsed') ? 'node' : 'node collapsed';
close();
};

btnCopyHex.onclick = function (event) {
event.stopPropagation();
navigator.clipboard.writeText(contextMenu.node.asn1.toHexString('byte'));
close();
};

btnCopyB64.onclick = function (event) {
event.stopPropagation();
navigator.clipboard.writeText(contextMenu.node.asn1.toB64String());
close();
};

btnCopyTree.onclick = function (event) {
event.stopPropagation();
navigator.clipboard.writeText(contextMenu.node.asn1.toPrettyString());
close();
};

btnCopyValue.onclick = function (event) {
event.stopPropagation();
navigator.clipboard.writeText(contextMenu.node.asn1.content());
close();
};
22 changes: 6 additions & 16 deletions defs.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ASN.1 RFC definitions matcher
// Copyright (c) 2023-2023 Lapo Luchini <[email protected]>
// Copyright (c) 2023-2024 Lapo Luchini <[email protected]>

// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
Expand All @@ -13,13 +13,7 @@
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

(typeof define != 'undefined' ? define : function (factory) { 'use strict';
if (typeof module == 'object') module.exports = factory(function (name) { return require(name); });
else window.defs = factory(function (name) { return window[name.substring(2)]; });
})(function (require) {
'use strict';

const rfc = require('./rfcdef');
import { rfcdef } from './rfcdef.js';

function translate(def, tn, stats) {
if (def?.type == 'tag' && !def.explicit)
Expand Down Expand Up @@ -56,14 +50,14 @@ function firstUpper(s) {
return s[0].toUpperCase() + s.slice(1);
}

class Defs {
export class Defs {

static moduleAndType(mod, name) {
return Object.assign({ module: { oid: mod.oid, name: mod.name, source: mod.source } }, mod.types[name]);
}

static searchType(name) {
for (const mod of Object.values(rfc))
for (const mod of Object.values(rfcdef))
if (name in mod.types) {
// console.log(name + ' found in ' + r.name);
// return r.types[name];
Expand Down Expand Up @@ -122,7 +116,7 @@ class Defs {

}

Defs.RFC = rfc;
Defs.RFC = rfcdef;

Defs.commonTypes = [
[ 'X.509 certificate', '1.3.6.1.5.5.7.0.18', 'Certificate' ],
Expand All @@ -132,8 +126,4 @@ Defs.commonTypes = [
[ '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' ],
[ 'CMP PKI Message', '1.3.6.1.5.5.7.0.16', 'PKIMessage' ],
].map(arr => ({ description: arr[0], ...Defs.moduleAndType(rfc[arr[1]], arr[2]) }));

return Defs;

});
].map(arr => ({ description: arr[0], ...Defs.moduleAndType(rfcdef[arr[1]], arr[2]) }));
23 changes: 7 additions & 16 deletions dom.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ASN.1 JavaScript decoder
// Copyright (c) 2008-2023 Lapo Luchini <[email protected]>
// Copyright (c) 2008-2024 Lapo Luchini <[email protected]>

// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
Expand All @@ -13,15 +13,11 @@
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

(typeof define != 'undefined' ? define : function (factory) { 'use strict';
if (typeof module == 'object') module.exports = factory(function (name) { return require(name); });
else window.dom = factory(function (name) { return window[name.substring(2)]; });
})(function (require) {
'use strict';
import { ASN1 } from './asn1.js';
import { oids } from './oids.js';
import { bindContextMenu } from './context.js';

const
ASN1 = require('./asn1'),
oids = require('./oids'),
lineLength = 80,
contentLength = 8 * lineLength,
DOM = {
Expand Down Expand Up @@ -55,7 +51,7 @@ const
},
};

class ASN1DOM extends ASN1 {
export class ASN1DOM extends ASN1 {

toDOM(spaces) {
spaces = spaces || '';
Expand Down Expand Up @@ -147,9 +143,7 @@ class ASN1DOM extends ASN1 {
sub.appendChild(this.sub[i].toDOM(spaces));
}
node.appendChild(sub);
head.onclick = function () {
node.className = (node.className == 'node collapsed') ? 'node' : 'node collapsed';
};
bindContextMenu(node);
return node;
}
fakeHover(current) {
Expand Down Expand Up @@ -192,6 +186,7 @@ class ASN1DOM extends ASN1 {
this.className = 'hex';
}
};
bindContextMenu(node);
if (root == node) {
let lineStart = this.posStart() & 0xF;
if (lineStart != 0) {
Expand Down Expand Up @@ -236,7 +231,3 @@ class ASN1DOM extends ASN1 {
}

}

return ASN1DOM;

});
Loading

0 comments on commit 513085b

Please sign in to comment.