From d69cde1a40c0530328c1aac29b7eeb4a7cda53b6 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 22 Nov 2018 22:30:36 -0700 Subject: [PATCH] v0.8.2: bugfix ASN1 null, integer 0, and incorrect byte length --- bin/rasha.js | 8 +++++++ lib/asn1.js | 62 +++++++++++++++++++++++++++++++++++++++++++++++----- package.json | 2 +- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/bin/rasha.js b/bin/rasha.js index 3874dea..0084031 100755 --- a/bin/rasha.js +++ b/bin/rasha.js @@ -3,6 +3,8 @@ var fs = require('fs'); var Rasha = require('../index.js'); +var PEM = require('../lib/pem.js'); +var ASN1 = require('../lib/asn1.js'); var infile = process.argv[2]; var format = process.argv[3]; @@ -16,6 +18,12 @@ try { } if ('string' === typeof key) { + if ('tpl' === format) { + var block = PEM.parseBlock(key); + var asn1 = ASN1.parse(block.der); + ASN1.tpl(asn1); + return; + } var pub = (-1 !== [ 'public', 'spki', 'pkix' ].indexOf(format)); Rasha.import({ pem: key, public: (pub || format) }).then(function (jwk) { console.info(JSON.stringify(jwk, null, 2)); diff --git a/lib/asn1.js b/lib/asn1.js index 73c8d12..6668931 100644 --- a/lib/asn1.js +++ b/lib/asn1.js @@ -89,6 +89,7 @@ ASN1.parse = function parseAsn1(buf, depth) { var child; var iters = 0; var adjust = 0; + var adjustedLen; // Determine how many bytes the length uses, and what it is if (0x80 & asn1.length) { @@ -101,20 +102,25 @@ ASN1.parse = function parseAsn1(buf, depth) { // High-order bit Integers have a leading 0x00 to signify that they are positive. // Bit Streams use the first byte to signify padding, which x.509 doesn't use. if (0x00 === buf[index] && (0x02 === asn1.type || 0x03 === asn1.type)) { - index += 1; - adjust = -1; + // However, 0x00 on its own is a valid number + if (asn1.length > 1) { + index += 1; + adjust = -1; + } } + adjustedLen = asn1.length + adjust; + // this is a primitive value type if (-1 !== ASN1.VTYPES.indexOf(asn1.type)) { - asn1.value = buf.slice(index, index + asn1.length + adjust); + asn1.value = buf.slice(index, index + adjustedLen); return asn1; } asn1.children = []; - while (iters < 15 && index < buf.byteLength) { + while (iters < 15 && index <= asn1.length) { iters += 1; - child = ASN1.parse(buf.slice(index, index + asn1.length), (depth || 0) + 1); + child = ASN1.parse(buf.slice(index, index + adjustedLen), (depth || 0) + 1); index += (2 + child.lengthSize + child.length); asn1.children.push(child); } @@ -144,4 +150,50 @@ ASN1._stringify = function(asn1) { }; */ +ASN1.tpl = function (asn1) { + //console.log(JSON.stringify(asn1, null, 2)); + //console.log(asn1); + var ws = ''; + var i = 0; + var vars = []; + var str = ws; + + function write(asn1, k) { + str += "\n" + ws; + var val; + if ('number' !== typeof k) { + // ignore + } else if (k) { + str += ', '; + } else { + str += ' '; + } + if (0x02 === asn1.type) { + str += "ASN1.UInt("; + } else if (0x03 === asn1.type) { + str += "ASN1.BitStr("; + } else { + str += "ASN1('" + Buffer.from([asn1.type]).toString('hex') + "', "; + } + if (!asn1.children) { + val = Buffer.from(asn1.value || ''); + vars.push("// " + val.byteLength + " bytes\nvar tpl" + i + " = '" + + val.toString('hex') + "';"); + str += "tpl" + i + ")"; + return ; + } + asn1.children.forEach(function (a, j) { + i += 1; + ws += '\t'; + write(a, j); + ws = ws.slice(1); + }); + str += "\n" + ws + ")"; + } + + write(asn1); + console.log(vars.join('\n') + '\n'); + console.log(str + ';'); +}; + module.exports = ASN1; diff --git a/package.json b/package.json index 3f8ab9d..1d3764b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rasha", - "version": "0.8.0", + "version": "0.8.2", "description": "PEM-to-JWK and JWK-to-PEM for RSA keys in a lightweight, zero-dependency library focused on perfect universal compatibility.", "homepage": "https://git.coolaj86.com/coolaj86/rasha.js", "main": "index.js",