Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New: Option to change E2E key #12169

Merged
merged 16 commits into from
Sep 26, 2018
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions packages/rocketchat-e2e/client/accountEncryption.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<template name="accountEncryption">
<section class="preferences-page preferences-page--new">
{{#header sectionName="Encryption" buttons=true fullpage=true}}
<div class="rc-header__section-button">
<button class="rc-button rc-button--primary" name="send" type="submit" data-button="create" form="encryption" {{canSave 'disabled'}}>{{_ "Save_changes"}}</button>
</div>
{{/header}}

<div class="preferences-page__content">
<form id="encryption" autocomplete="off" class="container">
{{# if isEnabled}}
<fieldset>
<div class="section">
<div class="section-content border-component-color">

<div class="rc-input{{#if confirmationKeyInvalid}} rc-input--error{{/if}} rc-w50 padded">
{{#with canChange=allowKeyChange}}
<label class="rc-input__label">
<div class="rc-input__title">{{_ "New_encryption_key"}}</div>
<div class="rc-input__wrapper">
<input name="encryptionKey" type="password" class="rc-input__element" placeholder="{{_ "New_Password_Placeholder"}}" autocomplete="new-password" {{ifThenElse canChange '' 'disabled'}}>
Hudell marked this conversation as resolved.
Show resolved Hide resolved
</div>
</label>
{{#if canConfirmNewKey}}
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Confirm_new_encryption_key"}}</div>
<div class="rc-input__wrapper">
<input name="confirmation-encryptionKey" type="password" class="rc-input__element" placeholder="{{_ "Confirm_New_Password_Placeholder"}}" autocomplete="confirm-new-password">
</div>
</label>
{{/if}}
{{# unless canChange}}
<div class="rc-input__description">{{_ 'EncryptionKey_Change_Disabled'}}</div>
{{/unless}}
{{/with}}
</div>
</div>
</div>
</fieldset>

{{else}}
{{_ "Admin_disabled_encryption"}}
{{/if}}
</form>
</div>
</section>
</template>
87 changes: 87 additions & 0 deletions packages/rocketchat-e2e/client/accountEncryption.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/* globals Template, t, ReactiveVar */
import toastr from 'toastr';
import s from 'underscore.string';
import qrcode from 'yaqrcode';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove this?

import { RocketChat } from 'meteor/rocketchat:lib';
import { e2e } from 'meteor/rocketchat:e2e';

window.qrcode = qrcode;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove this?


Template.accountEncryption.helpers({
isEnabled() {
return RocketChat.settings.get('E2E_Enable');
},
allowKeyChange() {
return localStorage.getItem('public_key') && localStorage.getItem('private_key');
},
canConfirmNewKey() {
const encryptionKey = Template.instance().encryptionKey.get();
return encryptionKey && encryptionKey !== '';
},
ifThenElse(condition, val, not = '') {
return condition ? val : not;
},
canSave(ret) {
const instance = Template.instance();

const encryptionKey = instance.encryptionKey.get();
const confirmationEncryptionKey = instance.confirmationEncryptionKey.get();

if ((!encryptionKey || encryptionKey !== confirmationEncryptionKey)) {
return ret;
}
},
});

Template.accountEncryption.events({
'input [name=encryptionKey]'(e, instance) {
instance.encryptionKey.set(e.target.value);

if (e.target.value.length === 0) {
instance.confirmationEncryptionKey.set('');
}
},
'input [name=confirmation-encryptionKey]'(e, instance) {
instance.confirmationEncryptionKey.set(e.target.value);
},
'submit form'(e, instance) {
e.preventDefault();

return instance.save();
},
});

Template.accountEncryption.onCreated(function() {
const self = this;

this.encryptionKey = new ReactiveVar;
this.confirmationEncryptionKey = new ReactiveVar;

this.save = function(cb) {
const instance = this;
const data = {};

if (s.trim(self.encryptionKey.get())) {
data.newEncryptionKey = self.encryptionKey.get();
}

if (Object.keys(data).length === 0) {
return cb && cb();
}

e2e.changePassword(data.newEncryptionKey);

instance.clearForm();
toastr.remove();
this.encryptionKey.set('');
this.confirmationEncryptionKey.set('');

toastr.success(t('Encryption_key_saved_successfully'));
};

this.clearForm = function() {
this.find('[name=encryptionKey]').value = '';
this.find('[name=confirmation-encryptionKey]').value = '';
};

});
20 changes: 17 additions & 3 deletions packages/rocketchat-e2e/client/rocketchat.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ class E2E {
if (!this.db_public_key || !this.db_private_key) {
await call('addKeyToChain', {
public_key: localStorage.getItem('public_key'),
private_key: await this.encodePrivateKey(localStorage.getItem('private_key')),
private_key: await this.encodePrivateKey(localStorage.getItem('private_key'), this.createRandomPassword()),
});
}

Expand Down Expand Up @@ -189,6 +189,17 @@ class E2E {
});
}

async changePassword(newPassword) {
await call('addKeyToChain', {
public_key: localStorage.getItem('public_key'),
private_key: await this.encodePrivateKey(localStorage.getItem('private_key'), newPassword),
});

if (localStorage.getItem('e2e.randomPassword')) {
localStorage.setItem('e2e.randomPassword', newPassword);
}
}

async loadKeysFromDB() {
try {
const { public_key, private_key } = await call('fetchMyKeys');
Expand Down Expand Up @@ -238,11 +249,14 @@ class E2E {
}
}

async encodePrivateKey(private_key) {
createRandomPassword() {
const randomPassword = `${ Random.id(3) }-${ Random.id(3) }-${ Random.id(3) }`.toLowerCase();
localStorage.setItem('e2e.randomPassword', randomPassword);
return randomPassword;
}

const masterKey = await this.getMasterKey(randomPassword);
async encodePrivateKey(private_key, password) {
const masterKey = await this.getMasterKey(password);

const vector = crypto.getRandomValues(new Uint8Array(16));
try {
Expand Down
13 changes: 10 additions & 3 deletions packages/rocketchat-e2e/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ Package.describe({
});

Package.onUse(function(api) {
api.use('ecmascript');
api.use('less');
api.use('mizzao:timesync');
api.use([
'ecmascript',
'less',
'mizzao:timesync',
'rocketchat:lib',
'templating',
'sha',
]);

api.mainModule('client/rocketchat.e2e.js', 'client');
api.addFiles('client/accountEncryption.html', 'client');
api.addFiles('client/accountEncryption.js', 'client');

api.mainModule('server/index.js', 'server');
});
5 changes: 5 additions & 0 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@
"Additional_Feedback": "Additional Feedback",
"additional_integrations_Bots": "If you are looking for how to integrate your own bot, then look no further than our Hubot adapter. <a href='https://github.com/RocketChat/hubot-rocketchat' target='_blank'>https://github.com/RocketChat/hubot-rocketchat</a>",
"additional_integrations_Zapier": "Are you looking to integrate other software and applications with Rocket.Chat but you don't have the time to manually do it? Then we suggest using Zapier which we fully support. Read more about it on our documentation. <a href='https://rocket.chat/docs/administrator-guides/integrations/zapier/using-zaps/' target='_blank'>https://rocket.chat/docs/administrator-guides/integrations/zapier/using-zaps/</a>",
"Admin_disabled_encryption": "Your administrator did not enable E2E encryption.",
"Admin_Info": "Admin Info",
"Administration": "Administration",
"Adult_images_are_not_allowed": "Adult images are not allowed",
Expand Down Expand Up @@ -572,6 +573,7 @@
"Compact": "Compact",
"Condensed": "Condensed",
"Computer": "Computer",
"Confirm_new_encryption_key": "Confirm new encryption key",
"Confirm_password": "Confirm your password",
"Connection_Closed": "Connection closed",
"Connection_Reset": "Connection reset",
Expand Down Expand Up @@ -1030,6 +1032,8 @@
"Encrypted": "Encrypted",
"Encrypted_channel_Description": "End to end encrypted channel. Search will not work with encrypted channels and notifications may not show the messages content.",
"Encrypted_message": "Encrypted message",
"EncryptionKey_Change_Disabled": "You can't change your encryption key because it was never used on this browser.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest:
You can't set a password for your encryption key because your private key is not present on this client. Please go to the client you have the encryption working and set the password there to be able to import it here.

"Encryption_key_saved_successfully": "Your encryption key was saved successfully.",
"End_OTR": "End OTR",
"Enter_a_name": "Enter a name",
"Enter_a_regex": "Enter a regex",
Expand Down Expand Up @@ -1886,6 +1890,7 @@
"New_Password_Placeholder": "Please enter new password...",
"Confirm_new_password": "Confirm New Password",
"Confirm_New_Password_Placeholder": "Please re-enter new password...",
"New_encryption_key": "New encryption key",
"New_role": "New role",
"New_Room_Notification": "New Room Notification",
"New_Trigger": "New Trigger",
Expand Down
2 changes: 2 additions & 0 deletions packages/rocketchat-ui-account/client/accountFlex.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ <h1 class="sidebar-flex__title">{{_ "My_Account"}}</h1>
{{/if}}

{{> sidebarItem menuItem "Security" "lock" "account" "security" }}

Hudell marked this conversation as resolved.
Show resolved Hide resolved
{{> sidebarItem menuItem "Encryption" "key" "account" "encryption" }}

{{#if accessTokensEnabled}}
{{> sidebarItem menuItem "Personal_Access_Tokens" "key" "account" "tokens" }}
Expand Down