Compare commits

..

No commits in common. "master" and "v1.1.3" have entirely different histories.

4 changed files with 11 additions and 43 deletions

View File

@ -1,6 +1,6 @@
# Bluecrypt ASN.1 Parser # Bluecrypt ASN.1 Parser
An ASN.1 decoder in less than 100 lines of Vanilla JavaScript, An ASN.1 parser in less than 100 lines of Vanilla JavaScript,
part of the Bluecrypt suite. part of the Bluecrypt suite.
<br> <br>
<small>(< 150 with newlines and comments)</small> <small>(< 150 with newlines and comments)</small>
@ -17,10 +17,6 @@ part of the Bluecrypt suite.
* [x] Online [Demo](https://coolaj86.com/demos/asn1-parser/) * [x] Online [Demo](https://coolaj86.com/demos/asn1-parser/)
* [ ] Node.js (built, publishing soon) * [ ] Node.js (built, publishing soon)
### Need an ASN.1 Builder too?
Check out https://git.coolaj86.com/coolaj86/asn1-packer.js/
# Demo # Demo
<https://coolaj86.com/demos/asn1-parser/> <https://coolaj86.com/demos/asn1-parser/>

View File

@ -1,7 +1,3 @@
// Copyright 2018 AJ ONeal. All rights reserved
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
;(function (exports) { ;(function (exports) {
'use strict'; 'use strict';
@ -17,13 +13,8 @@ var PEM = exports.PEM;
// Parser // Parser
// //
// Although I've only seen 9 max in https certificates themselves, ASN1.ELOOP = "uASN1.js Error: iterated over 15+ elements (probably a malformed file)";
// but each domain list could have up to 100 ASN1.EDEEP = "uASN1.js Error: element nested 20+ layers deep (probably a malformed file)";
ASN1.ELOOPN = 102;
ASN1.ELOOP = "uASN1.js Error: iterated over " + ASN1.ELOOPN + "+ elements (probably a malformed file)";
// I've seen https certificates go 29 deep
ASN1.EDEEPN = 60;
ASN1.EDEEP = "uASN1.js Error: element nested " + ASN1.EDEEPN + "+ layers deep (probably a malformed file)";
// Container Types are Sequence 0x30, Container Array? (0xA0, 0xA1) // Container Types are Sequence 0x30, Container Array? (0xA0, 0xA1)
// Value Types are Boolean 0x01, Integer 0x02, Null 0x05, Object ID 0x06, String 0x0C, 0x16, 0x13, 0x1e Value Array? (0x82) // Value Types are Boolean 0x01, Integer 0x02, Null 0x05, Object ID 0x06, String 0x0C, 0x16, 0x13, 0x1e Value Array? (0x82)
// Bit String (0x03) and Octet String (0x04) may be values or containers // Bit String (0x03) and Octet String (0x04) may be values or containers
@ -32,8 +23,8 @@ ASN1.CTYPES = [ 0x30, 0x31, 0xa0, 0xa1 ];
ASN1.VTYPES = [ 0x01, 0x02, 0x05, 0x06, 0x0c, 0x82 ]; ASN1.VTYPES = [ 0x01, 0x02, 0x05, 0x06, 0x0c, 0x82 ];
ASN1.parse = function parseAsn1Helper(buf) { ASN1.parse = function parseAsn1Helper(buf) {
//var ws = ' '; //var ws = ' ';
function parseAsn1(buf, depth, eager) { function parseAsn1(buf, depth) {
if (depth.length >= ASN1.EDEEPN) { throw new Error(ASN1.EDEEP); } if (depth.length >= 20) { throw new Error(ASN1.EDEEP); }
var index = 2; // we know, at minimum, data starts after type (0) and lengthSize (1) var index = 2; // we know, at minimum, data starts after type (0) and lengthSize (1)
var asn1 = { type: buf[0], lengthSize: 0, length: buf[1] }; var asn1 = { type: buf[0], lengthSize: 0, length: buf[1] };
@ -66,11 +57,10 @@ ASN1.parse = function parseAsn1Helper(buf) {
function parseChildren(eager) { function parseChildren(eager) {
asn1.children = []; asn1.children = [];
//console.warn('1 len:', (2 + asn1.lengthSize + asn1.length), 'idx:', index, 'clen:', 0); //console.warn('1 len:', (2 + asn1.lengthSize + asn1.length), 'idx:', index, 'clen:', 0);
while (iters < ASN1.ELOOPN && index < (2 + asn1.length + asn1.lengthSize)) { while (iters < 15 && index < (2 + asn1.length + asn1.lengthSize)) {
iters += 1; iters += 1;
depth.length += 1; depth.length += 1;
child = parseAsn1(buf.slice(index, index + adjustedLen), depth, eager); child = parseAsn1(buf.slice(index, index + adjustedLen), depth);
depth.length -= 1;
// The numbers don't match up exactly and I don't remember why... // The numbers don't match up exactly and I don't remember why...
// probably something with adjustedLen or some such, but the tests pass // probably something with adjustedLen or some such, but the tests pass
index += (2 + child.lengthSize + child.length); index += (2 + child.lengthSize + child.length);
@ -88,14 +78,14 @@ ASN1.parse = function parseAsn1Helper(buf) {
//console.warn('index:', index, 'length:', (2 + asn1.lengthSize + asn1.length)); //console.warn('index:', index, 'length:', (2 + asn1.lengthSize + asn1.length));
throw new Error("premature end-of-file"); throw new Error("premature end-of-file");
} }
if (iters >= ASN1.ELOOPN) { throw new Error(ASN1.ELOOP); } if (iters >= 15) { throw new Error(ASN1.ELOOP); }
delete asn1.value; delete asn1.value;
return asn1; return asn1;
} }
// Recurse into types that are _always_ containers // Recurse into types that are _always_ containers
if (-1 !== ASN1.CTYPES.indexOf(asn1.type)) { return parseChildren(eager); } if (-1 !== ASN1.CTYPES.indexOf(asn1.type)) { return parseChildren(); }
// Return types that are _always_ values // Return types that are _always_ values
asn1.value = buf.slice(index, index + adjustedLen); asn1.value = buf.slice(index, index + adjustedLen);

View File

@ -12,38 +12,22 @@
<body> <body>
<h1>Bluecrypt ASN.1 Parser</h1> <h1>Bluecrypt ASN.1 Parser</h1>
<h2>PEM (base64-encoded DER)</h2>
<textarea class="js-input" placeholder="Paste a PEM here">-----BEGIN PUBLIC KEY----- <textarea class="js-input" placeholder="Paste a PEM here">-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIT1SWLxsacPiE5Z16jkopAn8/+85 MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIT1SWLxsacPiE5Z16jkopAn8/+85
rMjgyCokrnjDft6Y/YnA4A50yZe7CnFsqeDcpnPbubP6cpYiVcnevNIYyg== rMjgyCokrnjDft6Y/YnA4A50yZe7CnFsqeDcpnPbubP6cpYiVcnevNIYyg==
-----END PUBLIC KEY-----</textarea> -----END PUBLIC KEY-----</textarea>
<h2>Hex</h2>
<pre><code class="js-hex"> </code></pre> <pre><code class="js-hex"> </code></pre>
<h2>ASN.1 Array</h2>
<pre><code class="js-array"> </code></pre>
<h2>ASN.1 Object</h2>
<pre><code class="js-json"> </code></pre> <pre><code class="js-json"> </code></pre>
<br> <br>
<p>Made with <a href="https://git.coolaj86.com/coolaj86/asn1-parser.js/">asn1-parser.js</a></p> <p>Made with <a href="https://git.coolaj86.com/coolaj86/asn1-parser/">asn1-parser.js</a></p>
<script src="./asn1-parser.js"></script> <script src="./asn1-parser.js"></script>
<script> <script>
var $input = document.querySelector('.js-input'); var $input = document.querySelector('.js-input');
function toArray(next) {
console.log(next);
if (next.value) {
return [next.type, Enc.bufToHex(next.value)];
}
return [next.type, next.children.map(function (child) {
return toArray(child);
})];
}
function convert() { function convert() {
console.log('keyup'); console.log('keyup');
var json; var json;
@ -51,7 +35,6 @@ rMjgyCokrnjDft6Y/YnA4A50yZe7CnFsqeDcpnPbubP6cpYiVcnevNIYyg==
try { try {
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);
var arr = [];
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');
json = ASN1.parse(pem.der); json = ASN1.parse(pem.der);
@ -60,7 +43,6 @@ rMjgyCokrnjDft6Y/YnA4A50yZe7CnFsqeDcpnPbubP6cpYiVcnevNIYyg==
} }
document.querySelector('.js-json').innerText = JSON.stringify(json, ASN1._replacer, 2); document.querySelector('.js-json').innerText = JSON.stringify(json, ASN1._replacer, 2);
document.querySelector('.js-array').innerText = JSON.stringify(toArray(json), null, 2);
} }
$input.addEventListener('keyup', convert); $input.addEventListener('keyup', convert);

View File

@ -1,6 +1,6 @@
{ {
"name": "asn1-parser", "name": "asn1-parser",
"version": "1.1.8", "version": "1.1.3",
"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",