generate RSA keys with node 10.12+
This commit is contained in:
parent
40bb9a0fdd
commit
6cd0c28b86
5 changed files with 131 additions and 9 deletions
38
README.md
38
README.md
|
@ -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
|
||||||
|
|
16
bin/rasha.js
16
bin/rasha.js
|
@ -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 {
|
||||||
|
|
71
lib/rasha.js
71
lib/rasha.js
|
@ -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");
|
||||||
|
|
|
@ -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
13
test.sh
|
@ -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 ""
|
||||||
|
|
Loading…
Reference in a new issue