Add attachment digests
// FREEBIE
This commit is contained in:
parent
f1a1a819ba
commit
43de0cc2ec
5 changed files with 65 additions and 10 deletions
|
@ -36695,6 +36695,23 @@ Internal.SessionLock.queueJobForNumber = function queueJobForNumber(number, runJ
|
||||||
var calculateMAC = libsignal.crypto.calculateMAC;
|
var calculateMAC = libsignal.crypto.calculateMAC;
|
||||||
var verifyMAC = libsignal.crypto.verifyMAC;
|
var verifyMAC = libsignal.crypto.verifyMAC;
|
||||||
|
|
||||||
|
function verifyDigest(data, theirDigest) {
|
||||||
|
return crypto.subtle.digest({name: 'SHA-256'}, data).then(function(ourDigest) {
|
||||||
|
var a = new Uint8Array(ourDigest);
|
||||||
|
var b = new Uint8Array(theirDigest);
|
||||||
|
var result = 0;
|
||||||
|
for (var i=0; i < theirDigest.byteLength; ++i) {
|
||||||
|
result = result | (a[i] ^ b[i]);
|
||||||
|
}
|
||||||
|
if (result !== 0) {
|
||||||
|
throw new Error('Bad digest');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function calculateDigest(data) {
|
||||||
|
return crypto.subtle.digest({name: 'SHA-256'}, data);
|
||||||
|
}
|
||||||
|
|
||||||
window.textsecure = window.textsecure || {};
|
window.textsecure = window.textsecure || {};
|
||||||
window.textsecure.crypto = {
|
window.textsecure.crypto = {
|
||||||
// Decrypts message into a raw string
|
// Decrypts message into a raw string
|
||||||
|
@ -36724,7 +36741,7 @@ Internal.SessionLock.queueJobForNumber = function queueJobForNumber(number, runJ
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
decryptAttachment: function(encryptedBin, keys) {
|
decryptAttachment: function(encryptedBin, keys, theirDigest) {
|
||||||
if (keys.byteLength != 64) {
|
if (keys.byteLength != 64) {
|
||||||
throw new Error("Got invalid length attachment keys");
|
throw new Error("Got invalid length attachment keys");
|
||||||
}
|
}
|
||||||
|
@ -36741,6 +36758,10 @@ Internal.SessionLock.queueJobForNumber = function queueJobForNumber(number, runJ
|
||||||
var mac = encryptedBin.slice(encryptedBin.byteLength - 32, encryptedBin.byteLength);
|
var mac = encryptedBin.slice(encryptedBin.byteLength - 32, encryptedBin.byteLength);
|
||||||
|
|
||||||
return verifyMAC(ivAndCiphertext, mac_key, mac, 32).then(function() {
|
return verifyMAC(ivAndCiphertext, mac_key, mac, 32).then(function() {
|
||||||
|
if (theirDigest !== undefined) {
|
||||||
|
return verifyDigest(encryptedBin, theirDigest);
|
||||||
|
}
|
||||||
|
}).then(function() {
|
||||||
return decrypt(aes_key, ciphertext, iv);
|
return decrypt(aes_key, ciphertext, iv);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -36764,7 +36785,9 @@ Internal.SessionLock.queueJobForNumber = function queueJobForNumber(number, runJ
|
||||||
var encryptedBin = new Uint8Array(16 + ciphertext.byteLength + 32);
|
var encryptedBin = new Uint8Array(16 + ciphertext.byteLength + 32);
|
||||||
encryptedBin.set(ivAndCiphertext);
|
encryptedBin.set(ivAndCiphertext);
|
||||||
encryptedBin.set(new Uint8Array(mac), 16 + ciphertext.byteLength);
|
encryptedBin.set(new Uint8Array(mac), 16 + ciphertext.byteLength);
|
||||||
return encryptedBin.buffer;
|
return calculateDigest(encryptedBin.buffer).then(function(digest) {
|
||||||
|
return { ciphertext: encryptedBin.buffer, digest: digest };
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -38539,10 +38562,12 @@ MessageReceiver.prototype.extend({
|
||||||
return textsecure.storage.get('blocked', []).indexOf(number) >= 0;
|
return textsecure.storage.get('blocked', []).indexOf(number) >= 0;
|
||||||
},
|
},
|
||||||
handleAttachment: function(attachment) {
|
handleAttachment: function(attachment) {
|
||||||
|
var digest = attachment.digest ? attachment.digest.toArrayBuffer() : undefined;
|
||||||
function decryptAttachment(encrypted) {
|
function decryptAttachment(encrypted) {
|
||||||
return textsecure.crypto.decryptAttachment(
|
return textsecure.crypto.decryptAttachment(
|
||||||
encrypted,
|
encrypted,
|
||||||
attachment.key.toArrayBuffer()
|
attachment.key.toArrayBuffer(),
|
||||||
|
digest
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39041,10 +39066,11 @@ MessageSender.prototype = {
|
||||||
proto.key = libsignal.crypto.getRandomBytes(64);
|
proto.key = libsignal.crypto.getRandomBytes(64);
|
||||||
|
|
||||||
var iv = libsignal.crypto.getRandomBytes(16);
|
var iv = libsignal.crypto.getRandomBytes(16);
|
||||||
return textsecure.crypto.encryptAttachment(attachment.data, proto.key, iv).then(function(encryptedBin) {
|
return textsecure.crypto.encryptAttachment(attachment.data, proto.key, iv).then(function(result) {
|
||||||
return this.server.putAttachment(encryptedBin).then(function(id) {
|
return this.server.putAttachment(result.ciphertext).then(function(id) {
|
||||||
proto.id = id;
|
proto.id = id;
|
||||||
proto.contentType = attachment.contentType;
|
proto.contentType = attachment.contentType;
|
||||||
|
proto.digest = result.digest;
|
||||||
return proto;
|
return proto;
|
||||||
});
|
});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
|
@ -10,6 +10,23 @@
|
||||||
var calculateMAC = libsignal.crypto.calculateMAC;
|
var calculateMAC = libsignal.crypto.calculateMAC;
|
||||||
var verifyMAC = libsignal.crypto.verifyMAC;
|
var verifyMAC = libsignal.crypto.verifyMAC;
|
||||||
|
|
||||||
|
function verifyDigest(data, theirDigest) {
|
||||||
|
return crypto.subtle.digest({name: 'SHA-256'}, data).then(function(ourDigest) {
|
||||||
|
var a = new Uint8Array(ourDigest);
|
||||||
|
var b = new Uint8Array(theirDigest);
|
||||||
|
var result = 0;
|
||||||
|
for (var i=0; i < theirDigest.byteLength; ++i) {
|
||||||
|
result = result | (a[i] ^ b[i]);
|
||||||
|
}
|
||||||
|
if (result !== 0) {
|
||||||
|
throw new Error('Bad digest');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function calculateDigest(data) {
|
||||||
|
return crypto.subtle.digest({name: 'SHA-256'}, data);
|
||||||
|
}
|
||||||
|
|
||||||
window.textsecure = window.textsecure || {};
|
window.textsecure = window.textsecure || {};
|
||||||
window.textsecure.crypto = {
|
window.textsecure.crypto = {
|
||||||
// Decrypts message into a raw string
|
// Decrypts message into a raw string
|
||||||
|
@ -39,7 +56,7 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
decryptAttachment: function(encryptedBin, keys) {
|
decryptAttachment: function(encryptedBin, keys, theirDigest) {
|
||||||
if (keys.byteLength != 64) {
|
if (keys.byteLength != 64) {
|
||||||
throw new Error("Got invalid length attachment keys");
|
throw new Error("Got invalid length attachment keys");
|
||||||
}
|
}
|
||||||
|
@ -56,6 +73,10 @@
|
||||||
var mac = encryptedBin.slice(encryptedBin.byteLength - 32, encryptedBin.byteLength);
|
var mac = encryptedBin.slice(encryptedBin.byteLength - 32, encryptedBin.byteLength);
|
||||||
|
|
||||||
return verifyMAC(ivAndCiphertext, mac_key, mac, 32).then(function() {
|
return verifyMAC(ivAndCiphertext, mac_key, mac, 32).then(function() {
|
||||||
|
if (theirDigest !== undefined) {
|
||||||
|
return verifyDigest(encryptedBin, theirDigest);
|
||||||
|
}
|
||||||
|
}).then(function() {
|
||||||
return decrypt(aes_key, ciphertext, iv);
|
return decrypt(aes_key, ciphertext, iv);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -79,7 +100,9 @@
|
||||||
var encryptedBin = new Uint8Array(16 + ciphertext.byteLength + 32);
|
var encryptedBin = new Uint8Array(16 + ciphertext.byteLength + 32);
|
||||||
encryptedBin.set(ivAndCiphertext);
|
encryptedBin.set(ivAndCiphertext);
|
||||||
encryptedBin.set(new Uint8Array(mac), 16 + ciphertext.byteLength);
|
encryptedBin.set(new Uint8Array(mac), 16 + ciphertext.byteLength);
|
||||||
return encryptedBin.buffer;
|
return calculateDigest(encryptedBin.buffer).then(function(digest) {
|
||||||
|
return { ciphertext: encryptedBin.buffer, digest: digest };
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -338,10 +338,12 @@ MessageReceiver.prototype.extend({
|
||||||
return textsecure.storage.get('blocked', []).indexOf(number) >= 0;
|
return textsecure.storage.get('blocked', []).indexOf(number) >= 0;
|
||||||
},
|
},
|
||||||
handleAttachment: function(attachment) {
|
handleAttachment: function(attachment) {
|
||||||
|
var digest = attachment.digest ? attachment.digest.toArrayBuffer() : undefined;
|
||||||
function decryptAttachment(encrypted) {
|
function decryptAttachment(encrypted) {
|
||||||
return textsecure.crypto.decryptAttachment(
|
return textsecure.crypto.decryptAttachment(
|
||||||
encrypted,
|
encrypted,
|
||||||
attachment.key.toArrayBuffer()
|
attachment.key.toArrayBuffer(),
|
||||||
|
digest
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,10 +119,11 @@ MessageSender.prototype = {
|
||||||
proto.key = libsignal.crypto.getRandomBytes(64);
|
proto.key = libsignal.crypto.getRandomBytes(64);
|
||||||
|
|
||||||
var iv = libsignal.crypto.getRandomBytes(16);
|
var iv = libsignal.crypto.getRandomBytes(16);
|
||||||
return textsecure.crypto.encryptAttachment(attachment.data, proto.key, iv).then(function(encryptedBin) {
|
return textsecure.crypto.encryptAttachment(attachment.data, proto.key, iv).then(function(result) {
|
||||||
return this.server.putAttachment(encryptedBin).then(function(id) {
|
return this.server.putAttachment(result.ciphertext).then(function(id) {
|
||||||
proto.id = id;
|
proto.id = id;
|
||||||
proto.contentType = attachment.contentType;
|
proto.contentType = attachment.contentType;
|
||||||
|
proto.digest = result.digest;
|
||||||
return proto;
|
return proto;
|
||||||
});
|
});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
|
@ -120,6 +120,9 @@ message AttachmentPointer {
|
||||||
optional fixed64 id = 1;
|
optional fixed64 id = 1;
|
||||||
optional string contentType = 2;
|
optional string contentType = 2;
|
||||||
optional bytes key = 3;
|
optional bytes key = 3;
|
||||||
|
optional uint32 size = 4;
|
||||||
|
optional bytes thumbnail = 5;
|
||||||
|
optional bytes digest = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GroupContext {
|
message GroupContext {
|
||||||
|
|
Loading…
Reference in a new issue