From 3657d674ab607e53a55bf753da643d089dcdaef9 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sun, 18 Nov 2018 16:35:53 -0700 Subject: [PATCH] ASN.1 cleanup (comments) --- lib/ecdsacsr.js | 57 ++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/lib/ecdsacsr.js b/lib/ecdsacsr.js index 223d61c..e16a0ab 100644 --- a/lib/ecdsacsr.js +++ b/lib/ecdsacsr.js @@ -6,49 +6,58 @@ var crypto = require('crypto'); // prime256v1 (ANSI X9.62 named elliptic curve) var OBJ_ID_EC = '06 08 2A8648CE3D030107'.replace(/\s+/g, '').toLowerCase(); -function ASN1() { +// +// A dumbed-down, minimal ASN.1 packer +// + +// Almost every ASN.1 type that's important for CSR +// can be represented generically with only a few rules. +function ASN1(/*type, hexstrings...*/) { var args = Array.prototype.slice.call(arguments); var typ = args.shift(); - var str = args.join('').replace(/\s+/g, ''); + var str = args.join('').replace(/\s+/g, '').toLowerCase(); var len = (str.length/2); - var len2 = len; var lenlen = 0; var hex = typ; - var hlen = ''; - // high-order bit means multiple bytes - if (len2 !== Math.round(len2)) { + + // We can't have an odd number of hex chars + if (len !== Math.round(len)) { throw new Error("invalid hex"); } - if (len2 > 127) { + + // The first byte of any ASN.1 sequence is the type (Sequence, Integer, etc) + // The second byte is either the size of the value, or the size of its size + + // 1. If the second byte is < 0x80 (128) it is considered the size + // 2. If it is > 0x80 then it describes the number of bytes of the size + // ex: 0x82 means the next 2 bytes describe the size of the value + // 3. The special case of exactly 0x80 is "indefinite" length (to end-of-file) + + if (len > 127) { lenlen += 1; - while (len2 > 255) { + while (len > 255) { lenlen += 1; - len2 = len2 >> 8; - //console.warn("LEN2", len2); + len = len >> 8; } } - if (lenlen) { - hlen = numToHex(0x80 + lenlen); - } - /* - console.warn( - 'typ:', typ - , 'lenlen:', hlen - , 'len:', len, numToHex(len) - ); - console.warn('str:', str); - */ - return hex + hlen + numToHex(len) + str; + + if (lenlen) { hex += numToHex(0x80 + lenlen); } + return hex + numToHex(str.length/2) + str; } + +// The Integer type has some special rules ASN1.UInt = function UINT() { var str = Array.prototype.slice.call(arguments).join(''); var first = parseInt(str.slice(0, 2), 16); - // high-order bit means signed, negative - // we want positive, so we pad with a leading '00' + + // If the first byte is 0x80 or greater, the number is considered negative + // Therefore we add a '00' prefix if the 0x80 bit is set if (0x80 & first) { str = '00' + str; } + return ASN1('02', str); }; +// The Bit String type also has a special rule ASN1.BitStr = function BITSTR() { var str = Array.prototype.slice.call(arguments).join(''); // '00' is a mask of how many bits of the next byte to ignore