partial implementations
This commit is contained in:
parent
2aced3a54d
commit
0ebedd4e74
|
@ -0,0 +1,76 @@
|
||||||
|
// Copyright 2014 ISRG. All rights reserved
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var utils = {
|
||||||
|
|
||||||
|
fromStandardB64: function(x) {
|
||||||
|
return x.replace(/[+]/g, "-").replace(/\//g, "_").replace(/=/g,"");
|
||||||
|
},
|
||||||
|
|
||||||
|
toStandardB64: function(x) {
|
||||||
|
var b64 = x.replace(/-/g, "+").replace(/_/g, "/").replace(/=/g, "");
|
||||||
|
|
||||||
|
switch (b64.length % 4) {
|
||||||
|
case 2: b64 += "=="; break;
|
||||||
|
case 3: b64 += "="; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return b64;
|
||||||
|
},
|
||||||
|
|
||||||
|
b64enc: function(buffer) {
|
||||||
|
return utils.fromStandardB64(buffer.toString("base64"));
|
||||||
|
},
|
||||||
|
|
||||||
|
b64dec: function(str) {
|
||||||
|
return new Buffer(utils.toStandardB64(str), "base64");
|
||||||
|
},
|
||||||
|
|
||||||
|
isB64String: function(x) {
|
||||||
|
return ("string" === typeof x) && !x.match(/[^a-zA-Z0-9_-]/);
|
||||||
|
},
|
||||||
|
|
||||||
|
fieldsPresent: function(fields, object) {
|
||||||
|
for (var i in fields) {
|
||||||
|
if (!(fields[i] in object)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
validSignature: function(sig) {
|
||||||
|
return (("object" === typeof sig) &&
|
||||||
|
("alg" in sig) && ("string" === typeof sig.alg) &&
|
||||||
|
("nonce" in sig) && utils.isB64String(sig.nonce) &&
|
||||||
|
("sig" in sig) && utils.isB64String(sig.sig) &&
|
||||||
|
("jwk" in sig) && utils.validJWK(sig.jwk));
|
||||||
|
},
|
||||||
|
|
||||||
|
validJWK: function(jwk) {
|
||||||
|
return (("object" === typeof jwk) && ("kty" in jwk) && (
|
||||||
|
((jwk.kty === "RSA")
|
||||||
|
&& ("n" in jwk) && utils.isB64String(jwk.n)
|
||||||
|
&& ("e" in jwk) && utils.isB64String(jwk.e)) ||
|
||||||
|
((jwk.kty === "EC")
|
||||||
|
&& ("crv" in jwk)
|
||||||
|
&& ("x" in jwk) && utils.isB64String(jwk.x)
|
||||||
|
&& ("y" in jwk) && utils.isB64String(jwk.y))
|
||||||
|
) && !("d" in jwk));
|
||||||
|
},
|
||||||
|
|
||||||
|
// A simple, non-standard fingerprint for a JWK,
|
||||||
|
// just so that we don't have to store objects
|
||||||
|
keyFingerprint: function(jwk) {
|
||||||
|
switch (jwk.kty) {
|
||||||
|
case "RSA": return jwk.n;
|
||||||
|
case "EC": return jwk.crv + jwk.x + jwk.y;
|
||||||
|
}
|
||||||
|
throw "Unrecognized key type";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = utils;
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*!
|
||||||
|
* rsa-compat
|
||||||
|
* Copyright(c) 2016 AJ ONeal <aj@daplie.com> https://daplie.com
|
||||||
|
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var cryptoc = {};
|
||||||
|
var rsaExtra = require('./rsa-extra');
|
||||||
|
var rsaForge = require('./rsa-forge');
|
||||||
|
var ursac;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ursac = require('./rsa-ursa');
|
||||||
|
} catch(e) {
|
||||||
|
ursac = {};
|
||||||
|
// things will run a little slower on keygen, but it'll work on windows
|
||||||
|
// (but don't try this on raspberry pi - 20+ MINUTES key generation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// order of crypto precdence is
|
||||||
|
// * native
|
||||||
|
// * ursa
|
||||||
|
// * forge extra (the new one aimed to be less-forgey)
|
||||||
|
// * forge (fallback)
|
||||||
|
Object.keys(ursac).forEach(function (key) {
|
||||||
|
if (!cryptoc[key]) {
|
||||||
|
cryptoc[key] = ursac[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(rsaExtra).forEach(function (key) {
|
||||||
|
if (!cryptoc[key]) {
|
||||||
|
cryptoc[key] = rsaExtra[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(rsaForge).forEach(function (key) {
|
||||||
|
if (!cryptoc[key]) {
|
||||||
|
cryptoc[key] = rsaForge[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports.cryptoc = cryptoc;
|
|
@ -0,0 +1,120 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var ursa = require('ursa');
|
||||||
|
|
||||||
|
function notToJson() {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ursac = {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// to components
|
||||||
|
//
|
||||||
|
_privateJwkToComponents: function (jwk) {
|
||||||
|
var components = [];
|
||||||
|
|
||||||
|
[ 'n', 'e', 'p', 'q', 'dp', 'dq', 'qi', 'd' ].forEach(function (key) {
|
||||||
|
components.push(new Buffer(jwk[key], 'base64'));
|
||||||
|
});
|
||||||
|
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
, _publicJwkToComponents: function (jwk) {
|
||||||
|
var components = [];
|
||||||
|
[ 'n', 'e' ].forEach(function (key) {
|
||||||
|
components.push(new Buffer(jwk[key], 'base64'));
|
||||||
|
});
|
||||||
|
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Generate New Keypair
|
||||||
|
//
|
||||||
|
, generateKeypair: function (bitlen, exp, options, cb) {
|
||||||
|
var keypair = ursa.generatePrivateKey(bitlen || 2048, exp || 6553);
|
||||||
|
|
||||||
|
keypair.toJSON = notToJson;
|
||||||
|
|
||||||
|
cb(null, {
|
||||||
|
_ursa: keypair
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Export Public / Private PEMs
|
||||||
|
//
|
||||||
|
, exportPrivateKeyPem: function (keypair) {
|
||||||
|
if (keypair.privateKeyPem) {
|
||||||
|
return keypair.privateKeyPem;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keypair._ursa) {
|
||||||
|
return keypair._ursa.toPrivatePem().toString('ascii');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keypair.privateKeyJwk) {
|
||||||
|
keypair._ursa = ursa.createPrivateKeyFromComponents.apply(
|
||||||
|
ursa
|
||||||
|
, ursac._privateJwkToComponents(keypair.privateKeyJwk)
|
||||||
|
);
|
||||||
|
keypair._ursa.toJSON = notToJson;
|
||||||
|
|
||||||
|
return keypair._ursa.toPrivatePem().toString('ascii');
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("None of privateKeyPem, _ursa, or privateKeyJwk found. No way to export private key PEM");
|
||||||
|
}
|
||||||
|
, exportPublicKeyPem: function (keypair) {
|
||||||
|
if (keypair.publicKeyPem) {
|
||||||
|
return keypair.publicKeyPem;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keypair._ursa || keypair._ursaPublic) {
|
||||||
|
return (keypair._ursa || keypair._ursaPublic).toPublicPem().toString('ascii');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keypair.publicKeyJwk) {
|
||||||
|
keypair._ursaPublic = ursa.createPublicKeyFromComponents.apply(
|
||||||
|
ursa
|
||||||
|
, ursac._publicJwkToComponents(keypair.publicKeyJwk)
|
||||||
|
);
|
||||||
|
keypair._ursaPublic.toJSON = notToJson;
|
||||||
|
|
||||||
|
return keypair._ursa.toPublicPem().toString('ascii');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keypair.privateKeyJwk) {
|
||||||
|
keypair._ursa = ursa.createPrivateKeyFromComponents.apply(
|
||||||
|
ursa
|
||||||
|
, ursac._privateJwkToComponents(keypair.privateKeyJwk)
|
||||||
|
);
|
||||||
|
keypair._ursa.toJSON = notToJson;
|
||||||
|
|
||||||
|
return keypair._ursa.toPublicPem().toString('ascii');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keypair.privateKeyPem) {
|
||||||
|
keypair._ursa = ursa.createPrivateKey(keypair.privateKeyPem);
|
||||||
|
keypair._ursa.toJSON = notToJson;
|
||||||
|
|
||||||
|
return keypair._ursa.toPublicPem().toString('ascii');
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("None of publicKeyPem, _ursa, publicKeyJwk, privateKeyPem, or privateKeyJwk found. No way to export public key PEM");
|
||||||
|
}
|
||||||
|
//, exportPrivateKeyJwk: NOT IMPLEMENTED HERE
|
||||||
|
//, exportPublicKeyJwk: NOT IMPLEMENTED HERE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return ursac;
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*!
|
||||||
|
* rsa-compat
|
||||||
|
* Copyright(c) 2016 AJ ONeal <aj@daplie.com> https://daplie.com
|
||||||
|
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
var RSA = {};
|
||||||
|
var NOBJ = {};
|
||||||
|
|
||||||
|
function create(deps) {
|
||||||
|
var crypto = require('crypto');
|
||||||
|
|
||||||
|
deps = deps || {};
|
||||||
|
deps.NOBJ = {};
|
||||||
|
deps.RSA = RSA;
|
||||||
|
|
||||||
|
RSA.utils = require('./lib/key-utils.js');
|
||||||
|
|
||||||
|
RSA.utils._bytesToBuffer = function (bytes) {
|
||||||
|
var forge = require("node-forge");
|
||||||
|
return new Buffer(forge.util.bytesToHex(bytes), "hex");
|
||||||
|
};
|
||||||
|
RSA._internal = require('./lib/node').create(deps);
|
||||||
|
|
||||||
|
RSA.thumbprint = function (jwk) {
|
||||||
|
jwk = jwk.privateKeyJwk || jwk.publicKeyJwk || jwk;
|
||||||
|
if (!jwk.e || !jwk.n) {
|
||||||
|
throw new Error("You must provide an RSA jwk with 'e' and 'n' (the public components)");
|
||||||
|
}
|
||||||
|
var input = RSA.utils._bytesToBuffer('{"e":"'+ jwk.e + '","kty":"RSA","n":"'+ jwk.n +'"}');
|
||||||
|
return RSA.util.b64enc(crypto.createHash('sha256').update(input).digest());
|
||||||
|
};
|
||||||
|
|
||||||
|
RSA.generateKeypair = function (length, exponent, options, cb) {
|
||||||
|
var keypair = {
|
||||||
|
privateKeyPem: undefined
|
||||||
|
, publicKeyPem: undefined
|
||||||
|
, privateKeyJwk: undefined
|
||||||
|
, publicKeyJwk: undefined
|
||||||
|
, _ursa: undefined
|
||||||
|
, _forge: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
options = options || NOBJ;
|
||||||
|
|
||||||
|
RSA._internal.generateKeypair(length, exponent, options, function (keys) {
|
||||||
|
if (false !== options.jwk || options.thumbprint) {
|
||||||
|
keypair.privateKeyJwk = RSA._internal.exportPrivateJwk(keys);
|
||||||
|
if (options.public) {
|
||||||
|
keypair.publicKeyJwk = RSA._internal.exportPublicJwk(keys);
|
||||||
|
/*
|
||||||
|
return {
|
||||||
|
kty: keypair.privateKeyJwk.kty
|
||||||
|
, n: keypair.privateKeyJwk.n
|
||||||
|
, e: keypair.privateKeyJwk.e
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.pem) {
|
||||||
|
keypair.privateKeyPem = RSA._internal.exportPrivatePem(keys);
|
||||||
|
if (options.public) {
|
||||||
|
keypair.publicKeyPem = RSA._internal.exportPublicPem(keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.thumprint) {
|
||||||
|
keypair.thumbprint = RSA.thumbprint(keypair.privateKeyJwk /*|| keypair.publicKeyJwk*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.internal) {
|
||||||
|
//keypair._ursa = undefined;
|
||||||
|
//keypair._forge = undefined;
|
||||||
|
keypair._ursa = keys._ursa;
|
||||||
|
keypair._forge = keys._forge;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(null, keypair);
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return RSA;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.RSA = create(/*require('./lib/node')*/);
|
||||||
|
//module.exports.RSA.create = create;
|
Loading…
Reference in New Issue