WIP more asn1
This commit is contained in:
parent
ba92407194
commit
ab8ec9fa7c
107
lib/ecdsacsr.js
107
lib/ecdsacsr.js
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue