| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  | ;(function (exports) { | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |   'use strict'; | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |   var OAUTH3 = exports.OAUTH3 = exports.OAUTH3 || require('./oauth3.core.js').OAUTH3; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |   OAUTH3.crypto = {}; | 
					
						
							|  |  |  |   try { | 
					
						
							|  |  |  |     OAUTH3.crypto.core = require('./oauth3.node.crypto'); | 
					
						
							|  |  |  |   } catch (error) { | 
					
						
							|  |  |  |     OAUTH3.crypto.core = {}; | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |     OAUTH3.crypto.core.ready = false; | 
					
						
							|  |  |  |     var finishBeforeReady = []; | 
					
						
							|  |  |  |     var deferedCalls = []; | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // We don't currently have a fallback method for this function, so we assign
 | 
					
						
							|  |  |  |     // it directly to the core object instead of the webCrypto object.
 | 
					
						
							|  |  |  |     OAUTH3.crypto.core.randomBytes = function (size) { | 
					
						
							|  |  |  |       var buf = OAUTH3._browser.window.crypto.getRandomValues(new Uint8Array(size)); | 
					
						
							|  |  |  |       return OAUTH3.PromiseA.resolve(buf); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     var webCrypto = {}; | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     var deferCryptoCall = function(name) { | 
					
						
							|  |  |  |       return function() { | 
					
						
							|  |  |  |         var args = arguments; | 
					
						
							|  |  |  |         return new OAUTH3.PromiseA(function(resolve, reject) { | 
					
						
							|  |  |  |           deferedCalls.push(function(){ | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |               webCrypto[name].apply(webCrypto, args) | 
					
						
							|  |  |  |                 .then(function(result){ | 
					
						
							|  |  |  |                   resolve(result); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  |             } catch(e) { | 
					
						
							|  |  |  |               reject(e); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     OAUTH3.crypto.core.sha256 = deferCryptoCall("sha256"); | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     webCrypto.sha256 = function (buf) { | 
					
						
							|  |  |  |       return OAUTH3._browser.window.crypto.subtle.digest({name: 'SHA-256'}, buf); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |     OAUTH3.crypto.core.pbkdf2 = deferCryptoCall("pbkdf2"); | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     webCrypto.pbkdf2 = function (password, salt) { | 
					
						
							|  |  |  |       return OAUTH3._browser.window.crypto.subtle.importKey('raw', OAUTH3._binStr.binStrToBuffer(password), {name: 'PBKDF2'}, false, ['deriveKey']) | 
					
						
							|  |  |  |         .then(function (key) { | 
					
						
							|  |  |  |           var opts = {name: 'PBKDF2', salt: salt, iterations: 8192, hash: {name: 'SHA-256'}}; | 
					
						
							|  |  |  |           return OAUTH3._browser.window.crypto.subtle.deriveKey(opts, key, {name: 'AES-GCM', length: 128}, true, ['encrypt', 'decrypt']); | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         .then(function (key) { | 
					
						
							|  |  |  |           return OAUTH3._browser.window.crypto.subtle.exportKey('raw', key); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |     OAUTH3.crypto.core.encrypt = deferCryptoCall("encrypt"); | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     webCrypto.encrypt = function (rawKey, iv, data) { | 
					
						
							|  |  |  |       return OAUTH3._browser.window.crypto.subtle.importKey('raw', rawKey, {name: 'AES-GCM'}, false, ['encrypt']) | 
					
						
							|  |  |  |         .then(function (key) { | 
					
						
							|  |  |  |           return OAUTH3._browser.window.crypto.subtle.encrypt({name: 'AES-GCM', iv: iv}, key, data); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     OAUTH3.crypto.core.decrypt = deferCryptoCall("decrypt"); | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     webCrypto.decrypt = function (rawKey, iv, data) { | 
					
						
							|  |  |  |       return OAUTH3._browser.window.crypto.subtle.importKey('raw', rawKey, {name: 'AES-GCM'}, false, ['decrypt']) | 
					
						
							|  |  |  |         .then(function (key) { | 
					
						
							|  |  |  |           return OAUTH3._browser.window.crypto.subtle.decrypt({name: 'AES-GCM', iv: iv}, key, data); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |     OAUTH3.crypto.core.genEcdsaKeyPair = deferCryptoCall("genEcdsaKeyPair"); | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     webCrypto.genEcdsaKeyPair = function () { | 
					
						
							|  |  |  |       return OAUTH3._browser.window.crypto.subtle.generateKey({name: 'ECDSA', namedCurve: 'P-256'}, true, ['sign', 'verify']) | 
					
						
							|  |  |  |         .then(function (keyPair) { | 
					
						
							|  |  |  |           return OAUTH3.PromiseA.all([ | 
					
						
							|  |  |  |             OAUTH3._browser.window.crypto.subtle.exportKey('jwk', keyPair.privateKey) | 
					
						
							|  |  |  |           , OAUTH3._browser.window.crypto.subtle.exportKey('jwk', keyPair.publicKey) | 
					
						
							|  |  |  |           ]); | 
					
						
							|  |  |  |         }).then(function (jwkPair) { | 
					
						
							|  |  |  |           return { privateKey: jwkPair[0], publicKey:  jwkPair[1] }; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |     OAUTH3.crypto.core.sign = deferCryptoCall("sign"); | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     webCrypto.sign = function (jwk, msg) { | 
					
						
							|  |  |  |       return OAUTH3._browser.window.crypto.subtle.importKey('jwk', jwk, {name: 'ECDSA', namedCurve: jwk.crv}, false, ['sign']) | 
					
						
							|  |  |  |         .then(function (key) { | 
					
						
							|  |  |  |           return OAUTH3._browser.window.crypto.subtle.sign({name: 'ECDSA', hash: {name: 'SHA-256'}}, key, msg); | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         .then(function (sig) { | 
					
						
							|  |  |  |           return new Uint8Array(sig); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |      | 
					
						
							|  |  |  |     OAUTH3.crypto.core.verify = deferCryptoCall("verify"); | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     webCrypto.verify = function (jwk, msg, signature) { | 
					
						
							|  |  |  |       // If the JWK has properties that should only exist on the private key or is missing
 | 
					
						
							|  |  |  |       // "verify" in the key_ops, importing in as a public key won't work.
 | 
					
						
							|  |  |  |       if (jwk.hasOwnProperty('d') || jwk.hasOwnProperty('key_ops')) { | 
					
						
							|  |  |  |         jwk = JSON.parse(JSON.stringify(jwk)); | 
					
						
							|  |  |  |         delete jwk.d; | 
					
						
							|  |  |  |         delete jwk.key_ops; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return OAUTH3._browser.window.crypto.subtle.importKey('jwk', jwk, {name: 'ECDSA', namedCurve: jwk.crv}, false, ['verify']) | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |       .then(function (key) { | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |         return OAUTH3._browser.window.crypto.subtle.verify({name: 'ECDSA', hash: {name: 'SHA-256'}}, key, signature, msg); | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     function checkWebCrypto() { | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |       /* global OAUTH3_crypto_fallback */ | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |       var loadFallback = function() { | 
					
						
							|  |  |  |         var prom; | 
					
						
							|  |  |  |         loadFallback = function () { return prom; }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         prom = new OAUTH3.PromiseA(function (resolve) { | 
					
						
							|  |  |  |           var body = document.getElementsByTagName('body')[0]; | 
					
						
							|  |  |  |           var script = document.createElement('script'); | 
					
						
							|  |  |  |           script.type = 'text/javascript'; | 
					
						
							|  |  |  |           script.onload = resolve; | 
					
						
							|  |  |  |           script.onreadystatechange = function () { | 
					
						
							|  |  |  |             if (this.readyState === 'complete' || this.readyState === 'loaded') { | 
					
						
							|  |  |  |               resolve(); | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |           }; | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |           script.src = '/assets/oauth3.org/oauth3.crypto.fallback.js'; | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |           body.appendChild(script); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         return prom; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |       function checkException(name, func) { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |         return OAUTH3.PromiseA.resolve().then(func) | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |           .then(function () { | 
					
						
							|  |  |  |             OAUTH3.crypto.core[name] = webCrypto[name]; | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |           }, function (err) { | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |             console.warn('error with WebCrypto', name, '- using fallback', err); | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |             return loadFallback().then(function () { | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |               OAUTH3.crypto.core[name] = OAUTH3_crypto_fallback[name]; | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |       } | 
					
						
							|  |  |  |       function checkResult(name, expected, func) { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |          | 
					
						
							|  |  |  |         finishBeforeReady.push(checkException(name, function () { | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |           return func() | 
					
						
							|  |  |  |             .then(function (result) { | 
					
						
							|  |  |  |               if (typeof expected === typeof result) { | 
					
						
							|  |  |  |                 return result; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               return OAUTH3._base64.bufferToUrlSafe(result); | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |             .then(function (result) { | 
					
						
							|  |  |  |               if (result !== expected) { | 
					
						
							|  |  |  |                 throw new Error("result ("+result+") doesn't match expectation ("+expected+")"); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |         })); | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var zeroBuf = new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); | 
					
						
							|  |  |  |       var dataBuf = OAUTH3._base64.urlSafeToBuffer('1234567890abcdefghijklmn'); | 
					
						
							|  |  |  |       var keyBuf = OAUTH3._base64.urlSafeToBuffer('l_Aeoqk6ePjwjCYrlHrgrg'); | 
					
						
							|  |  |  |       var encBuf = OAUTH3._base64.urlSafeToBuffer('Ji_gEtcNElUONSR4Mf9S75davXjh_6-oQN9AgO5UF8rERw'); | 
					
						
							|  |  |  |       checkResult('sha256', 'BwMveUm2V1axuERvUoxM4dScgNl9yKhER9a6p80GXj4', function () { | 
					
						
							|  |  |  |         return webCrypto.sha256(dataBuf); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       checkResult('pbkdf2', OAUTH3._base64.bufferToUrlSafe(keyBuf), function () { | 
					
						
							|  |  |  |         return webCrypto.pbkdf2('password', zeroBuf); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       checkResult('encrypt', OAUTH3._base64.bufferToUrlSafe(encBuf), function () { | 
					
						
							|  |  |  |         return webCrypto.encrypt(keyBuf, zeroBuf.slice(0, 12), dataBuf); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       checkResult('decrypt', OAUTH3._base64.bufferToUrlSafe(dataBuf), function () { | 
					
						
							|  |  |  |         return webCrypto.decrypt(keyBuf, zeroBuf.slice(0, 12), encBuf); | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |       var jwk = { | 
					
						
							|  |  |  |         kty: "EC" | 
					
						
							|  |  |  |       , crv: "P-256" | 
					
						
							|  |  |  |       , d: "ChXx7ea5YtEltCufA8CVb0lQv3glcCfcSpEgdedgIP0" | 
					
						
							|  |  |  |       , x: "Akt5ZDbytcKS5UQMURvGb_UIMS4qFctDwrX8bX22ato" | 
					
						
							|  |  |  |       , y: "cV7nhpWNT1FeRIbdold4jLtgsEpZBFcNy3p2E5mqvto" | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |       var sig = OAUTH3._base64.urlSafeToBuffer('nc3F8qeP8OXpfqPD9tTcFQg0Wfp37RTAppLPIKE1ZupR_8Aba64hNExwd1dOk802OFQxaECPDZCkKe7WA9RXAg'); | 
					
						
							|  |  |  |       checkResult('verify', true, function() { | 
					
						
							|  |  |  |         return webCrypto.verify(jwk, dataBuf, sig); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       // The results of these functions are less predictable, so we can't check their return value.
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |       finishBeforeReady.push(checkException('genEcdsaKeyPair', function () { | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |         return webCrypto.genEcdsaKeyPair(); | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |       })); | 
					
						
							|  |  |  |       finishBeforeReady.push(checkException('sign', function () { | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |         return webCrypto.sign(jwk, dataBuf); | 
					
						
							| 
									
										
										
										
											2017-11-13 13:09:58 -08:00
										 |  |  |       })); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       OAUTH3.PromiseA.all(finishBeforeReady) | 
					
						
							|  |  |  |         .then(function(results) { | 
					
						
							|  |  |  |           OAUTH3.crypto.core.ready = true; | 
					
						
							|  |  |  |           deferedCalls.forEach(function(request) { | 
					
						
							|  |  |  |             request(); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     } | 
					
						
							|  |  |  |     checkWebCrypto(); | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-20 17:41:20 -06:00
										 |  |  |   OAUTH3.crypto.thumbprintJwk = function (jwk) { | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |     var keys; | 
					
						
							|  |  |  |     if (jwk.kty === 'EC') { | 
					
						
							|  |  |  |       keys = ['crv', 'x', 'y']; | 
					
						
							|  |  |  |     } else if (jwk.kty === 'RSA') { | 
					
						
							|  |  |  |       keys = ['e', 'n']; | 
					
						
							|  |  |  |     } else if (jwk.kty === 'oct') { | 
					
						
							|  |  |  |       keys = ['k']; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return OAUTH3.PromiseA.reject(new Error('invalid JWK key type ' + jwk.kty)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     keys.push('kty'); | 
					
						
							|  |  |  |     keys.sort(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var missing = keys.filter(function (name) { return !jwk.hasOwnProperty(name); }); | 
					
						
							|  |  |  |     if (missing.length > 0) { | 
					
						
							|  |  |  |       return OAUTH3.PromiseA.reject(new Error('JWK of type '+jwk.kty+' missing fields ' + missing)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-28 13:26:30 -06:00
										 |  |  |     // I'm not actually 100% sure this behavior is guaranteed, but when we use an array as the
 | 
					
						
							|  |  |  |     // replacer argument the keys are always in the order they appeared in the array.
 | 
					
						
							|  |  |  |     var jwkStr = JSON.stringify(jwk, keys); | 
					
						
							| 
									
										
										
										
											2017-03-20 17:41:20 -06:00
										 |  |  |     return OAUTH3.crypto.core.sha256(OAUTH3._binStr.binStrToBuffer(jwkStr)) | 
					
						
							|  |  |  |       .then(OAUTH3._base64.bufferToUrlSafe); | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |   OAUTH3.crypto.createKeyPair = function () { | 
					
						
							|  |  |  |     // TODO: maybe support other types of key pairs, not just ECDSA P-256
 | 
					
						
							|  |  |  |     return OAUTH3.crypto.core.genEcdsaKeyPair().then(function (keyPair) { | 
					
						
							| 
									
										
										
										
											2017-03-20 17:41:20 -06:00
										 |  |  |       return OAUTH3.crypto.thumbprintJwk(keyPair.publicKey).then(function (kid) { | 
					
						
							|  |  |  |         keyPair.privateKey.alg = keyPair.publicKey.alg = 'ES256'; | 
					
						
							|  |  |  |         keyPair.privateKey.kid = keyPair.publicKey.kid = kid; | 
					
						
							|  |  |  |         return keyPair; | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   OAUTH3.crypto.encryptKeyPair = function (keyPair, password) { | 
					
						
							|  |  |  |     var saltProm = OAUTH3.crypto.core.randomBytes(16); | 
					
						
							|  |  |  |     var kekProm = saltProm.then(function (salt) { | 
					
						
							|  |  |  |       return OAUTH3.crypto.core.pbkdf2(password, salt); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |     return OAUTH3.PromiseA.all([ | 
					
						
							|  |  |  |       kekProm | 
					
						
							|  |  |  |     , saltProm | 
					
						
							|  |  |  |     , OAUTH3.crypto.core.randomBytes(12) | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |   , ]).then(function (results) { | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |       var kek        = results[0]; | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |       var salt       = results[1]; | 
					
						
							|  |  |  |       var ecdsaIv    = results[2]; | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |       var privKeyBuf = OAUTH3._binStr.binStrToBuffer(JSON.stringify(keyPair.privateKey)); | 
					
						
							|  |  |  |       return OAUTH3.crypto.core.encrypt(kek, ecdsaIv, privKeyBuf).then(function (encrypted) { | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |         return { | 
					
						
							| 
									
										
										
										
											2017-03-21 17:16:40 -06:00
										 |  |  |           publicKey:  keyPair.publicKey | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |         , privateKey: OAUTH3._base64.bufferToUrlSafe(encrypted) | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |         , salt:       OAUTH3._base64.bufferToUrlSafe(salt) | 
					
						
							|  |  |  |         , ecdsaIv:    OAUTH3._base64.bufferToUrlSafe(ecdsaIv) | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |       , }; | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |   OAUTH3.crypto.decryptKeyPair = function (storedObj, password) { | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |     var salt   = OAUTH3._base64.urlSafeToBuffer(storedObj.salt); | 
					
						
							|  |  |  |     var encJwk = OAUTH3._base64.urlSafeToBuffer(storedObj.privateKey); | 
					
						
							|  |  |  |     var iv     = OAUTH3._base64.urlSafeToBuffer(storedObj.ecdsaIv); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |     return OAUTH3.crypto.core.pbkdf2(password, salt) | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |       .then(function (key) { | 
					
						
							| 
									
										
										
										
											2017-03-20 17:41:20 -06:00
										 |  |  |         return OAUTH3.crypto.core.decrypt(key, iv, encJwk); | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       .then(OAUTH3._binStr.bufferToBinStr) | 
					
						
							| 
									
										
										
										
											2017-11-09 15:25:19 -07:00
										 |  |  |       .then(JSON.parse) | 
					
						
							|  |  |  |       .then(function (privateKey) { | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |           privateKey: privateKey | 
					
						
							|  |  |  |         , publicKey:  storedObj.publicKey | 
					
						
							|  |  |  |       , }; | 
					
						
							| 
									
										
										
										
											2017-03-20 16:11:14 -06:00
										 |  |  |       }); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }('undefined' !== typeof exports ? exports : window)); |