From 7d30ca129d56b644804d5e5b2c3bb3dcaa8d2c8a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 6 Feb 2019 23:56:13 -0700 Subject: [PATCH] v1.4.0: add jwk thumbprinting --- README.md | 9 +++++++++ bin/eckles.js | 13 +++++++++++++ lib/eckles.js | 23 +++++++++++++++++++++++ package.json | 2 +- test.sh | 6 ++++++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b4b2ad..28ad2e6 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ ECDSA (elliptic curve) tools. Lightweight. Zero Dependencies. Universal compatib * [x] Fast and Easy EC Key Generation * [x] PEM-to-JWK * [x] JWK-to-PEM +* [x] JWK thumbprint * [x] SSH "pub" format * [x] CLI * See [Eckles CLI](https://git.coolaj86.com/coolaj86/eckles-cli.js) @@ -176,6 +177,14 @@ rMjgyCokrnjDft6Y/YnA4A50yZe7CnFsqeDcpnPbubP6cpYiVcnevNIYyg== -----END PUBLIC KEY----- ``` +## JWK Thumbprint + +```js +Eckles.thumbprint({ jwk: jwk }).then(function (thumbprint) { + console.log(thumbprint); +}); +``` + Testing ------- diff --git a/bin/eckles.js b/bin/eckles.js index 07b5658..7910f5c 100755 --- a/bin/eckles.js +++ b/bin/eckles.js @@ -39,7 +39,16 @@ try { // ignore } +var thumbprint = ('thumbprint' === format); +if (thumbprint) { + format = 'public'; +} + if ('string' === typeof key) { + if (thumbprint) { + Eckles.thumbprint({ pem: key }).then(console.log); + return; + } var pub = (-1 !== [ 'public', 'spki', 'pkix' ].indexOf(format)); Eckles.import({ pem: key, public: (pub || format) }).then(function (jwk) { console.log(JSON.stringify(jwk, null, 2)); @@ -48,6 +57,10 @@ if ('string' === typeof key) { process.exit(1); }); } else { + if (thumbprint) { + Eckles.thumbprint({ jwk: key }).then(console.log); + return; + } Eckles.export({ jwk: key, format: format }).then(function (pem) { console.log(pem); }).catch(function (err) { diff --git a/lib/eckles.js b/lib/eckles.js index 1b48219..29ec3a1 100644 --- a/lib/eckles.js +++ b/lib/eckles.js @@ -224,4 +224,27 @@ EC.pack = function (opts) { }); }; +EC.__thumbprint = function (jwk) { + var buf = require('crypto').createHash('sha256') + // alphabetically sorted keys [ 'crv', 'kty', 'x', 'y' ] + .update('{"crv":"' + jwk.crv + '","kty":"EC","x":"' + jwk.x + '","y":"' + jwk.y + '"}') + .digest() + ; + return Enc.bufToUrlBase64(buf); +}; + +EC.thumbprint = function (opts) { + return Promise.resolve().then(function () { + var jwk; + if ('EC' === opts.kty) { + jwk = opts; + } else if (opts.jwk) { + jwk = opts.jwk; + } else { + jwk = EC.importSync(opts); + } + return EC.__thumbprint(jwk); + }); +}; + EC.toPem = EC.export = EC.pack; diff --git a/package.json b/package.json index ada609e..0fec01b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eckles", - "version": "1.3.3", + "version": "1.4.0", "description": "💯 PEM-to-JWK and JWK-to-PEM (and SSH) for ECDSA keys in a lightweight, zero-dependency library focused on perfect universal compatibility.", "homepage": "https://git.coolaj86.com/coolaj86/eckles.js", "main": "index.js", diff --git a/test.sh b/test.sh index a72b887..e47363b 100644 --- a/test.sh +++ b/test.sh @@ -118,6 +118,12 @@ node bin/eckles.js pkcs8 > /dev/null node bin/eckles.js ssh #> /dev/null echo "PASS" +echo "" +echo "Testing Thumbprints" +node bin/eckles.js ./fixtures/privkey-ec-p256.sec1.pem thumbprint +node bin/eckles.js ./fixtures/pub-ec-p256.jwk.json thumbprint +echo "PASS" + rm *.2