Lightweight, Zero-Dependency RSA and EC/ECDSA crypto for Node.js and Browsers
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 

108 lignes
2.5 KiB

'use strict';
var Keypairs = module.exports;
Keypairs._sign = function (opts, payload) {
return Keypairs._import(opts).then(function (privkey) {
if ('string' === typeof payload) {
payload = new TextEncoder().encode(payload);
}
return window.crypto.subtle
.sign(
{
name: Keypairs._getName(opts),
hash: { name: 'SHA-' + Keypairs._getBits(opts) }
},
privkey,
payload
)
.then(function (signature) {
signature = new Uint8Array(signature); // ArrayBuffer -> u8
// This will come back into play for CSRs, but not for JOSE
if ('EC' === opts.jwk.kty && /x509|asn1/i.test(opts.format)) {
return Keypairs._ecdsaJoseSigToAsn1Sig(signature);
} else {
// jose/jws/jwt
return signature;
}
});
});
};
Keypairs._import = function (opts) {
return Promise.resolve().then(function () {
var ops;
// all private keys just happen to have a 'd'
if (opts.jwk.d) {
ops = ['sign'];
} else {
ops = ['verify'];
}
// gotta mark it as extractable, as if it matters
opts.jwk.ext = true;
opts.jwk.key_ops = ops;
return window.crypto.subtle
.importKey(
'jwk',
opts.jwk,
{
name: Keypairs._getName(opts),
namedCurve: opts.jwk.crv,
hash: { name: 'SHA-' + Keypairs._getBits(opts) }
},
true,
ops
)
.then(function (privkey) {
delete opts.jwk.ext;
return privkey;
});
});
};
// ECDSA JOSE / JWS / JWT signatures differ from "normal" ASN1/X509 ECDSA signatures
// https://tools.ietf.org/html/rfc7518#section-3.4
Keypairs._ecdsaJoseSigToAsn1Sig = function (bufsig) {
// it's easier to do the manipulation in the browser with an array
bufsig = Array.from(bufsig);
var hlen = bufsig.length / 2; // should be even
var r = bufsig.slice(0, hlen);
var s = bufsig.slice(hlen);
// unpad positive ints less than 32 bytes wide
while (!r[0]) {
r = r.slice(1);
}
while (!s[0]) {
s = s.slice(1);
}
// pad (or re-pad) ambiguously non-negative BigInts, up to 33 bytes wide
if (0x80 & r[0]) {
r.unshift(0);
}
if (0x80 & s[0]) {
s.unshift(0);
}
var len = 2 + r.length + 2 + s.length;
var head = [0x30];
// hard code 0x80 + 1 because it won't be longer than
// two SHA512 plus two pad bytes (130 bytes <= 256)
if (len >= 0x80) {
head.push(0x81);
}
head.push(len);
return Uint8Array.from(
head.concat([0x02, r.length], r, [0x02, s.length], s)
);
};
Keypairs._getName = function (opts) {
if (/EC/i.test(opts.jwk.kty)) {
return 'ECDSA';
} else {
return 'RSASSA-PKCS1-v1_5';
}
};