encrypt and decrypt images before upload and after download

pull/661/head
sachaaaaa 6 years ago
parent 25f0c3f700
commit 7c52a1d038

@ -933,7 +933,8 @@
avatarColor: conversation.getColor(), avatarColor: conversation.getColor(),
onOk: async (newName, avatar) => { onOk: async (newName, avatar) => {
let newAvatarPath = ''; let newAvatarPath = '';
let url = null;
let profileKey = null;
if (avatar) { if (avatar) {
const data = await readFile({ file: avatar }); const data = await readFile({ file: avatar });
@ -945,19 +946,30 @@
conversation.setLokiProfile({ displayName: newName }); conversation.setLokiProfile({ displayName: newName });
conversation.set('avatar', tempUrl); conversation.set('avatar', tempUrl);
const avatarPointer = await textsecure.messaging.uploadAvatar( // Encrypt with a new key every time
data profileKey = libsignal.crypto.getRandomBytes(32);
const encryptedData = await textsecure.crypto.encryptProfile(
data.data,
profileKey
); );
conversation.set('avatarPointer', avatarPointer.url); const avatarPointer = await textsecure.messaging.uploadAvatar({
...data,
data: encryptedData,
size: encryptedData.byteLength,
});
({ url } = avatarPointer);
const downloaded = await messageReceiver.downloadAttachment({ storage.put('profileKey', profileKey);
url: avatarPointer.url,
conversation.set('avatarPointer', url);
const upgraded = await Signal.Migrations.processNewAttachment({
isRaw: true, isRaw: true,
data: data.data,
url,
}); });
const upgraded = await Signal.Migrations.processNewAttachment(
downloaded
);
newAvatarPath = upgraded.path; newAvatarPath = upgraded.path;
} }

@ -202,11 +202,17 @@
if (isGrant) { if (isGrant) {
// Send profile name to secondary device // Send profile name to secondary device
const lokiProfile = ourConversation.getLokiProfile(); const lokiProfile = ourConversation.getLokiProfile();
// profile.avatar is the path to the local image
// replace with the avatar URL
const avatarPointer = ourConversation.get('avatarPointer');
lokiProfile.avatar = avatarPointer;
const profile = new textsecure.protobuf.DataMessage.LokiProfile( const profile = new textsecure.protobuf.DataMessage.LokiProfile(
lokiProfile lokiProfile
); );
const profileKey = window.storage.get('profileKey');
const dataMessage = new textsecure.protobuf.DataMessage({ const dataMessage = new textsecure.protobuf.DataMessage({
profile, profile,
profileKey,
}); });
// Attach contact list // Attach contact list
const conversations = await window.Signal.Data.getConversationsWithFriendStatus( const conversations = await window.Signal.Data.getConversationsWithFriendStatus(

@ -1127,12 +1127,13 @@ MessageReceiver.prototype.extend({
); );
primaryConversation.trigger('change'); primaryConversation.trigger('change');
Whisper.events.trigger('secondaryDeviceRegistration'); Whisper.events.trigger('secondaryDeviceRegistration');
// Update profile name // Update profile
if (dataMessage && dataMessage.profile) { if (dataMessage) {
const { profile, profileKey } = dataMessage;
const ourNumber = window.storage.get('primaryDevicePubKey'); const ourNumber = window.storage.get('primaryDevicePubKey');
const me = window.ConversationController.get(ourNumber); const me = window.ConversationController.get(ourNumber);
if (me) { if (me) {
me.setLokiProfile(dataMessage.profile); this.updateProfile(me, profile, profileKey);
} }
} }
// Update contact list // Update contact list
@ -1238,7 +1239,7 @@ MessageReceiver.prototype.extend({
return true; return true;
}, },
async updateProfile(conversation, profile) { async updateProfile(conversation, profile, profileKey) {
// Retain old values unless changed: // Retain old values unless changed:
const newProfile = conversation.get('profile') || {}; const newProfile = conversation.get('profile') || {};
@ -1252,17 +1253,40 @@ MessageReceiver.prototype.extend({
if (needsUpdate) { if (needsUpdate) {
conversation.set('avatarPointer', profile.avatar); conversation.set('avatarPointer', profile.avatar);
conversation.set('profileKey', profileKey);
const downloaded = await this.downloadAttachment({ const downloaded = await this.downloadAttachment({
url: profile.avatar, url: profile.avatar,
isRaw: true, isRaw: true,
}); });
const upgraded = await Signal.Migrations.processNewAttachment( // null => use jazzicon
downloaded let path = null;
); if (profileKey) {
newProfile.avatar = upgraded.path; // Convert profileKey to ArrayBuffer, if needed
const encoding = typeof profileKey === 'string' ? 'base64' : null;
try {
const profileKeyArrayBuffer = dcodeIO.ByteBuffer.wrap(
profileKey,
encoding
).toArrayBuffer();
const decryptedData = await textsecure.crypto.decryptProfile(
downloaded.data,
profileKeyArrayBuffer
);
const upgraded = await Signal.Migrations.processNewAttachment({
...downloaded,
data: decryptedData,
});
({ path } = upgraded);
} catch (e) {
window.log.error(`Could not decrypt profile image: ${e}`);
}
} }
newProfile.avatar = path;
}
} else {
newProfile.avatar = null;
} }
await conversation.setLokiProfile(newProfile); await conversation.setLokiProfile(newProfile);
@ -1361,7 +1385,11 @@ MessageReceiver.prototype.extend({
// Check if we need to update any profile names // Check if we need to update any profile names
if (!isMe && conversation) { if (!isMe && conversation) {
if (message.profile) { if (message.profile) {
await this.updateProfile(conversation, message.profile); await this.updateProfile(
conversation,
message.profile,
message.profileKey
);
} }
} }

@ -191,8 +191,7 @@ MessageSender.prototype = {
async makeAttachmentPointer( async makeAttachmentPointer(
attachment, attachment,
publicServer = null, publicServer = null,
isRaw = false, { isRaw = false, isAvatar = false }
isAvatar = false
) { ) {
if (typeof attachment !== 'object' || attachment == null) { if (typeof attachment !== 'object' || attachment == null) {
return Promise.resolve(undefined); return Promise.resolve(undefined);
@ -211,13 +210,7 @@ MessageSender.prototype = {
const proto = new textsecure.protobuf.AttachmentPointer(); const proto = new textsecure.protobuf.AttachmentPointer();
let attachmentData; let attachmentData;
let server; const server = publicServer || this.server;
if (publicServer) {
server = publicServer;
} else {
({ server } = this);
}
if (publicServer || isRaw) { if (publicServer || isRaw) {
attachmentData = attachment.data; attachmentData = attachment.data;
@ -572,7 +565,12 @@ MessageSender.prototype = {
}, },
uploadAvatar(attachment) { uploadAvatar(attachment) {
return this.makeAttachmentPointer(attachment, null, true, true); // isRaw is true since the data is already encrypted
// and doesn't need to be encrypted again
return this.makeAttachmentPointer(attachment, null, {
isRaw: true,
isAvatar: true,
});
}, },
sendRequestConfigurationSyncMessage(options) { sendRequestConfigurationSyncMessage(options) {

Loading…
Cancel
Save