Browse Source

v1.2.0: add jwk thumbprinting

AJ ONeal 1 week ago
parent
commit
e088eedc8f
5 changed files with 54 additions and 2 deletions
  1. 9
    0
      README.md
  2. 13
    0
      bin/rasha.js
  3. 24
    0
      lib/rasha.js
  4. 1
    1
      package.json
  5. 7
    1
      test.sh

+ 9
- 0
README.md View File

@@ -14,6 +14,7 @@ RSA tools. Lightweight. Zero Dependencies. Universal compatibility.
14 14
 * [x] Fast and Easy RSA Key Generation
15 15
 * [x] PEM-to-JWK
16 16
 * [x] JWK-to-PEM
17
+* [x] JWK thumbprint
17 18
 * [x] SSH "pub" format
18 19
 * [ ] ECDSA
19 20
   * **Need EC or ECDSA tools?** Check out [Eckles.js](https://git.coolaj86.com/coolaj86/eckles.js)
@@ -174,6 +175,14 @@ Qi49OykUCfNZeQlEz7UNNj9RGps/50+CNwIDAQAB
174 175
 -----END PUBLIC KEY-----
175 176
 ```
176 177
 
178
+## JWK Thumbprint
179
+
180
+```js
181
+Rasha.thumbprint({ jwk: jwk }).then(function (thumbprint) {
182
+  console.log(thumbprint);
183
+});
184
+```
185
+
177 186
 Testing
178 187
 -------
179 188
 

+ 13
- 0
bin/rasha.js View File

@@ -46,7 +46,16 @@ try {
46 46
   // ignore
47 47
 }
48 48
 
49
+var thumbprint = ('thumbprint' === format);
50
+if (thumbprint) {
51
+  format = 'public';
52
+}
53
+
49 54
 if ('string' === typeof key) {
55
+  if (thumbprint) {
56
+    Rasha.thumbprint({ pem: key }).then(console.info);
57
+    return;
58
+  }
50 59
   if ('tpl' === format) {
51 60
     var block = PEM.parseBlock(key);
52 61
     var asn1 = ASN1.parse(block.der);
@@ -63,6 +72,10 @@ if ('string' === typeof key) {
63 72
     process.exit(1);
64 73
   });
65 74
 } else {
75
+  if (thumbprint) {
76
+    Rasha.thumbprint({ jwk: key }).then(console.info);
77
+    return;
78
+  }
66 79
   Rasha.export({ jwk: key, format: format }).then(function (pem) {
67 80
     if (sign) { signMessage(pem, msg); return; }
68 81
     console.info(pem);

+ 24
- 0
lib/rasha.js View File

@@ -5,6 +5,7 @@ var SSH = require('./ssh.js');
5 5
 var PEM = require('./pem.js');
6 6
 var x509 = require('./x509.js');
7 7
 var ASN1 = require('./asn1.js');
8
+var Enc = require('./encoding.js');
8 9
 
9 10
 /*global Promise*/
10 11
 RSA.generate = function (opts) {
@@ -202,3 +203,26 @@ RSA.nueter = function (jwk) {
202 203
   });
203 204
   return jwk;
204 205
 };
206
+
207
+RSA.__thumbprint = function (jwk) {
208
+  var buf = require('crypto').createHash('sha256')
209
+    // alphabetically sorted keys [ 'e', 'kty', 'n' ]
210
+    .update('{"e":"' + jwk.e + '","kty":"RSA","n":"' + jwk.n + '"}')
211
+    .digest()
212
+  ;
213
+  return Enc.bufToUrlBase64(buf);
214
+};
215
+
216
+RSA.thumbprint = function (opts) {
217
+  return Promise.resolve().then(function () {
218
+    var jwk;
219
+    if ('RSA' === opts.kty) {
220
+      jwk = opts;
221
+    } else if (opts.jwk) {
222
+      jwk = opts.jwk;
223
+    } else {
224
+      jwk = RSA.importSync(opts);
225
+    }
226
+    return RSA.__thumbprint(jwk);
227
+  });
228
+};

+ 1
- 1
package.json View File

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

+ 7
- 1
test.sh View File

@@ -149,7 +149,7 @@ rndkey 768
149 149
 rndkey 1024
150 150
 rndkey 2048 # first secure key size
151 151
 
152
-if [ "${RASHA_TEST_LARGE_KEYS}" == "true" ]; then 
152
+if [ "${RASHA_TEST_LARGE_KEYS}" == "true" ]; then
153 153
   rndkey 3072
154 154
   rndkey 4096 # largest reasonable key size
155 155
 else
@@ -165,6 +165,12 @@ echo "Pass"
165 165
 rm fixtures/*.1.*
166 166
 
167 167
 echo ""
168
+echo "Testing Thumbprints"
169
+node bin/rasha.js ./fixtures/privkey-rsa-2048.pkcs1.pem thumbprint
170
+node bin/rasha.js ./fixtures/pub-rsa-2048.jwk.json thumbprint
171
+echo "PASS"
172
+
173
+echo ""
168 174
 echo ""
169 175
 echo "PASSED:"
170 176
 echo "• All inputs produced valid outputs"