| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | [Eckles.js](https://git.coolaj86.com/coolaj86/eckles.js) | 
					
						
							| 
									
										
										
										
											2018-11-18 22:50:08 -07:00
										 |  |  | ========= | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 23:31:03 -07:00
										 |  |  | Sponsored by [Root](https://therootcompany.com). | 
					
						
							|  |  |  | Built for [ACME.js](https://git.coolaj86.com/coolaj86/acme.js) | 
					
						
							|  |  |  | and [Greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | | < 600 lines of code | 3kb gzipped | 10kb minified | 17kb with comments | | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 23:17:39 -07:00
										 |  |  | ECDSA (elliptic curve) tools. Lightweight. Zero Dependencies. Universal compatibility. | 
					
						
							| 
									
										
										
										
											2018-11-18 22:50:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | * [x] Fast and Easy EC Key Generation | 
					
						
							| 
									
										
										
										
											2018-11-19 22:28:17 -07:00
										 |  |  | * [x] PEM-to-JWK | 
					
						
							| 
									
										
										
										
											2018-11-19 23:17:39 -07:00
										 |  |  | * [x] JWK-to-PEM | 
					
						
							| 
									
										
										
										
											2018-11-20 23:55:17 -07:00
										 |  |  | * [x] SSH "pub" format | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | * [x] CLI | 
					
						
							| 
									
										
										
										
											2018-11-24 23:24:46 -07:00
										 |  |  |   * See [Eckles CLI](https://git.coolaj86.com/coolaj86/eckles-cli.js) | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | * [ ] RSA | 
					
						
							|  |  |  |   * **Need RSA tools?** Check out [Rasha.js](https://git.coolaj86.com/coolaj86/rasha.js) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Install
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For node.js: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm install --save eckles | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CLI: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm install -g eckles | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 23:24:46 -07:00
										 |  |  | See [Eckles CLI](https://git.coolaj86.com/coolaj86/eckles-cli.js) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | ## Generate EC (ECDSA/ECDH) Key
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Achieves the *fastest possible key generation* using node's native EC bindings to OpenSSL, | 
					
						
							|  |  |  | then converts to JWK for ease-of-use. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | Eckles.generate({ format: 'jwk' }).then(function (keypair) { | 
					
						
							|  |  |  |   console.log(keypair.private); | 
					
						
							|  |  |  |   console.log(keypair.public); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2018-11-18 22:50:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | **options** | 
					
						
							| 
									
										
										
										
											2018-11-19 23:31:03 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | * `format` defaults to `'jwk'` | 
					
						
							|  |  |  |   * `'sec1'` (traditional) | 
					
						
							|  |  |  |   * `'pkcs8'` | 
					
						
							|  |  |  |   * `'ssh'` | 
					
						
							|  |  |  | * `encoding` defaults to `'json'` | 
					
						
							|  |  |  |   * `'pem'` (type + DER.toString('base64')) | 
					
						
							|  |  |  |   * `'der'` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **advanced options** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * `namedCurve` defaults to `'P-256'` | 
					
						
							|  |  |  |   * `P-384` is also supported | 
					
						
							|  |  |  |   * larger keys have not been implemented | 
					
						
							|  |  |  |     * A) because they're a senseless waste | 
					
						
							|  |  |  |     * B) they have similar, but slightly different formats | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 23:17:39 -07:00
										 |  |  | ## PEM-to-JWK
 | 
					
						
							| 
									
										
										
										
											2018-11-19 22:28:17 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | * [x] SEC1/X9.62, PKCS#8, SPKI/PKIX | 
					
						
							|  |  |  | * [x] P-256 (prime256v1, secp256r1), P-384 (secp384r1) | 
					
						
							| 
									
										
										
										
											2018-11-20 23:55:17 -07:00
										 |  |  | * [x] SSH (RFC4716), (RFC 4716/SSH2) | 
					
						
							| 
									
										
										
										
											2018-11-18 22:50:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | var Eckles = require('eckles'); | 
					
						
							| 
									
										
										
										
											2018-11-19 23:31:03 -07:00
										 |  |  | var pem = require('fs') | 
					
						
							|  |  |  |   .readFileSync('./node_modles/eckles/fixtures/privkey-ec-p256.sec1.pem', 'ascii'); | 
					
						
							| 
									
										
										
										
											2018-11-19 08:53:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | Eckles.import({ pem: pem }).then(function (jwk) { | 
					
						
							| 
									
										
										
										
											2018-11-18 22:50:08 -07:00
										 |  |  |   console.log(jwk); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 22:28:17 -07:00
										 |  |  | ```js | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   "kty": "EC", | 
					
						
							|  |  |  |   "crv": "P-256", | 
					
						
							|  |  |  |   "d": "iYydo27aNGO9DBUWeGEPD8oNi1LZDqfxPmQlieLBjVQ", | 
					
						
							|  |  |  |   "x": "IT1SWLxsacPiE5Z16jkopAn8_-85rMjgyCokrnjDft4", | 
					
						
							|  |  |  |   "y": "mP2JwOAOdMmXuwpxbKng3KZz27mz-nKWIlXJ3rzSGMo" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 23:17:39 -07:00
										 |  |  | ## JWK-to-PEM
 | 
					
						
							| 
									
										
										
										
											2018-11-19 22:28:17 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 23:17:39 -07:00
										 |  |  | * [x] SEC1/X9.62, PKCS#8, SPKI/PKIX | 
					
						
							| 
									
										
										
										
											2018-11-19 22:28:17 -07:00
										 |  |  | * [x] P-256 (prime256v1, secp256r1), P-384 (secp384r1) | 
					
						
							| 
									
										
										
										
											2018-11-20 10:43:47 -07:00
										 |  |  | * [x] SSH (RFC4716), (RFC 4716/SSH2) | 
					
						
							| 
									
										
										
										
											2018-11-19 22:28:17 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-18 22:50:08 -07:00
										 |  |  | ```js | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | var Eckles = require('eckles'); | 
					
						
							| 
									
										
										
										
											2018-11-19 23:17:39 -07:00
										 |  |  | var jwk = require('eckles/fixtures/privkey-ec-p256.jwk.json'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | Eckles.export({ jwk: jwk }).then(function (pem) { | 
					
						
							| 
									
										
										
										
											2018-11-19 23:17:39 -07:00
										 |  |  |   // PEM in SEC1 (x9.62) format | 
					
						
							| 
									
										
										
										
											2018-11-18 22:50:08 -07:00
										 |  |  |   console.log(pem); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 22:28:17 -07:00
										 |  |  | ``` | 
					
						
							|  |  |  | -----BEGIN EC PRIVATE KEY----- | 
					
						
							|  |  |  | MHcCAQEEIImMnaNu2jRjvQwVFnhhDw/KDYtS2Q6n8T5kJYniwY1UoAoGCCqGSM49 | 
					
						
							|  |  |  | AwEHoUQDQgAEIT1SWLxsacPiE5Z16jkopAn8/+85rMjgyCokrnjDft6Y/YnA4A50 | 
					
						
							|  |  |  | yZe7CnFsqeDcpnPbubP6cpYiVcnevNIYyg== | 
					
						
							|  |  |  | -----END EC PRIVATE KEY----- | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 23:31:03 -07:00
										 |  |  | ### Advanced Options
 | 
					
						
							| 
									
										
										
										
											2018-11-19 23:17:39 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | `format: 'pkcs8'`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The default output format is `sec1`/`x9.62` (EC-specific format) is used for private keys. | 
					
						
							|  |  |  | Use `format: 'pkcs8'` to output in PKCS#8 format instead. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | Eckles.export({ jwk: jwk, format: 'pkcs8' }).then(function (pem) { | 
					
						
							| 
									
										
										
										
											2018-11-19 23:17:39 -07:00
										 |  |  |   // PEM in PKCS#8 format | 
					
						
							|  |  |  |   console.log(pem); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-20 12:07:50 -07:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2018-11-22 03:52:15 -07:00
										 |  |  | -----BEGIN PRIVATE KEY----- | 
					
						
							| 
									
										
										
										
											2018-11-20 12:07:50 -07:00
										 |  |  | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiYydo27aNGO9DBUW | 
					
						
							|  |  |  | eGEPD8oNi1LZDqfxPmQlieLBjVShRANCAAQhPVJYvGxpw+ITlnXqOSikCfz/7zms | 
					
						
							|  |  |  | yODIKiSueMN+3pj9icDgDnTJl7sKcWyp4Nymc9u5s/pyliJVyd680hjK | 
					
						
							| 
									
										
										
										
											2018-11-22 03:52:15 -07:00
										 |  |  | -----END PRIVATE KEY----- | 
					
						
							| 
									
										
										
										
											2018-11-20 12:07:50 -07:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-20 10:43:47 -07:00
										 |  |  | `format: 'ssh'`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Although SSH uses SEC1 for private keys, it uses ts own special non-ASN1 format | 
					
						
							|  |  |  | (affectionately known as rfc4716) for public keys. I got curious and then decided | 
					
						
							|  |  |  | to add this format as well. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To get the same format as you | 
					
						
							|  |  |  | would get with `ssh-keygen`, pass `ssh` as the format option: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | Eckles.export({ jwk: jwk, format: 'ssh' }).then(function (pub) { | 
					
						
							| 
									
										
										
										
											2018-11-20 10:43:47 -07:00
										 |  |  |   // Special SSH2 Public Key format (RFC 4716) | 
					
						
							|  |  |  |   console.log(pub); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-20 12:07:50 -07:00
										 |  |  | ``` | 
					
						
							|  |  |  | ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCE9Uli8bGnD4hOWdeo5KKQJ/P/vOazI4MgqJK54w37emP2JwOAOdMmXuwpxbKng3KZz27mz+nKWIlXJ3rzSGMo= P-256@localhost | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 23:17:39 -07:00
										 |  |  | `public: 'true'`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If a private key is used as input, a private key will be output. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If you'd like to output a public key instead you can pass `public: true` or `format: 'spki'`. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-18 22:50:08 -07:00
										 |  |  | ```js | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | Eckles.export({ jwk: jwk, public: true }).then(function (pem) { | 
					
						
							| 
									
										
										
										
											2018-11-19 23:17:39 -07:00
										 |  |  |   // PEM in SPKI/PKIX format | 
					
						
							| 
									
										
										
										
											2018-11-18 22:50:08 -07:00
										 |  |  |   console.log(pem); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-20 12:07:50 -07:00
										 |  |  | ``` | 
					
						
							|  |  |  | -----BEGIN PUBLIC KEY----- | 
					
						
							|  |  |  | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIT1SWLxsacPiE5Z16jkopAn8/+85 | 
					
						
							|  |  |  | rMjgyCokrnjDft6Y/YnA4A50yZe7CnFsqeDcpnPbubP6cpYiVcnevNIYyg== | 
					
						
							|  |  |  | -----END PUBLIC KEY----- | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 00:36:53 -07:00
										 |  |  | Testing | 
					
						
							|  |  |  | ------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | All cases are tested in `test.sh`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | You can compare these keys to the ones that you get from OpenSSL, ssh-keygen, and WebCrypto: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | # Generate EC P-256 Keypair
 | 
					
						
							|  |  |  | openssl ecparam -genkey -name prime256v1 -noout -out ./privkey-ec-p256.sec1.pem | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Export Public-only EC Key (as SPKI)
 | 
					
						
							|  |  |  | openssl ec -in ./privkey-ec-p256.sec1.pem -pubout -out ./pub-ec-p256.spki.pem | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Convert SEC1 (traditional) EC Keypair to PKCS8 format
 | 
					
						
							|  |  |  | openssl pkcs8 -topk8 -nocrypt -in ./privkey-ec-p256.sec1.pem -out ./privkey-ec-p256.pkcs8.pem | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Convert EC public key to SSH format
 | 
					
						
							|  |  |  | ssh-keygen -f ./pub-ec-p256.spki.pem -i -mPKCS8 > ./pub-ec-p256.ssh.pub | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 23:31:03 -07:00
										 |  |  | Goals of this project | 
					
						
							| 
									
										
										
										
											2018-11-18 22:50:08 -07:00
										 |  |  | ----- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-18 22:53:11 -07:00
										 |  |  | * Zero Dependencies | 
					
						
							| 
									
										
										
										
											2018-11-18 22:50:08 -07:00
										 |  |  | * Focused support for P-256 and P-384, which are already universally supported. | 
					
						
							|  |  |  | * Convert both ways | 
					
						
							| 
									
										
										
										
											2018-11-19 23:31:03 -07:00
										 |  |  | * Browser support as well (TODO) | 
					
						
							| 
									
										
										
										
											2018-11-21 00:36:53 -07:00
										 |  |  | * OpenSSL, ssh-keygen, and WebCrypto compatibility | 
					
						
							| 
									
										
										
										
											2018-11-19 23:31:03 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | Legal | 
					
						
							|  |  |  | ----- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 20:21:27 -07:00
										 |  |  | [Eckles.js](https://git.coolaj86.com/coolaj86/eckles.js) | | 
					
						
							|  |  |  | MPL-2.0 | | 
					
						
							| 
									
										
										
										
											2018-11-19 23:31:03 -07:00
										 |  |  | [Terms of Use](https://therootcompany.com/legal/#terms) | | 
					
						
							|  |  |  | [Privacy Policy](https://therootcompany.com/legal/#privacy) |