浏览代码

v1.2.11: convert ECDSA ASN.1 signature to ECDSA JWT type

tags/v1.2.12
AJ ONeal 6 个月前
父节点
当前提交
65db78a3c5
共有 3 个文件被更改,包括 42 次插入4 次删除
  1. 40
    3
      keypairs.js
  2. 1
    1
      package.json
  3. 1
    0
      test.js

+ 40
- 3
keypairs.js 查看文件

@@ -229,13 +229,21 @@ Keypairs.signJws = function (opts) {
229 229
       }
230 230
 
231 231
       // node specifies RSA-SHAxxx even whet it's actually ecdsa (it's all encoded x509 shasums anyway)
232
-      var nodeAlg = "RSA-SHA" + (((protect||header).alg||'').replace(/^[^\d]+/, '')||'256');
232
+      var nodeAlg = "SHA" + (((protect||header).alg||'').replace(/^[^\d]+/, '')||'256');
233 233
       var protected64 = Enc.strToUrlBase64(protectedHeader);
234 234
       var payload64 = Enc.bufToUrlBase64(payload);
235
-      var sig = require('crypto')
235
+      var binsig = require('crypto')
236 236
         .createSign(nodeAlg)
237 237
         .update(protect ? (protected64 + "." + payload64) : payload64)
238
-        .sign(pem, 'base64')
238
+        .sign(pem)
239
+      ;
240
+      if (!opts.jwk || 'RSA' !== opts.jwk.kty) {
241
+        // ECDSA JWT signatures differ from "normal" ECDSA signatures
242
+        // https://tools.ietf.org/html/rfc7518#section-3.4
243
+        binsig = convertIfEcdsa(binsig);
244
+      }
245
+
246
+      var sig = binsig.toString('base64')
239 247
         .replace(/\+/g, '-')
240 248
         .replace(/\//g, '_')
241 249
         .replace(/=/g, '')
@@ -249,6 +257,35 @@ Keypairs.signJws = function (opts) {
249 257
       };
250 258
     }
251 259
 
260
+    function convertIfEcdsa(binsig) {
261
+      // should have asn1 sequence header of 0x30
262
+      if (0x30 !== binsig[0]) { return binsig; }
263
+      var index = 2; // first ecdsa "R" header byte
264
+      var len = binsig[1];
265
+      var lenlen = 0;
266
+      // Seek length of length if length is greater than 127 (i.e. two 512-bit / 64-byte R and S values)
267
+      if (0x80 & len) {
268
+        lenlen = len - 0x80;
269
+        // the length of the signature won't be over 256 bytes (2048 bits) for many years yet
270
+        if (1 !== lenlen) { return binsig; }
271
+        // the length is this number
272
+        len = binsig[2];
273
+        index += lenlen;
274
+      }
275
+      // should have bigint header of 0x02 followd by a single byte of length
276
+      if (0x02 !== binsig[index]) { return binsig; }
277
+      index += 1;
278
+      var rlen = binsig[index];
279
+      var r = binsig.slice(index + 1, index + 1 + rlen);
280
+      var slen = binsig[index + 1 + rlen + 1]; // skip header and read length
281
+      var s = binsig.slice(index + 1 + rlen + 1 + 1);
282
+      if (slen !== s.byteLength) { return binsig; }
283
+      // There may be one byte of padding on either
284
+      if (33 === r.byteLength) { r = r.slice(1); }
285
+      if (33 === s.byteLength) { s = s.slice(1); }
286
+      return Buffer.concat([r, s]);
287
+    }
288
+
252 289
     if (opts.pem && opts.jwk) {
253 290
       return sign(opts.pem);
254 291
     } else {

+ 1
- 1
package.json 查看文件

@@ -1,6 +1,6 @@
1 1
 {
2 2
   "name": "keypairs",
3
-  "version": "1.2.9",
3
+  "version": "1.2.11",
4 4
   "description": "Lightweight RSA/ECDSA keypair generation and JWK <-> PEM",
5 5
   "main": "keypairs.js",
6 6
   "files": [

+ 1
- 0
test.js 查看文件

@@ -1,6 +1,7 @@
1 1
 var Keypairs = require('./');
2 2
 
3 3
 /* global Promise*/
4
+console.info("This SHOULD result in an error message:");
4 5
 Keypairs.parseOrGenerate({ key: '' }).then(function (pair) {
5 6
   // should NOT have any warning output
6 7
   if (!pair.private || !pair.public) {

正在加载...
取消
保存