generate RSA keys with node 10.12+

This commit is contained in:
AJ ONeal 2018-11-24 01:33:12 -07:00
parent 40bb9a0fdd
commit 6cd0c28b86
5 changed files with 131 additions and 9 deletions

View file

@ -5,27 +5,51 @@ Sponsored by [Root](https://therootcompany.com).
Built for [ACME.js](https://git.coolaj86.com/coolaj86/acme.js) Built for [ACME.js](https://git.coolaj86.com/coolaj86/acme.js)
and [Greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js) and [Greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js)
RSA tools. Lightweight. Zero Dependencies. Universal compatibility.
| ~550 lines of code | 3kb gzipped | 10kb minified | 18kb with comments | | ~550 lines of code | 3kb gzipped | 10kb minified | 18kb with comments |
RSA tools. Lightweight. Zero Dependencies. Universal compatibility.
* [x] Fast and Easy RSA Key Generation
* [x] PEM-to-JWK * [x] PEM-to-JWK
* [x] JWK-to-PEM * [x] JWK-to-PEM
* [x] SSH "pub" format * [x] SSH "pub" format
* [ ] ECDSA
* **Need EC or ECDSA tools?** Check out [Eckles.js](https://git.coolaj86.com/coolaj86/eckles.js)
This project is fully functional and tested (and the code is pretty clean). ## Generate RSA Key
It is considered to be complete, but if you find a bug please open an issue. Achieves the *fastest possible key generation* using node's native RSA bindings to OpenSSL,
then converts to JWK for ease-of-use.
## Looking for ECDSA as well? ```
Rasha.generate({ format: 'jwk' }).then(function (keypair) {
console.log(keypair.private);
console.log(keypair.public);
});
```
Check out [Eckles.js](https://git.coolaj86.com/coolaj86/eckles.js) **options**
* `format` defaults to `'jwk'`
* `'pkcs1'` (traditional)
* `'pkcs8'`
* `modulusLength` defaults to 2048 (must not be lower)
* generally you shouldn't pick a larger key size - they're slow
* **2048** is more than sufficient
* 3072 is way, way overkill and takes a few seconds to generate
* 4096 can take about a minute to generate and is just plain wasteful
**advanced options**
These options are provided for debugging and should not be used.
* `publicExponent` defaults to 65537 (`0x10001`)
## PEM-to-JWK ## PEM-to-JWK
* [x] PKCS#1 (traditional) * [x] PKCS#1 (traditional)
* [x] PKCS#8, SPKI/PKIX * [x] PKCS#8, SPKI/PKIX
* [x] 2048-bit, 4096-bit (and ostensibily all others) * [x] 2048-bit, 3072-bit, 4096-bit (and ostensibily all others)
* [x] SSH (RFC4716), (RFC 4716/SSH2) * [x] SSH (RFC4716), (RFC 4716/SSH2)
```js ```js

View file

@ -9,6 +9,22 @@ var ASN1 = require('../lib/asn1.js');
var infile = process.argv[2]; var infile = process.argv[2];
var format = process.argv[3]; var format = process.argv[3];
if (!infile) {
infile = 'jwk';
}
if (-1 !== [ 'jwk', 'pem', 'json', 'der', 'pkcs1', 'pkcs8', 'spki' ].indexOf(infile)) {
console.log("Generating new key...");
Rasha.generate({
format: infile
, modulusLength: parseInt(format, 10) || 2048
, encoding: parseInt(format, 10) ? null : format
}).then(function (key) {
console.log(key.private);
console.log(key.public);
});
return;
}
var key = fs.readFileSync(infile, 'ascii'); var key = fs.readFileSync(infile, 'ascii');
try { try {

View file

@ -7,6 +7,77 @@ var x509 = require('./x509.js');
var ASN1 = require('./asn1.js'); var ASN1 = require('./asn1.js');
/*global Promise*/ /*global Promise*/
RSA.generate = function (opts) {
return Promise.resolve().then(function () {
var typ = 'rsa';
var format = opts.format;
var encoding = opts.encoding;
var priv;
var pub;
if (!format) {
format = 'jwk';
}
if ('spki' === format || 'pkcs8' === format) {
format = 'pkcs8';
pub = 'spki';
}
if ('pem' === format) {
format = 'pkcs1';
encoding = 'pem';
} else if ('der' === format) {
format = 'pkcs1';
encoding = 'der';
}
if ('jwk' === format || 'json' === format) {
format = 'jwk';
encoding = 'json';
} else {
priv = format;
pub = pub || format;
}
if (!encoding) {
encoding = 'pem';
}
if (priv) {
priv = { type: priv, format: encoding };
pub = { type: pub, format: encoding };
} else {
// jwk
priv = { type: 'pkcs1', format: 'pem' };
pub = { type: 'pkcs1', format: 'pem' };
}
return new Promise(function (resolve, reject) {
return require('crypto').generateKeyPair(typ, {
modulusLength: opts.modulusLength || 2048
, publicExponent: opts.publicExponent || 0x10001
, privateKeyEncoding: priv
, publicKeyEncoding: pub
}, function (err, pubkey, privkey) {
if (err) { reject(err); }
resolve({
private: privkey
, public: pubkey
});
});
}).then(function (keypair) {
if ('jwk' !== format) {
return keypair;
}
return {
private: RSA.importSync({ pem: keypair.private, format: priv.format })
, public: RSA.importSync({ pem: keypair.public, format: pub.format, public: true })
};
});
});
};
RSA.importSync = function (opts) { RSA.importSync = function (opts) {
if (!opts || !opts.pem || 'string' !== typeof opts.pem) { if (!opts || !opts.pem || 'string' !== typeof opts.pem) {
throw new Error("must pass { pem: pem } as a string"); throw new Error("must pass { pem: pem } as a string");

View file

@ -1,6 +1,6 @@
{ {
"name": "rasha", "name": "rasha",
"version": "1.0.5", "version": "1.1.0",
"description": "💯 PEM-to-JWK and JWK-to-PEM for RSA keys in a lightweight, zero-dependency library focused on perfect universal compatibility.", "description": "💯 PEM-to-JWK and JWK-to-PEM for RSA keys in a lightweight, zero-dependency library focused on perfect universal compatibility.",
"homepage": "https://git.coolaj86.com/coolaj86/rasha.js", "homepage": "https://git.coolaj86.com/coolaj86/rasha.js",
"main": "index.js", "main": "index.js",

13
test.sh
View file

@ -121,6 +121,18 @@ rndkey() {
pemtojwk "" pemtojwk ""
jwktopem "" jwktopem ""
echo ""
echo "testing node key generation"
node bin/rasha.js > /dev/null
node bin/rasha.js jwk > /dev/null
node bin/rasha.js json 2048 > /dev/null
node bin/rasha.js der > /dev/null
node bin/rasha.js pkcs8 der > /dev/null
node bin/rasha.js pem > /dev/null
node bin/rasha.js pkcs1 pem > /dev/null
node bin/rasha.js spki > /dev/null
echo "PASS"
echo "" echo ""
echo "" echo ""
echo "Re-running tests with random keys of varying sizes" echo "Re-running tests with random keys of varying sizes"
@ -140,7 +152,6 @@ echo ""
echo "Note:" echo "Note:"
echo "Keys larger than 2048 have been tested and work, but are omitted from automated tests to save time." echo "Keys larger than 2048 have been tested and work, but are omitted from automated tests to save time."
rm fixtures/*.1.* rm fixtures/*.1.*
echo "" echo ""