AJ ONeal пре 4 година
родитељ
комит
b1df7af626
  1. 8
      .prettierrc
  2. 12
      bin/eckles.js
  3. 12
      bin/rasha.js
  4. 26
      ecdsa.js
  5. 66
      keypairs.js
  6. 6
      lib/browser/ecdsa.js
  7. 16
      lib/browser/keypairs.js
  8. 6
      lib/browser/rsa.js
  9. 2
      lib/browser/sha2.js
  10. 16
      lib/node/ecdsa.js
  11. 2
      lib/node/generate-privkey-forge.js
  12. 2
      lib/node/generate-privkey-node.js
  13. 7
      lib/node/generate-privkey-ursa.js
  14. 2
      lib/node/generate-privkey.js
  15. 13
      lib/node/keypairs.js
  16. 12
      lib/node/rsa.js
  17. 9
      lib/node/sha2.js
  18. 26
      rsa.js
  19. 50
      tests/index.js

8
.prettierrc

@ -0,0 +1,8 @@
{
"bracketSpacing": true,
"printWidth": 80,
"singleQuote": true,
"tabWidth": 4,
"trailingComma": "none",
"useTabs": true
}

12
bin/eckles.js

@ -23,7 +23,7 @@ if (
namedCurve: format === 'P-384' ? 'P-384' : 'P-256',
encoding: format === 'der' ? 'der' : 'pem'
})
.then(function(key) {
.then(function (key) {
if ('der' === infile || 'der' === format) {
key.private = key.private.toString('binary');
key.public = key.public.toString('binary');
@ -31,7 +31,7 @@ if (
console.log(key.private);
console.log(key.public);
})
.catch(function(err) {
.catch(function (err) {
console.error(err);
process.exit(1);
});
@ -58,10 +58,10 @@ if ('string' === typeof key) {
}
var pub = -1 !== ['public', 'spki', 'pkix'].indexOf(format);
Eckles.import({ pem: key, public: pub || format })
.then(function(jwk) {
.then(function (jwk) {
console.log(JSON.stringify(jwk, null, 2));
})
.catch(function(err) {
.catch(function (err) {
console.error(err);
process.exit(1);
});
@ -71,10 +71,10 @@ if ('string' === typeof key) {
return;
}
Eckles.export({ jwk: key, format: format })
.then(function(pem) {
.then(function (pem) {
console.log(pem);
})
.catch(function(err) {
.catch(function (err) {
console.error(err);
process.exit(2);
});

12
bin/rasha.js

@ -29,7 +29,7 @@ if (
modulusLength: parseInt(format, 10) || 2048,
encoding: parseInt(format, 10) ? null : format
})
.then(function(key) {
.then(function (key) {
if ('der' === infile || 'der' === format) {
key.private = key.private.toString('binary');
key.public = key.public.toString('binary');
@ -37,7 +37,7 @@ if (
console.info(key.private);
console.info(key.public);
})
.catch(function(err) {
.catch(function (err) {
console.error(err);
process.exit(1);
});
@ -74,10 +74,10 @@ if ('string' === typeof key) {
var pub = -1 !== ['public', 'spki', 'pkix'].indexOf(format);
Rasha.import({ pem: key, public: pub || format })
.then(function(jwk) {
.then(function (jwk) {
console.info(JSON.stringify(jwk, null, 2));
})
.catch(function(err) {
.catch(function (err) {
console.error(err);
process.exit(1);
});
@ -87,14 +87,14 @@ if ('string' === typeof key) {
return;
}
Rasha.export({ jwk: key, format: format })
.then(function(pem) {
.then(function (pem) {
if (sign) {
signMessage(pem, msg);
return;
}
console.info(pem);
})
.catch(function(err) {
.catch(function (err) {
console.error(err);
process.exit(2);
});

26
ecdsa.js

@ -29,8 +29,8 @@ EC._universal =
'Bluecrypt only supports crypto with standard cross-browser and cross-platform support.';
EC.generate = native.generate;
EC.export = function(opts) {
return Promise.resolve().then(function() {
EC.export = function (opts) {
return Promise.resolve().then(function () {
if (!opts || !opts.jwk || 'object' !== typeof opts.jwk) {
throw new Error('must pass { jwk: jwk } as a JSON object');
}
@ -109,8 +109,8 @@ EC.export = function(opts) {
};
native.export = EC.export;
EC.import = function(opts) {
return Promise.resolve().then(function() {
EC.import = function (opts) {
return Promise.resolve().then(function () {
if (!opts || !opts.pem || 'string' !== typeof opts.pem) {
throw new Error('must pass { pem: pem } as a string');
}
@ -178,18 +178,18 @@ EC.import = function(opts) {
};
native.import = EC.import;
EC.pack = function(opts) {
return Promise.resolve().then(function() {
EC.pack = function (opts) {
return Promise.resolve().then(function () {
return EC.export(opts);
});
};
// Chopping off the private parts is now part of the public API.
// I thought it sounded a little too crude at first, but it really is the best name in every possible way.
EC.neuter = function(opts) {
EC.neuter = function (opts) {
// trying to find the best balance of an immutable copy with custom attributes
var jwk = {};
Object.keys(opts.jwk).forEach(function(k) {
Object.keys(opts.jwk).forEach(function (k) {
if ('undefined' === typeof opts.jwk[k]) {
return;
}
@ -204,7 +204,7 @@ EC.neuter = function(opts) {
native.neuter = EC.neuter;
// https://stackoverflow.com/questions/42588786/how-to-fingerprint-a-jwk
EC.__thumbprint = function(jwk) {
EC.__thumbprint = function (jwk) {
// Use the same entropy for SHA as for key
var alg = 'SHA-256';
if (/384/.test(jwk.crv)) {
@ -218,20 +218,20 @@ EC.__thumbprint = function(jwk) {
'","y":"' +
jwk.y +
'"}';
return sha2.sum(alg, payload).then(function(hash) {
return sha2.sum(alg, payload).then(function (hash) {
return Enc.bufToUrlBase64(Uint8Array.from(hash));
});
};
EC.thumbprint = function(opts) {
return Promise.resolve().then(function() {
EC.thumbprint = function (opts) {
return Promise.resolve().then(function () {
var jwk;
if ('EC' === opts.kty) {
jwk = opts;
} else if (opts.jwk) {
jwk = opts.jwk;
} else {
return native.import(opts).then(function(jwk) {
return native.import(opts).then(function (jwk) {
return EC.__thumbprint(jwk);
});
}

66
keypairs.js

@ -9,7 +9,7 @@ var Rasha = require('./rsa.js');
var Eckles = require('./ecdsa.js');
var native = require('./lib/node/keypairs.js');
Keypairs.parse = function(opts) {
Keypairs.parse = function (opts) {
opts = opts || {};
var err;
@ -21,7 +21,7 @@ Keypairs.parse = function(opts) {
try {
jwk = JSON.parse(opts.key);
p = Keypairs.export({ jwk: jwk })
.catch(function(e) {
.catch(function (e) {
pem = opts.key;
err = new Error(
"Not a valid jwk '" +
@ -32,11 +32,11 @@ Keypairs.parse = function(opts) {
err.code = 'EINVALID';
return Promise.reject(err);
})
.then(function() {
.then(function () {
return jwk;
});
} catch (e) {
p = Keypairs.import({ pem: opts.key }).catch(function(e) {
p = Keypairs.import({ pem: opts.key }).catch(function (e) {
err = new Error(
'Could not parse key (type ' +
typeof opts.key +
@ -53,10 +53,10 @@ Keypairs.parse = function(opts) {
p = Promise.resolve(opts.key);
}
return p.then(function(jwk) {
return p.then(function (jwk) {
var pubopts = JSON.parse(JSON.stringify(opts));
pubopts.jwk = jwk;
return Keypairs.publish(pubopts).then(function(pub) {
return Keypairs.publish(pubopts).then(function (pub) {
// 'd' happens to be the name of a private part of both RSA and ECDSA keys
if (opts.public || opts.publish || !jwk.d) {
if (opts.private) {
@ -75,13 +75,13 @@ Keypairs.parse = function(opts) {
});
};
Keypairs.parseOrGenerate = function(opts) {
Keypairs.parseOrGenerate = function (opts) {
if (!opts.key) {
return Keypairs.generate(opts);
}
opts.private = true;
return Keypairs.parse(opts).catch(function(e) {
return Keypairs.generate(opts).then(function(pair) {
return Keypairs.parse(opts).catch(function (e) {
return Keypairs.generate(opts).then(function (pair) {
pair.parseError = e;
return pair;
});
@ -93,7 +93,7 @@ Keypairs._stance =
" properly and securely use non-standard crypto then you shouldn't need Bluecrypt anyway.";
Keypairs._universal =
'Bluecrypt only supports crypto with standard cross-browser and cross-platform support.';
Keypairs.generate = function(opts) {
Keypairs.generate = function (opts) {
opts = opts || {};
var p;
if (!opts.kty) {
@ -117,8 +117,8 @@ Keypairs.generate = function(opts) {
)
);
}
return p.then(function(pair) {
return Keypairs.thumbprint({ jwk: pair.public }).then(function(thumb) {
return p.then(function (pair) {
return Keypairs.thumbprint({ jwk: pair.public }).then(function (thumb) {
pair.private.kid = thumb; // maybe not the same id on the private key?
pair.public.kid = thumb;
return pair;
@ -126,22 +126,22 @@ Keypairs.generate = function(opts) {
});
};
Keypairs.import = function(opts) {
Keypairs.import = function (opts) {
return Eckles.import(opts)
.catch(function() {
.catch(function () {
return Rasha.import(opts);
})
.then(function(jwk) {
return Keypairs.thumbprint({ jwk: jwk }).then(function(thumb) {
.then(function (jwk) {
return Keypairs.thumbprint({ jwk: jwk }).then(function (thumb) {
jwk.kid = thumb;
return jwk;
});
});
};
Keypairs.export = function(opts) {
return Eckles.export(opts).catch(function(err) {
return Rasha.export(opts).catch(function() {
Keypairs.export = function (opts) {
return Eckles.export(opts).catch(function (err) {
return Rasha.export(opts).catch(function () {
return Promise.reject(err);
});
});
@ -153,10 +153,10 @@ native.export = Keypairs.export;
* Chopping off the private parts is now part of the public API.
* I thought it sounded a little too crude at first, but it really is the best name in every possible way.
*/
Keypairs.neuter = function(opts) {
Keypairs.neuter = function (opts) {
/** trying to find the best balance of an immutable copy with custom attributes */
var jwk = {};
Object.keys(opts.jwk).forEach(function(k) {
Object.keys(opts.jwk).forEach(function (k) {
if ('undefined' === typeof opts.jwk[k]) {
return;
}
@ -169,8 +169,8 @@ Keypairs.neuter = function(opts) {
return jwk;
};
Keypairs.thumbprint = function(opts) {
return Promise.resolve().then(function() {
Keypairs.thumbprint = function (opts) {
return Promise.resolve().then(function () {
if (/EC/i.test(opts.jwk.kty)) {
return Eckles.thumbprint(opts);
} else {
@ -179,7 +179,7 @@ Keypairs.thumbprint = function(opts) {
});
};
Keypairs.publish = function(opts) {
Keypairs.publish = function (opts) {
if ('object' !== typeof opts.jwk || !opts.jwk.kty) {
throw new Error('invalid jwk: ' + JSON.stringify(opts.jwk));
}
@ -205,15 +205,15 @@ Keypairs.publish = function(opts) {
if (jwk.kid) {
return Promise.resolve(jwk);
}
return Keypairs.thumbprint({ jwk: jwk }).then(function(thumb) {
return Keypairs.thumbprint({ jwk: jwk }).then(function (thumb) {
jwk.kid = thumb;
return jwk;
});
};
// JWT a.k.a. JWS with Claims using Compact Serialization
Keypairs.signJwt = function(opts) {
return Keypairs.thumbprint({ jwk: opts.jwk }).then(function(thumb) {
Keypairs.signJwt = function (opts) {
return Keypairs.thumbprint({ jwk: opts.jwk }).then(function (thumb) {
var header = opts.header || {};
var claims = JSON.parse(JSON.stringify(opts.claims || {}));
header.typ = 'JWT';
@ -260,14 +260,14 @@ Keypairs.signJwt = function(opts) {
protected: header,
header: undefined,
payload: claims
}).then(function(jws) {
}).then(function (jws) {
return [jws.protected, jws.payload, jws.signature].join('.');
});
});
};
Keypairs.signJws = function(opts) {
return Keypairs.thumbprint(opts).then(function(thumb) {
Keypairs.signJws = function (opts) {
return Keypairs.thumbprint(opts).then(function (thumb) {
function alg() {
if (!opts.jwk) {
throw new Error("opts.jwk must exist and must declare 'typ'");
@ -321,7 +321,7 @@ Keypairs.signJws = function(opts) {
var payload64 = Enc.bufToUrlBase64(payload);
var msg = protected64 + '.' + payload64;
return native._sign(opts, msg).then(function(buf) {
return native._sign(opts, msg).then(function (buf) {
var signedMsg = {
protected: protected64,
payload: payload64,
@ -335,7 +335,7 @@ Keypairs.signJws = function(opts) {
if (opts.jwk) {
return sign();
} else {
return Keypairs.import({ pem: opts.pem }).then(function(pair) {
return Keypairs.import({ pem: opts.pem }).then(function (pair) {
opts.jwk = pair.private;
return sign();
});
@ -346,7 +346,7 @@ Keypairs.signJws = function(opts) {
// TODO expose consistently
Keypairs.sign = native._sign;
Keypairs._getBits = function(opts) {
Keypairs._getBits = function (opts) {
if (opts.alg) {
return opts.alg.replace(/[a-z\-]/gi, '');
}

6
lib/browser/ecdsa.js

@ -4,7 +4,7 @@ var native = module.exports;
// XXX received from caller
var EC = native;
native.generate = function(opts) {
native.generate = function (opts) {
var wcOpts = {};
if (!opts) {
opts = {};
@ -41,10 +41,10 @@ native.generate = function(opts) {
var extractable = true;
return window.crypto.subtle
.generateKey(wcOpts, extractable, ['sign', 'verify'])
.then(function(result) {
.then(function (result) {
return window.crypto.subtle
.exportKey('jwk', result.privateKey)
.then(function(privJwk) {
.then(function (privJwk) {
privJwk.key_ops = undefined;
privJwk.ext = undefined;
return {

16
lib/browser/keypairs.js

@ -2,8 +2,8 @@
var Keypairs = module.exports;
Keypairs._sign = function(opts, payload) {
return Keypairs._import(opts).then(function(privkey) {
Keypairs._sign = function (opts, payload) {
return Keypairs._import(opts).then(function (privkey) {
if ('string' === typeof payload) {
payload = new TextEncoder().encode(payload);
}
@ -17,7 +17,7 @@ Keypairs._sign = function(opts, payload) {
privkey,
payload
)
.then(function(signature) {
.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)) {
@ -30,8 +30,8 @@ Keypairs._sign = function(opts, payload) {
});
};
Keypairs._import = function(opts) {
return Promise.resolve().then(function() {
Keypairs._import = function (opts) {
return Promise.resolve().then(function () {
var ops;
// all private keys just happen to have a 'd'
if (opts.jwk.d) {
@ -55,7 +55,7 @@ Keypairs._import = function(opts) {
true,
ops
)
.then(function(privkey) {
.then(function (privkey) {
delete opts.jwk.ext;
return privkey;
});
@ -64,7 +64,7 @@ Keypairs._import = function(opts) {
// 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) {
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
@ -99,7 +99,7 @@ Keypairs._ecdsaJoseSigToAsn1Sig = function(bufsig) {
);
};
Keypairs._getName = function(opts) {
Keypairs._getName = function (opts) {
if (/EC/i.test(opts.jwk.kty)) {
return 'ECDSA';
} else {

6
lib/browser/rsa.js

@ -4,7 +4,7 @@ var native = module.exports;
// XXX added by caller: _stance, neuter
var RSA = native;
native.generate = function(opts) {
native.generate = function (opts) {
var wcOpts = {};
if (!opts) {
opts = {};
@ -46,10 +46,10 @@ native.generate = function(opts) {
var extractable = true;
return window.crypto.subtle
.generateKey(wcOpts, extractable, ['sign', 'verify'])
.then(function(result) {
.then(function (result) {
return window.crypto.subtle
.exportKey('jwk', result.privateKey)
.then(function(privJwk) {
.then(function (privJwk) {
return {
private: privJwk,
public: RSA.neuter({ jwk: privJwk })

2
lib/browser/sha2.js

@ -3,7 +3,7 @@
var sha2 = module.exports;
var encoder = new TextEncoder();
sha2.sum = function(alg, str) {
sha2.sum = function (alg, str) {
var data = str;
if ('string' === typeof data) {
data = encoder.encode(str);

16
lib/node/ecdsa.js

@ -5,8 +5,8 @@ var native = module.exports;
var EC = native;
// TODO SSH
native.generate = function(opts) {
return Promise.resolve().then(function() {
native.generate = function (opts) {
return Promise.resolve().then(function () {
var typ = 'ec';
var format = opts.format;
var encoding = opts.encoding;
@ -48,7 +48,7 @@ native.generate = function(opts) {
pub = { type: 'spki', format: 'pem' };
}
return new Promise(function(resolve, reject) {
return new Promise(function (resolve, reject) {
return require('crypto').generateKeyPair(
typ,
{
@ -56,7 +56,7 @@ native.generate = function(opts) {
privateKeyEncoding: priv,
publicKeyEncoding: pub
},
function(err, pubkey, privkey) {
function (err, pubkey, privkey) {
if (err) {
reject(err);
}
@ -66,7 +66,7 @@ native.generate = function(opts) {
});
}
);
}).then(function(keypair) {
}).then(function (keypair) {
if ('jwk' === format) {
return Promise.all([
native.import({
@ -78,7 +78,7 @@ native.generate = function(opts) {
format: pub.type,
public: true
})
]).then(function(pair) {
]).then(function (pair) {
return {
private: pair[0],
public: pair[1]
@ -96,12 +96,12 @@ native.generate = function(opts) {
format: format,
public: true
})
.then(function(jwk) {
.then(function (jwk) {
return EC.export({
jwk: jwk,
format: opts.format,
public: true
}).then(function(pub) {
}).then(function (pub) {
return {
private: keypair.private,
public: pub

2
lib/node/generate-privkey-forge.js

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
module.exports = function(bitlen, exp) {
module.exports = function (bitlen, exp) {
var k = require('node-forge').pki.rsa.generateKeyPair({
bits: bitlen || 2048,
e: exp || 0x10001

2
lib/node/generate-privkey-node.js

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
module.exports = function(bitlen, exp) {
module.exports = function (bitlen, exp) {
var keypair = require('crypto').generateKeyPairSync('rsa', {
modulusLength: bitlen,
publicExponent: exp,

7
lib/node/generate-privkey-ursa.js

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
module.exports = function(bitlen, exp) {
module.exports = function (bitlen, exp) {
var ursa;
try {
ursa = require('ursa');
@ -13,10 +13,7 @@ module.exports = function(bitlen, exp) {
}
var keypair = ursa.generatePrivateKey(bitlen, exp);
var result = {
privateKeyPem: keypair
.toPrivatePem()
.toString('ascii')
.trim()
privateKeyPem: keypair.toPrivatePem().toString('ascii').trim()
};
return result;
};

2
lib/node/generate-privkey.js

@ -6,7 +6,7 @@
var oldver = false;
module.exports = function(bitlen, exp) {
module.exports = function (bitlen, exp) {
bitlen = parseInt(bitlen, 10) || 2048;
exp = parseInt(exp, 10) || 65537;

13
lib/node/keypairs.js

@ -3,17 +3,14 @@
var Keypairs = module.exports;
var crypto = require('crypto');
Keypairs._sign = function(opts, payload) {
return Keypairs._import(opts).then(function(pem) {
Keypairs._sign = function (opts, payload) {
return Keypairs._import(opts).then(function (pem) {
payload = Buffer.from(payload);
// node specifies RSA-SHAxxx even when it's actually ecdsa (it's all encoded x509 shasums anyway)
// TODO opts.alg = (protect||header).alg
var nodeAlg = 'SHA' + Keypairs._getBits(opts);
var binsig = crypto
.createSign(nodeAlg)
.update(payload)
.sign(pem);
var binsig = crypto.createSign(nodeAlg).update(payload).sign(pem);
if ('EC' === opts.jwk.kty && !/x509|asn1/i.test(opts.format)) {
// ECDSA JWT signatures differ from "normal" ECDSA signatures
@ -25,7 +22,7 @@ Keypairs._sign = function(opts, payload) {
});
};
Keypairs._import = function(opts) {
Keypairs._import = function (opts) {
if (opts.pem && opts.jwk) {
return Promise.resolve(opts.pem);
} else {
@ -34,7 +31,7 @@ Keypairs._import = function(opts) {
}
};
Keypairs._ecdsaAsn1SigToJoseSig = function(binsig) {
Keypairs._ecdsaAsn1SigToJoseSig = function (binsig) {
// should have asn1 sequence header of 0x30
if (0x30 !== binsig[0]) {
throw new Error('Impossible EC SHA head marker');

12
lib/node/rsa.js

@ -7,9 +7,9 @@ var RSA = native;
var PEM = require('@root/pem');
var X509 = require('@root/x509');
native.generate = function(opts) {
native.generate = function (opts) {
opts.kty = 'RSA';
return native._generate(opts).then(function(pair) {
return native._generate(opts).then(function (pair) {
var format = opts.format;
var encoding = opts.encoding;
@ -74,23 +74,23 @@ native.generate = function(opts) {
}
var exOpts = { jwk: pair.private, format: format, encoding: encoding };
return RSA.export(exOpts).then(function(priv) {
return RSA.export(exOpts).then(function (priv) {
exOpts.public = true;
if ('pkcs8' === exOpts.format) {
exOpts.format = 'spki';
}
return RSA.export(exOpts).then(function(pub) {
return RSA.export(exOpts).then(function (pub) {
return { private: priv, public: pub };
});
});
});
};
native._generate = function(opts) {
native._generate = function (opts) {
if (!opts) {
opts = {};
}
return new Promise(function(resolve, reject) {
return new Promise(function (resolve, reject) {
try {
var modlen = opts.modulusLength || 2048;
var exp = opts.publicExponent || 0x10001;

9
lib/node/sha2.js

@ -4,14 +4,11 @@
var sha2 = module.exports;
var crypto = require('crypto');
sha2.sum = function(alg, str) {
return Promise.resolve().then(function() {
sha2.sum = function (alg, str) {
return Promise.resolve().then(function () {
var sha = 'sha' + String(alg).replace(/^sha-?/i, '');
// utf8 is the default for strings
var buf = Buffer.from(str);
return crypto
.createHash(sha)
.update(buf)
.digest();
return crypto.createHash(sha).update(buf).digest();
});
};

26
rsa.js

@ -20,10 +20,10 @@ RSA.generate = native.generate;
// Chopping off the private parts is now part of the public API.
// I thought it sounded a little too crude at first, but it really is the best name in every possible way.
RSA.neuter = function(opts) {
RSA.neuter = function (opts) {
// trying to find the best balance of an immutable copy with custom attributes
var jwk = {};
Object.keys(opts.jwk).forEach(function(k) {
Object.keys(opts.jwk).forEach(function (k) {
if ('undefined' === typeof opts.jwk[k]) {
return;
}
@ -38,7 +38,7 @@ RSA.neuter = function(opts) {
native.neuter = RSA.neuter;
// https://stackoverflow.com/questions/42588786/how-to-fingerprint-a-jwk
RSA.__thumbprint = function(jwk) {
RSA.__thumbprint = function (jwk) {
// Use the same entropy for SHA as for key
var len = Math.floor(jwk.n.length * 0.75);
var alg = 'SHA-256';
@ -51,20 +51,20 @@ RSA.__thumbprint = function(jwk) {
}
return sha2
.sum(alg, '{"e":"' + jwk.e + '","kty":"RSA","n":"' + jwk.n + '"}')
.then(function(hash) {
.then(function (hash) {
return Enc.bufToUrlBase64(Uint8Array.from(hash));
});
};
RSA.thumbprint = function(opts) {
return Promise.resolve().then(function() {
RSA.thumbprint = function (opts) {
return Promise.resolve().then(function () {
var jwk;
if ('EC' === opts.kty) {
jwk = opts;
} else if (opts.jwk) {
jwk = opts.jwk;
} else {
return RSA.import(opts).then(function(jwk) {
return RSA.import(opts).then(function (jwk) {
return RSA.__thumbprint(jwk);
});
}
@ -72,8 +72,8 @@ RSA.thumbprint = function(opts) {
});
};
RSA.export = function(opts) {
return Promise.resolve().then(function() {
RSA.export = function (opts) {
return Promise.resolve().then(function () {
if (!opts || !opts.jwk || 'object' !== typeof opts.jwk) {
throw new Error('must pass { jwk: jwk }');
}
@ -152,16 +152,16 @@ RSA.export = function(opts) {
};
native.export = RSA.export;
RSA.pack = function(opts) {
RSA.pack = function (opts) {
// wrapped in a promise for API compatibility
// with the forthcoming browser version
// (and potential future native node capability)
return Promise.resolve().then(function() {
return Promise.resolve().then(function () {
return RSA.export(opts);
});
};
RSA._importSync = function(opts) {
RSA._importSync = function (opts) {
if (!opts || !opts.pem || 'string' !== typeof opts.pem) {
throw new Error('must pass { pem: pem } as a string');
}
@ -185,7 +185,7 @@ RSA.parse = function parseRsa(opts) {
// wrapped in a promise for API compatibility
// with the forthcoming browser version
// (and potential future native node capability)
return Promise.resolve().then(function() {
return Promise.resolve().then(function () {
return RSA._importSync(opts);
});
};

50
tests/index.js

@ -4,7 +4,7 @@ var Keypairs = require('../');
/* global Promise*/
Keypairs.parseOrGenerate({ key: null })
.then(function(pair) {
.then(function (pair) {
// should NOT have any warning output
if (!pair.private || !pair.public) {
throw new Error('missing key pairs');
@ -12,42 +12,42 @@ Keypairs.parseOrGenerate({ key: null })
return Promise.all([
// Testing Public Part of key
Keypairs.export({ jwk: pair.public }).then(function(pem) {
Keypairs.export({ jwk: pair.public }).then(function (pem) {
if (!/--BEGIN PUBLIC/.test(pem)) {
throw new Error('did not export public pem');
}
return Promise.all([
Keypairs.parse({ key: pem }).then(function(pair) {
Keypairs.parse({ key: pem }).then(function (pair) {
if (pair.private) {
throw new Error("shouldn't have private part");
}
return true;
}),
Keypairs.parse({ key: pem, private: true })
.then(function() {
.then(function () {
var err = new Error(
'should have thrown an error when private key was required and public pem was given'
);
err.code = 'NOERR';
throw err;
})
.catch(function(e) {
.catch(function (e) {
if ('NOERR' === e.code) {
throw e;
}
return true;
})
]).then(function() {
]).then(function () {
return true;
});
}),
// Testing Private Part of Key
Keypairs.export({ jwk: pair.private }).then(function(pem) {
Keypairs.export({ jwk: pair.private }).then(function (pem) {
if (!/--BEGIN .*PRIVATE KEY--/.test(pem)) {
throw new Error('did not export private pem: ' + pem);
}
return Promise.all([
Keypairs.parse({ key: pem }).then(function(pair) {
Keypairs.parse({ key: pem }).then(function (pair) {
if (!pair.private) {
throw new Error('should have private part');
}
@ -56,7 +56,7 @@ Keypairs.parseOrGenerate({ key: null })
}
return true;
}),
Keypairs.parse({ key: pem, public: true }).then(function(
Keypairs.parse({ key: pem, public: true }).then(function (
pair
) {
if (pair.private) {
@ -69,12 +69,12 @@ Keypairs.parseOrGenerate({ key: null })
}
return true;
})
]).then(function() {
]).then(function () {
return true;
});
}),
Keypairs.parseOrGenerate({ key: 'not a key', public: true }).then(
function(pair) {
function (pair) {
// SHOULD have warning output
if (!pair.private || !pair.public) {
throw new Error(
@ -89,18 +89,18 @@ Keypairs.parseOrGenerate({ key: null })
return true;
}
),
Keypairs.parse({ key: JSON.stringify(pair.private) }).then(function(
pair
) {
if (!pair.private || !pair.public) {
throw new Error('missing key pairs (stringified jwt)');
Keypairs.parse({ key: JSON.stringify(pair.private) }).then(
function (pair) {
if (!pair.private || !pair.public) {
throw new Error('missing key pairs (stringified jwt)');
}
return true;
}
return true;
}),
),
Keypairs.parse({
key: JSON.stringify(pair.private),
public: true
}).then(function(pair) {
}).then(function (pair) {
if (pair.private) {
throw new Error("has private key when it shouldn't");
}
@ -110,14 +110,14 @@ Keypairs.parseOrGenerate({ key: null })
return true;
}),
Keypairs.parse({ key: JSON.stringify(pair.public), private: true })
.then(function() {
.then(function () {
var err = new Error(
'should have thrown an error when private key was required and public jwk was given'
);
err.code = 'NOERR';
throw err;
})
.catch(function(e) {
.catch(function (e) {
if ('NOERR' === e.code) {
throw e;
}
@ -130,7 +130,7 @@ Keypairs.parseOrGenerate({ key: null })
alg: 'ES256',
iss: 'https://example.com/',
exp: '1h'
}).then(function(jwt) {
}).then(function (jwt) {
var parts = jwt.split('.');
var now = Math.round(Date.now() / 1000);
var token = {
@ -144,10 +144,10 @@ Keypairs.parseOrGenerate({ key: null })
}
throw new Error('token was not properly generated');
})
]).then(function(results) {
]).then(function (results) {
if (
results.length &&
results.every(function(v) {
results.every(function (v) {
return true === v;
})
) {
@ -158,7 +158,7 @@ Keypairs.parseOrGenerate({ key: null })
}
});
})
.catch(function(e) {
.catch(function (e) {
console.error('Caught an unexpected (failing) error:');
console.error(e);
process.exit(1);

Loading…
Откажи
Сачувај