mirror of
				https://github.com/therootcompany/keyfetch.js.git
				synced 2024-11-16 17:29:02 +00:00 
			
		
		
		
	v1.1.6: bugfix verify and ecdsa keys
This commit is contained in:
		
							parent
							
								
									9e5ffd1fc9
								
							
						
					
					
						commit
						2c36227afd
					
				
							
								
								
									
										53
									
								
								keyfetch.js
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								keyfetch.js
									
									
									
									
									
								
							| @ -253,22 +253,65 @@ keyfetch.verify = function (opts) { | |||||||
|       fetcher = keyfetch.jwks; |       fetcher = keyfetch.jwks; | ||||||
|       fetchOne = keyfetch.jwk; |       fetchOne = keyfetch.jwk; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     function verify(jwk, payload) { |     function verify(jwk, payload) { | ||||||
|       var alg = 'RSA-SHA' + decoded.header.alg.replace(/[^\d]+/i, ''); |       var alg = 'SHA' + decoded.header.alg.replace(/[^\d]+/i, ''); | ||||||
|  |       var sig = convertIfEcdsa(decoded.header, decoded.signature); | ||||||
|       return require('crypto') |       return require('crypto') | ||||||
|         .createVerify(alg) |         .createVerify(alg) | ||||||
|         .update(jwt.split('.')[0] + '.' + payload) |         .update(jwt.split('.')[0] + '.' + payload) | ||||||
|         .verify(jwk.pem, decoded.signature, 'base64'); |         .verify(jwk.pem, sig, 'base64'); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     function convertIfEcdsa(header, b64sig) { | ||||||
|  |       // ECDSA JWT signatures differ from "normal" ECDSA signatures
 | ||||||
|  |       // https://tools.ietf.org/html/rfc7518#section-3.4
 | ||||||
|  |       if (!/^ES/i.test(header.alg)) { return b64sig; } | ||||||
|  | 
 | ||||||
|  |       var bufsig = Buffer.from(b64sig, 'base64'); | ||||||
|  |       var hlen = bufsig.byteLength / 2; // should be even
 | ||||||
|  |       var r = bufsig.slice(0, hlen); | ||||||
|  |       var s = bufsig.slice(hlen); | ||||||
|  |       // pad ambiguously non-negative BigInts
 | ||||||
|  |       if (0x80 & r[0]) { r = Buffer.concat([Buffer.from([0]), r]); } | ||||||
|  |       if (0x80 & s[0]) { s = Buffer.concat([Buffer.from([0]), s]); } | ||||||
|  | 
 | ||||||
|  |       var len = 2 + r.byteLength + 2 + s.byteLength; | ||||||
|  |       var head = [0x30]; | ||||||
|  |       // hard code 0x80 + 1 because it won't be longer than
 | ||||||
|  |       // two SHA512 plus two pad bytes (130 bytes <= 256)
 | ||||||
|  |       if (len >= 0x80) { head.push(0x81); } | ||||||
|  |       head.push(len); | ||||||
|  | 
 | ||||||
|  |       var buf = Buffer.concat([ | ||||||
|  |         Buffer.from(head) | ||||||
|  |       , Buffer.from([0x02, r.byteLength]), r | ||||||
|  |       , Buffer.from([0x02, r.byteLength]), s | ||||||
|  |       ]); | ||||||
|  | 
 | ||||||
|  |       return buf.toString('base64') | ||||||
|  |         .replace(/-/g, '+') | ||||||
|  |         .replace(/_/g, '/') | ||||||
|  |         .replace(/=/g, '') | ||||||
|  |       ; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     var payload = jwt.split('.')[1]; // as string, as it was signed
 | ||||||
|     if (kid) { |     if (kid) { | ||||||
|       return fetchOne(kid, iss); //.catch(fetchAny);
 |       return fetchOne(kid, iss).then(verifyOne); //.catch(fetchAny);
 | ||||||
|     } else { |     } else { | ||||||
|       fetchAny(); |       return fetchAny(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     function verifyOne(jwk) { | ||||||
|  |       if (verify(jwk, payload)) { | ||||||
|  |         return decoded; | ||||||
|  |       } | ||||||
|  |       throw new Error('token signature verification was unsuccessful'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     function fetchAny() { |     function fetchAny() { | ||||||
|       return fetcher(iss).then(function (jwks) { |       return fetcher(iss).then(function (jwks) { | ||||||
|         var payload = jwt.split('.')[1]; // as string, as it was signed
 |  | ||||||
|         if (jwks.some(function (jwk) { |         if (jwks.some(function (jwk) { | ||||||
|           if (kid) { |           if (kid) { | ||||||
|             if (kid !== jwk.kid && kid !== jwk.thumbprint) { return; } |             if (kid !== jwk.kid && kid !== jwk.thumbprint) { return; } | ||||||
|  | |||||||
| @ -29,5 +29,5 @@ | |||||||
|   "scripts": { |   "scripts": { | ||||||
|     "test": "echo \"Error: no test specified\" && exit 1" |     "test": "echo \"Error: no test specified\" && exit 1" | ||||||
|   }, |   }, | ||||||
|   "version": "1.1.4" |   "version": "1.1.6" | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user