v1.2.11: convert ECDSA ASN.1 signature to ECDSA JWT type
This commit is contained in:
		
							parent
							
								
									e04557c84a
								
							
						
					
					
						commit
						65db78a3c5
					
				
							
								
								
									
										43
									
								
								keypairs.js
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								keypairs.js
									
									
									
									
									
								
							| @ -229,13 +229,21 @@ Keypairs.signJws = function (opts) { | ||||
|       } | ||||
| 
 | ||||
|       // node specifies RSA-SHAxxx even whet it's actually ecdsa (it's all encoded x509 shasums anyway)
 | ||||
|       var nodeAlg = "RSA-SHA" + (((protect||header).alg||'').replace(/^[^\d]+/, '')||'256'); | ||||
|       var nodeAlg = "SHA" + (((protect||header).alg||'').replace(/^[^\d]+/, '')||'256'); | ||||
|       var protected64 = Enc.strToUrlBase64(protectedHeader); | ||||
|       var payload64 = Enc.bufToUrlBase64(payload); | ||||
|       var sig = require('crypto') | ||||
|       var binsig = require('crypto') | ||||
|         .createSign(nodeAlg) | ||||
|         .update(protect ? (protected64 + "." + payload64) : payload64) | ||||
|         .sign(pem, 'base64') | ||||
|         .sign(pem) | ||||
|       ; | ||||
|       if (!opts.jwk || 'RSA' !== opts.jwk.kty) { | ||||
|         // ECDSA JWT signatures differ from "normal" ECDSA signatures
 | ||||
|         // https://tools.ietf.org/html/rfc7518#section-3.4
 | ||||
|         binsig = convertIfEcdsa(binsig); | ||||
|       } | ||||
| 
 | ||||
|       var sig = binsig.toString('base64') | ||||
|         .replace(/\+/g, '-') | ||||
|         .replace(/\//g, '_') | ||||
|         .replace(/=/g, '') | ||||
| @ -249,6 +257,35 @@ Keypairs.signJws = function (opts) { | ||||
|       }; | ||||
|     } | ||||
| 
 | ||||
|     function convertIfEcdsa(binsig) { | ||||
|       // should have asn1 sequence header of 0x30
 | ||||
|       if (0x30 !== binsig[0]) { return binsig; } | ||||
|       var index = 2; // first ecdsa "R" header byte
 | ||||
|       var len = binsig[1]; | ||||
|       var lenlen = 0; | ||||
|       // Seek length of length if length is greater than 127 (i.e. two 512-bit / 64-byte R and S values)
 | ||||
|       if (0x80 & len) { | ||||
|         lenlen = len - 0x80; | ||||
|         // the length of the signature won't be over 256 bytes (2048 bits) for many years yet
 | ||||
|         if (1 !== lenlen) { return binsig; } | ||||
|         // the length is this number
 | ||||
|         len = binsig[2]; | ||||
|         index += lenlen; | ||||
|       } | ||||
|       // should have bigint header of 0x02 followd by a single byte of length
 | ||||
|       if (0x02 !== binsig[index]) { return binsig; } | ||||
|       index += 1; | ||||
|       var rlen = binsig[index]; | ||||
|       var r = binsig.slice(index + 1, index + 1 + rlen); | ||||
|       var slen = binsig[index + 1 + rlen + 1]; // skip header and read length
 | ||||
|       var s = binsig.slice(index + 1 + rlen + 1 + 1); | ||||
|       if (slen !== s.byteLength) { return binsig; } | ||||
|       // There may be one byte of padding on either
 | ||||
|       if (33 === r.byteLength) { r = r.slice(1); } | ||||
|       if (33 === s.byteLength) { s = s.slice(1); } | ||||
|       return Buffer.concat([r, s]); | ||||
|     } | ||||
| 
 | ||||
|     if (opts.pem && opts.jwk) { | ||||
|       return sign(opts.pem); | ||||
|     } else { | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "keypairs", | ||||
|   "version": "1.2.9", | ||||
|   "version": "1.2.11", | ||||
|   "description": "Lightweight RSA/ECDSA keypair generation and JWK <-> PEM", | ||||
|   "main": "keypairs.js", | ||||
|   "files": [ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user