encrypt and decrypt images before upload and after download

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

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

@ -202,11 +202,17 @@
if (isGrant) {
// Send profile name to secondary device
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(
lokiProfile
);
const profileKey = window.storage.get('profileKey');
const dataMessage = new textsecure.protobuf.DataMessage({
profile,
profileKey,
});
// Attach contact list
const conversations = await window.Signal.Data.getConversationsWithFriendStatus(

@ -1127,12 +1127,13 @@ MessageReceiver.prototype.extend({
);
primaryConversation.trigger('change');
Whisper.events.trigger('secondaryDeviceRegistration');
// Update profile name
if (dataMessage && dataMessage.profile) {
// Update profile
if (dataMessage) {
const { profile, profileKey } = dataMessage;
const ourNumber = window.storage.get('primaryDevicePubKey');
const me = window.ConversationController.get(ourNumber);
if (me) {
me.setLokiProfile(dataMessage.profile);
this.updateProfile(me, profile, profileKey);
}
}
// Update contact list
@ -1238,7 +1239,7 @@ MessageReceiver.prototype.extend({
return true;
},
async updateProfile(conversation, profile) {
async updateProfile(conversation, profile, profileKey) {
// Retain old values unless changed:
const newProfile = conversation.get('profile') || {};
@ -1252,17 +1253,40 @@ MessageReceiver.prototype.extend({
if (needsUpdate) {
conversation.set('avatarPointer', profile.avatar);
conversation.set('profileKey', profileKey);
const downloaded = await this.downloadAttachment({
url: profile.avatar,
isRaw: true,
});
const upgraded = await Signal.Migrations.processNewAttachment(
downloaded
);
newProfile.avatar = upgraded.path;
// null => use jazzicon
let path = null;
if (profileKey) {
// 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);
@ -1361,7 +1385,11 @@ MessageReceiver.prototype.extend({
// Check if we need to update any profile names
if (!isMe && conversation) {
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(
attachment,
publicServer = null,
isRaw = false,
isAvatar = false
{ isRaw = false, isAvatar = false }
) {
if (typeof attachment !== 'object' || attachment == null) {
return Promise.resolve(undefined);
@ -211,13 +210,7 @@ MessageSender.prototype = {
const proto = new textsecure.protobuf.AttachmentPointer();
let attachmentData;
let server;
if (publicServer) {
server = publicServer;
} else {
({ server } = this);
}
const server = publicServer || this.server;
if (publicServer || isRaw) {
attachmentData = attachment.data;
@ -572,7 +565,12 @@ MessageSender.prototype = {
},
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) {

Loading…
Cancel
Save