You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			69 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			69 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
| (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) {
 | |
|                 var ret = {
 | |
|                     identityKeyPair  : keyPair,
 | |
|                     number           : provisionMessage.number,
 | |
|                     provisioningCode : provisionMessage.provisioningCode,
 | |
|                     userAgent        : provisionMessage.userAgent,
 | |
|                     readReceipts     : provisionMessage.readReceipts
 | |
|                 };
 | |
|                 if (provisionMessage.profileKey) {
 | |
|                   ret.profileKey = provisionMessage.profileKey.toArrayBuffer();
 | |
|                 }
 | |
|                 return ret;
 | |
|             });
 | |
|         });
 | |
|     },
 | |
|     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);
 | |
| };
 | |
| 
 | |
| })();
 |