From ae190fed447b530a77e17e60ae80cf4d49da3c17 Mon Sep 17 00:00:00 2001 From: Lilia Date: Mon, 11 Sep 2017 18:50:35 +0200 Subject: [PATCH] Profiles (#1453) * Add AES-GCM encryption for profiles With tests. * Add profileKey to DataMessage protobuf // FREEBIE * Decrypt and save profile names // FREEBIE * Save incoming profile keys * Move pad/unpad to crypto module // FREEBIE * Support fetching avatars from the cdn // FREEBIE * Translate failed authentication errors When AES-GCM authentication fails, webcrypto returns a very generic error. The same error is thrown for invalid length inputs, but our earlier checks in decryptProfile should rule out those failure modes and leave us safe to assume that we either had bad ciphertext or the wrong key. // FREEBIE * Handle profile avatars (wip) and log decrypt errors // FREEBIE * Display profile avatars Synced contact avatars will still override profile avatars. * Display profile names in convo list Only if we don't have a synced contact name. // FREEBIE * Make cdn url an environment config Use different ones for staging and production // FREEBIE * Display profile name in conversation header * Display profile name in group messages * Update conversation header if profile avatar changes // FREEBIE * Style profile names small with ~ * Save profileKeys from contact sync messages // FREEBIE * Save profile keys from provisioning messages For standalone accounts, generate a random profile key. // FREEBIE * Special case for one-time sync of our profile key Android will use a contact sync message to sync a profile key from Android clients who have just upgraded and generated their profile key. Normally we should receive this data in a provisioning message. // FREEBIE * Infer profile sharing from synced data messages * Populate profile keys on outgoing messages Requires that `profileSharing` be set on the conversation. // FREEBIE * Support for the profile key update flag When receiving a message with this flag, don't init a message record, just process the profile key and move on. // FREEBIE * Display profile names in group member list * Refresh contact's profile on profile key changes // FREEBIE * Catch errors on profile save // FREEBIE * Save our own synced contact info Don't return early if we get a contact sync for our own number // FREEBIE --- background.html | 19 +++- config/default.json | 1 + config/production.json | 3 +- js/background.js | 28 +++++- js/libtextsecure.js | 127 +++++++++++++++++++++--- js/models/conversations.js | 95 +++++++++++++++++- js/models/messages.js | 13 +++ js/views/contact_list_view.js | 1 + js/views/conversation_list_item_view.js | 1 + js/views/conversation_view.js | 11 ++ js/views/message_view.js | 1 + libtextsecure/ProvisioningCipher.js | 3 +- libtextsecure/account_manager.js | 8 +- libtextsecure/api.js | 11 +- libtextsecure/contacts_parser.js | 4 + libtextsecure/crypto.js | 67 +++++++++++++ libtextsecure/message_receiver.js | 3 + libtextsecure/sendmessage.js | 31 ++++-- libtextsecure/test/crypto_test.js | 54 ++++++++++ libtextsecure/test/index.html | 1 + main.js | 1 + protos/DeviceMessages.proto | 1 + protos/IncomingPushMessageSignal.proto | 3 + stylesheets/_global.scss | 8 ++ stylesheets/manifest.css | 5 + 25 files changed, 464 insertions(+), 36 deletions(-) create mode 100644 libtextsecure/test/crypto_test.js diff --git a/background.html b/background.html index 78cc9fba339d..e7edcaff20ea 100644 --- a/background.html +++ b/background.html @@ -142,6 +142,9 @@ {{ #number }} {{ number }} {{ /number }} + {{ #profileName }} + {{ profileName }} + {{ /profileName }} {{ #isVerified }} {{ verified }} {{ /isVerified }} @@ -267,7 +270,12 @@ + diff --git a/main.js b/main.js index 3275f2b3e821..aba7284000f3 100644 --- a/main.js +++ b/main.js @@ -98,6 +98,7 @@ function createWindow () { version: app.getVersion(), buildExpiration: config.get('buildExpiration'), serverUrl: config.get('serverUrl'), + cdnUrl: config.get('cdnUrl'), certificateAuthorities: config.get('certificateAuthorities'), environment: config.environment, node_version: process.versions.node diff --git a/protos/DeviceMessages.proto b/protos/DeviceMessages.proto index 18721736beda..1322c159d3e8 100644 --- a/protos/DeviceMessages.proto +++ b/protos/DeviceMessages.proto @@ -15,4 +15,5 @@ message ProvisionMessage { optional string number = 3; optional string provisioningCode = 4; optional string userAgent = 5; + optional bytes profileKey = 6; } diff --git a/protos/IncomingPushMessageSignal.proto b/protos/IncomingPushMessageSignal.proto index 4c8d54d48a77..76070e062f7e 100644 --- a/protos/IncomingPushMessageSignal.proto +++ b/protos/IncomingPushMessageSignal.proto @@ -83,6 +83,7 @@ message DataMessage { enum Flags { END_SESSION = 1; EXPIRATION_TIMER_UPDATE = 2; + PROFILE_KEY_UPDATE = 4; } optional string body = 1; @@ -90,6 +91,7 @@ message DataMessage { optional GroupContext group = 3; optional uint32 flags = 4; optional uint32 expireTimer = 5; + optional bytes profileKey = 6; } message SyncMessage { @@ -180,6 +182,7 @@ message ContactDetails { optional Avatar avatar = 3; optional string color = 4; optional Verified verified = 5; + optional bytes profileKey = 6; } message GroupDetails { diff --git a/stylesheets/_global.scss b/stylesheets/_global.scss index d4ef13503192..2ffafda5be19 100644 --- a/stylesheets/_global.scss +++ b/stylesheets/_global.scss @@ -287,6 +287,14 @@ $avatar-size: 44px; } } } +.profileName { + font-size: smaller; + + &:before { + content: '~'; + } +} + .conversation-list-item { cursor: pointer; &:hover { diff --git a/stylesheets/manifest.css b/stylesheets/manifest.css index 9a7729ac5267..5e4cc24e19ac 100644 --- a/stylesheets/manifest.css +++ b/stylesheets/manifest.css @@ -296,6 +296,11 @@ button.hamburger { .new-group-update .members .contact .last-timestamp { display: none; } +.profileName { + font-size: smaller; } + .profileName:before { + content: '~'; } + .conversation-list-item { cursor: pointer; } .conversation-list-item:hover {