diff --git a/lib/generate-privkey-forge.js b/lib/generate-privkey-forge.js new file mode 100644 index 0000000..686466f --- /dev/null +++ b/lib/generate-privkey-forge.js @@ -0,0 +1,41 @@ +'use strict'; + +var Rasha = require('rasha'); + +module.exports = function (bitlen, exp) { + var k = require('node-forge').pki.rsa + .generateKeyPair({ bits: bitlen || 2048, e: exp || 0x10001 }).privateKey; + return Rasha.exportSync({ + jwk: { + kty: "RSA" + , n: _toUrlBase64(k.n) + , e: _toUrlBase64(k.e) + , d: _toUrlBase64(k.d) + , p: _toUrlBase64(k.p) + , q: _toUrlBase64(k.q) + , dp: _toUrlBase64(k.dP) + , dq: _toUrlBase64(k.dQ) + , qi: _toUrlBase64(k.qInv) + } + }); +}; + +function _toUrlBase64(fbn) { + var hex = fbn.toRadix(16); + if (hex.length % 2) { + // Invalid hex string + hex = '0' + hex; + } + while ('00' === hex.slice(0, 2)) { + hex = hex.slice(2); + } + return Buffer.from(hex, 'hex').toString('base64') + .replace(/\+/g, "-") + .replace(/\//g, "_") + .replace(/=/g,"") + ; +} + +if (require.main === module) { + console.log(module.exports(2048, 0x10001)); +} diff --git a/lib/generate-privkey-node.js b/lib/generate-privkey-node.js new file mode 100644 index 0000000..0a2ff88 --- /dev/null +++ b/lib/generate-privkey-node.js @@ -0,0 +1,22 @@ +'use strict'; + +module.exports = function (bitlen, exp) { + return require('crypto').generateKeyPairSync( + 'rsa' + , { modulusLength: bitlen + , publicExponent: exp + , privateKeyEncoding: { + type: 'pkcs8' + , format: 'pem' + } + , publicKeyEncoding: { + type: 'spki' + , format: 'pem' + } + } + ).privateKey.trim(); +}; + +if (require.main === module) { + console.log(module.exports(2048, 0x10001)); +} diff --git a/lib/generate-privkey-ursa.js b/lib/generate-privkey-ursa.js new file mode 100644 index 0000000..4fbb501 --- /dev/null +++ b/lib/generate-privkey-ursa.js @@ -0,0 +1,9 @@ +'use strict'; + +module.exports = function (bitlen, exp) { + return require('ursa').generatePrivateKey(bitlen || 2048, exp || 65537).toPrivatePem().toString('ascii').trim(); +}; + +if (require.main === module) { + console.log(module.exports(2048, 0x10001)); +} diff --git a/lib/generate-privkey.js b/lib/generate-privkey.js new file mode 100644 index 0000000..afeb484 --- /dev/null +++ b/lib/generate-privkey.js @@ -0,0 +1,42 @@ +'use strict'; + +var oldver = false; + +module.exports = function (bitlen, exp) { + bitlen = parseInt(bitlen, 10); + exp = parseInt(exp, 10); + + try { + return require('./generate-privkey-node')(bitlen, exp); + } catch(e) { + if (!/generateKeyPairSync is not a function/.test(e.message)) { + throw e; + } + try { + return require('./generate-privkey-ursa')(bitlen, exp); + } catch(e) { + if (e.code !== 'MODULE_NOT_FOUND') { + throw e; + } + if (!oldver) { + oldver = true; + console.warn("[WARN] rsa-compat: Your version of node does not have crypto.generateKeyPair()"); + console.warn("[WARN] rsa-compat: Please update to node >= v10.12 or 'npm install ursa'"); + console.warn("[WARN] rsa-compat: Using node-forge as a fallback, but it may be unacceptably slow."); + } + try { + return require('./generate-privkey-forge')(bitlen, exp); + } catch(e) { + if (e.code !== 'MODULE_NOT_FOUND') { + throw e; + } + console.error("[ERROR] rsa-compat: could not generate a private key."); + console.error("None of crypto.generateKeyPair, ursa, nor node-forge are present"); + } + } + } +}; + +if (require.main === module) { + console.log(module.exports(2048, 0x10001)); +}