|  |  |  | (function() { | 
					
						
							|  |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function ProvisioningCipher() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ProvisioningCipher.prototype = { | 
					
						
							|  |  |  |     decrypt: function(provisionEnvelope) { | 
					
						
							|  |  |  |         var masterEphemeral = provisionEnvelope.publicKey.toArrayBuffer(); | 
					
						
							|  |  |  |         var message = provisionEnvelope.body.toArrayBuffer(); | 
					
						
							|  |  |  |         if (new Uint8Array(message)[0] != 1) { | 
					
						
							|  |  |  |             throw new Error("Bad version number on ProvisioningMessage"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var iv = message.slice(1, 16 + 1); | 
					
						
							|  |  |  |         var mac = message.slice(message.byteLength - 32, message.byteLength); | 
					
						
							|  |  |  |         var ivAndCiphertext = message.slice(0, message.byteLength - 32); | 
					
						
							|  |  |  |         var ciphertext = message.slice(16 + 1, message.byteLength - 32); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return libsignal.Curve.async.calculateAgreement( | 
					
						
							|  |  |  |             masterEphemeral, this.keyPair.privKey | 
					
						
							|  |  |  |         ).then(function(ecRes) { | 
					
						
							|  |  |  |             return libsignal.HKDF.deriveSecrets( | 
					
						
							|  |  |  |                 ecRes, new ArrayBuffer(32), "TextSecure Provisioning Message" | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         }).then(function(keys) { | 
					
						
							|  |  |  |             return libsignal.crypto.verifyMAC(ivAndCiphertext, keys[1], mac, 32).then(function() { | 
					
						
							|  |  |  |                 return libsignal.crypto.decrypt(keys[0], ciphertext, iv); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         }).then(function(plaintext) { | 
					
						
							|  |  |  |             var provisionMessage = textsecure.protobuf.ProvisionMessage.decode(plaintext); | 
					
						
							|  |  |  |             var privKey = provisionMessage.identityKeyPrivate.toArrayBuffer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return libsignal.Curve.async.createKeyPair(privKey).then(function(keyPair) { | 
					
						
							|  |  |  |                 return { | 
					
						
							|  |  |  |                     identityKeyPair  : keyPair, | 
					
						
							|  |  |  |                     number           : provisionMessage.number, | 
					
						
							|  |  |  |                     provisioningCode : provisionMessage.provisioningCode, | 
					
						
							|  |  |  |                     userAgent        : provisionMessage.userAgent | 
					
						
							|  |  |  |                 }; | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     getPublicKey: function() { | 
					
						
							|  |  |  |       return Promise.resolve().then(function() { | 
					
						
							|  |  |  |           if (!this.keyPair) { | 
					
						
							|  |  |  |               return libsignal.Curve.async.generateKeyPair().then(function(keyPair) { | 
					
						
							|  |  |  |                   this.keyPair = keyPair; | 
					
						
							|  |  |  |               }.bind(this)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |       }.bind(this)).then(function() { | 
					
						
							|  |  |  |           return this.keyPair.pubKey; | 
					
						
							|  |  |  |       }.bind(this)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | libsignal.ProvisioningCipher = function() { | 
					
						
							|  |  |  |     var cipher = new ProvisioningCipher(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     this.decrypt      = cipher.decrypt.bind(cipher); | 
					
						
							|  |  |  |     this.getPublicKey = cipher.getPublicKey.bind(cipher); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | })(); |