WIP more asn1

This commit is contained in:
AJ ONeal 2018-11-18 14:34:20 -07:00
parent ba92407194
commit ab8ec9fa7c
1 changed files with 55 additions and 52 deletions

View File

@ -26,21 +26,21 @@ function ASN1() {
} }
return hex + numToHex(len) + str; return hex + numToHex(len) + str;
} }
ASN1.UInt = function UINT() {
function UINT() {
var str = Array.prototype.slice.call(arguments).join(''); var str = Array.prototype.slice.call(arguments).join('');
var first = parseInt(str.slice(0, 2), 16); var first = parseInt(str.slice(0, 2), 16);
// high-order bit means signed, negative // high-order bit means signed, negative
// we want positive, so we pad with a leading '00' // we want positive, so we pad with a leading '00'
if (0x80 & first) { str = '00' + str; } if (0x80 & first) { str = '00' + str; }
return ASN1('02', str); return ASN1('02', str);
} };
function BITSTR() { ASN1.BitStr = function BITSTR() {
var str = Array.prototype.slice.call(arguments).join(''); var str = Array.prototype.slice.call(arguments).join('');
// '00' is a mask of how many bits of the next byte to ignore // '00' is a mask of how many bits of the next byte to ignore
return ASN1('03', '00' + str); return ASN1('03', '00' + str);
} };
function SEQ() { function SEQ() {
return ASN1('30', Array.prototype.slice.call(arguments).join('')); return ASN1('30', Array.prototype.slice.call(arguments).join(''));
} }
@ -204,22 +204,27 @@ function csrEcSig(r, s) {
// (ANSI X9.62 ECDSA algorithm with SHA256) // (ANSI X9.62 ECDSA algorithm with SHA256)
OBJID('2A 86 48 CE 3D 04 03 02') OBJID('2A 86 48 CE 3D 04 03 02')
) )
, BITSTR( , ASN1.BitStr(
SEQ( SEQ(
UINT(toHex(r)) ASN1.UInt(toHex(r))
, UINT(toHex(s)) , ASN1.UInt(toHex(s))
) )
) )
].join(''); ].join('');
} }
var csrDomains = '82 {dlen} {domain.tld}'; // 2+n bytes (type 82?) var csrDomains = '82 {dlen} {domain.tld}'; // 2+n bytes (type 82?)
// TODO utf8
function strToHex(str) { function strToHex(str) {
return str.split('').map(function (ch) { var escstr = encodeURIComponent(str);
var h = ch.charCodeAt(0).toString(16); // replaces any uri escape sequence, such as %0A,
if (2 === h.length) { // with binary escape, such as 0x0A
return h; var binstr = escstr.replace(/%([0-9A-F]{2})/g, function(match, p1) {
} return String.fromCharCode('0x' + p1);
});
return binstr.split('').map(function (b) {
var h = b.charCodeAt(0).toString(16);
if (2 === h.length) { return h; }
return '0' + h; return '0' + h;
}).join(''); }).join('');
} }
@ -249,7 +254,7 @@ function fromHex(hex) {
function createCsrBodyEc(domains, xy) { function createCsrBodyEc(domains, xy) {
var altnames = domains.map(function (d) { var altnames = domains.map(function (d) {
return csrDomains.replace(/{dlen}/, numToHex(d.length)).replace(/{domain\.tld}/, strToHex(d)); return ASN1('82', strToHex(d));
}).join('').replace(/\s+/g, ''); }).join('').replace(/\s+/g, '');
var sublen = domains[0].length; var sublen = domains[0].length;
var sanlen = (altnames.length/2); var sanlen = (altnames.length/2);
@ -272,56 +277,54 @@ function createCsrBodyEc(domains, xy) {
hxy += toHex(xy.y); hxy += toHex(xy.y);
} }
var version = ASN1.UInt('00');
var subject = ASN1('30'
, ASN1('31'
, ASN1('30'
// object id (commonName)
, ASN1('06', '55 04 03')
, ASN1('0C', strToHex(domains[0])))));
var pubkey = ASN1('30'
, ASN1('30'
// 1.2.840.10045.2.1 ecPublicKey
// (ANSI X9.62 public key type)
, ASN1('06', '2A 86 48 CE 3D 02 01')
// 1.2.840.10045.3.1.7 prime256v1
// (ANSI X9.62 named elliptic curve)
, ASN1('06', '2A 86 48 CE 3D 03 01 07')
)
, ASN1.BitStr(compression + hxy));
var altnames = ASN1('A0'
, ASN1('30'
// (extensionRequest (PKCS #9 via CRMF))
, ASN1('06', '2A 86 48 86 F7 0D 01 09 0E')
, ASN1('31'
, ASN1('30'
, ASN1('30'
// (subjectAltName (X.509 extension))
, ASN1('06', '55 1D 11')
, ASN1('04'
, ASN1('30', domains.map(function (d) {
return csrDomains.replace(/{dlen}/, numToHex(d.length)).replace(/{domain\.tld}/, strToHex(d));
}).join(''))))))));
var body = [ '30 81 {+85+n}' // 4 bytes, sequence var body = [ '30 81 {+85+n}' // 4 bytes, sequence
.replace(/{[^}]+}/, numToHex( .replace(/{[^}]+}/, numToHex(3 + 13 + sublen + 27 + publen + 30 + sanlen))
3
+ 13 + sublen
+ 27 + publen // Length for EC-related P-256 stuff
+ 30 + sanlen
))
// #0 Total 3 // #0 Total 3
, ASN1('02', '00') , version
// Subject // Subject
// #1 Total 2+11+n // #1 Total 2+11+n
, ASN1('30' , subject
, ASN1('31'
, ASN1('30'
// object id (commonName)
, ASN1('06', '55 04 03')
, ASN1('0C', strToHex(domains[0]))
)
)
)
// P-256 Public Key // P-256 Public Key
// #2 Total 2+25+xy // #2 Total 2+25+xy
, ASN1('30' , pubkey
, ASN1('30'
// 1.2.840.10045.2.1 ecPublicKey
// (ANSI X9.62 public key type)
, ASN1('06', '2A 86 48 CE 3D 02 01')
// 1.2.840.10045.3.1.7 prime256v1
// (ANSI X9.62 named elliptic curve)
, ASN1('06', '2A 86 48 CE 3D 03 01 07')
)
, BITSTR(compression + hxy)
)
// Altnames // Altnames
// #3 Total 2+28+n // #3 Total 2+28+n
, ASN1('A0' , altnames
, ASN1('30' ];
// (extensionRequest (PKCS #9 via CRMF))
, ASN1('06', '2A 86 48 86 F7 0D 01 09 0E')
, ASN1('31'
, ASN1('30'
, ASN1('30'
// (subjectAltName (X.509 extension))
, ASN1('06', '55 1D 11')
, ASN1('04'
, ASN1('30', altnames))))))) ];
body = body.join('').replace(/\s+/g, ''); body = body.join('').replace(/\s+/g, '');
return fromHex(body); return fromHex(body);
} }