v1.2.12: fix EC sig padding issues
This commit is contained in:
		
							parent
							
								
									65db78a3c5
								
							
						
					
					
						commit
						3c84a7e1bd
					
				
							
								
								
									
										36
									
								
								keypairs.js
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								keypairs.js
									
									
									
									
									
								
							| @ -237,7 +237,7 @@ Keypairs.signJws = function (opts) { | |||||||
|         .update(protect ? (protected64 + "." + payload64) : payload64) |         .update(protect ? (protected64 + "." + payload64) : payload64) | ||||||
|         .sign(pem) |         .sign(pem) | ||||||
|       ; |       ; | ||||||
|       if (!opts.jwk || 'RSA' !== opts.jwk.kty) { |       if ('EC' === opts.jwk.kty) { | ||||||
|         // ECDSA JWT signatures differ from "normal" ECDSA signatures
 |         // ECDSA JWT signatures differ from "normal" ECDSA signatures
 | ||||||
|         // https://tools.ietf.org/html/rfc7518#section-3.4
 |         // https://tools.ietf.org/html/rfc7518#section-3.4
 | ||||||
|         binsig = convertIfEcdsa(binsig); |         binsig = convertIfEcdsa(binsig); | ||||||
| @ -259,31 +259,37 @@ Keypairs.signJws = function (opts) { | |||||||
| 
 | 
 | ||||||
|     function convertIfEcdsa(binsig) { |     function convertIfEcdsa(binsig) { | ||||||
|       // should have asn1 sequence header of 0x30
 |       // should have asn1 sequence header of 0x30
 | ||||||
|       if (0x30 !== binsig[0]) { return binsig; } |       if (0x30 !== binsig[0]) { throw new Error("Impossible EC SHA head marker"); } | ||||||
|       var index = 2; // first ecdsa "R" header byte
 |       var index = 2; // first ecdsa "R" header byte
 | ||||||
|       var len = binsig[1]; |       var len = binsig[1]; | ||||||
|       var lenlen = 0; |       var lenlen = 0; | ||||||
|       // Seek length of length if length is greater than 127 (i.e. two 512-bit / 64-byte R and S values)
 |       // Seek length of length if length is greater than 127 (i.e. two 512-bit / 64-byte R and S values)
 | ||||||
|       if (0x80 & len) { |       if (0x80 & len) { | ||||||
|         lenlen = len - 0x80; |         lenlen = len - 0x80; // should be exactly 1
 | ||||||
|         // the length of the signature won't be over 256 bytes (2048 bits) for many years yet
 |         len = binsig[2]; // should be <= 130 (two 64-bit SHA-512s, plus padding)
 | ||||||
|         if (1 !== lenlen) { return binsig; } |  | ||||||
|         // the length is this number
 |  | ||||||
|         len = binsig[2]; |  | ||||||
|         index += lenlen; |         index += lenlen; | ||||||
|       } |       } | ||||||
|       // should have bigint header of 0x02 followd by a single byte of length
 |       // should be of BigInt type
 | ||||||
|       if (0x02 !== binsig[index]) { return binsig; } |       if (0x02 !== binsig[index]) { throw new Error("Impossible EC SHA R marker"); } | ||||||
|       index += 1; |       index += 1; | ||||||
|  | 
 | ||||||
|       var rlen = binsig[index]; |       var rlen = binsig[index]; | ||||||
|       var r = binsig.slice(index + 1, index + 1 + rlen); |       var bits = 32; | ||||||
|  |       if (rlen > 49) { | ||||||
|  |         bits = 64; | ||||||
|  |       } else if (rlen > 33) { | ||||||
|  |         bits = 48; | ||||||
|  |       } | ||||||
|  |       var r = binsig.slice(index + 1, index + 1 + rlen).toString('hex'); | ||||||
|       var slen = binsig[index + 1 + rlen + 1]; // skip header and read length
 |       var slen = binsig[index + 1 + rlen + 1]; // skip header and read length
 | ||||||
|       var s = binsig.slice(index + 1 + rlen + 1 + 1); |       var s = binsig.slice(index + 1 + rlen + 1 + 1).toString('hex'); | ||||||
|       if (slen !== s.byteLength) { return binsig; } |       if (2 *slen !== s.length) { throw new Error("Impossible EC SHA S length"); } | ||||||
|       // There may be one byte of padding on either
 |       // There may be one byte of padding on either
 | ||||||
|       if (33 === r.byteLength) { r = r.slice(1); } |       while (r.length < 2*bits) { r = '00' + r; } | ||||||
|       if (33 === s.byteLength) { s = s.slice(1); } |       while (s.length < 2*bits) { s = '00' + s; } | ||||||
|       return Buffer.concat([r, s]); |       if (2*(bits+1) === r.length) { r = r.slice(2); } | ||||||
|  |       if (2*(bits+1) === s.length) { s = s.slice(2); } | ||||||
|  |       return Buffer.concat([Buffer.from(r, 'hex'), Buffer.from(s, 'hex')]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (opts.pem && opts.jwk) { |     if (opts.pem && opts.jwk) { | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "keypairs", |   "name": "keypairs", | ||||||
|   "version": "1.2.11", |   "version": "1.2.12", | ||||||
|   "description": "Lightweight RSA/ECDSA keypair generation and JWK <-> PEM", |   "description": "Lightweight RSA/ECDSA keypair generation and JWK <-> PEM", | ||||||
|   "main": "keypairs.js", |   "main": "keypairs.js", | ||||||
|   "files": [ |   "files": [ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user