Use security module
This commit is contained in:
parent
0c0ebb2ebb
commit
5592a8d376
|
@ -17,7 +17,6 @@ import { request } from 'vendor';
|
|||
import { Utils } from 'common';
|
||||
import E2EEComponent from './E2EEComponent.vue';
|
||||
import E2EEMessageButton from './E2EEMessageButton.vue';
|
||||
import aes256 from 'aes256';
|
||||
|
||||
const TEMP_KEY = 'temporarymasterkey';
|
||||
let seed;
|
||||
|
@ -31,7 +30,7 @@ export default new class E2EE extends BuiltinModule {
|
|||
|
||||
setMaster(key) {
|
||||
seed = Security.randomBytes();
|
||||
const newMaster = this.encrypt(seed, key);
|
||||
const newMaster = Security.encrypt(seed, key);
|
||||
// TODO re-encrypt everything with new master
|
||||
return (this.master = newMaster);
|
||||
}
|
||||
|
@ -45,17 +44,22 @@ export default new class E2EE extends BuiltinModule {
|
|||
}
|
||||
|
||||
encrypt(key, content, prefix = '') {
|
||||
if (!key) {
|
||||
// Encrypt something with master
|
||||
return Security.encrypt(Security.decrypt(seed, this.master), content);
|
||||
}
|
||||
|
||||
if (!content) {
|
||||
// Get key for current channel and encrypt
|
||||
const haveKey = this.getKey(DiscordApi.currentChannel.id);
|
||||
if (!haveKey) return 'nokey';
|
||||
return this.encrypt(this.decrypt(this.decrypt(seed, this.master), haveKey), key);
|
||||
return Security.encrypt(Security.decrypt(seed, [this.master, haveKey]), key);
|
||||
}
|
||||
return prefix + aes256.encrypt(key, content);
|
||||
return prefix + Security.encrypt(key, content);
|
||||
}
|
||||
|
||||
decrypt(key, content, prefix = '') {
|
||||
return aes256.decrypt(key, content.replace(prefix, ''));
|
||||
return Security.decrypt(key, content, prefix);
|
||||
}
|
||||
|
||||
async createHmac(data) {
|
||||
|
@ -71,9 +75,10 @@ export default new class E2EE extends BuiltinModule {
|
|||
}
|
||||
|
||||
async enabled(e) {
|
||||
window._sec = Security;
|
||||
seed = Security.randomBytes();
|
||||
// TODO Input modal for key
|
||||
this.master = this.encrypt(seed, TEMP_KEY);
|
||||
this.master = Security.encrypt(seed, TEMP_KEY);
|
||||
|
||||
this.patchMessageContent();
|
||||
const selector = '.' + WebpackModules.getClassName('channelTextArea', 'emojiButton');
|
||||
|
@ -106,7 +111,7 @@ export default new class E2EE extends BuiltinModule {
|
|||
if (!content.startsWith('$:')) return; // Not an encrypted string
|
||||
let decrypt;
|
||||
try {
|
||||
decrypt = this.decrypt(this.decrypt(this.decrypt(seed, this.master), key), component.props.message.content);
|
||||
decrypt = Security.decrypt(seed, [this.master, key, component.props.message.content]);
|
||||
} catch (err) { return } // Ignore errors such as non empty
|
||||
|
||||
component.props.message.bd_encrypted = true;
|
||||
|
@ -121,7 +126,11 @@ export default new class E2EE extends BuiltinModule {
|
|||
|
||||
renderMessageContent(component, args, retVal) {
|
||||
if (!component.props.message.bd_encrypted) return;
|
||||
retVal.props.children[0].props.children.props.children.props.children.unshift(VueInjector.createReactElement(E2EEMessageButton));
|
||||
try {
|
||||
retVal.props.children[0].props.children.props.children.props.children.unshift(VueInjector.createReactElement(E2EEMessageButton));
|
||||
} catch (err) {
|
||||
Logger.err('E2EE', err.message);
|
||||
}
|
||||
}
|
||||
|
||||
beforeRenderImageWrapper(component, args, retVal) {
|
||||
|
@ -145,7 +154,7 @@ export default new class E2EE extends BuiltinModule {
|
|||
}
|
||||
Logger.info('E2EE', 'Returning encrypted image from cache');
|
||||
try {
|
||||
const decrypt = this.decrypt(this.decrypt(this.decrypt(seed, this.master), haveKey), cached.image);
|
||||
const decrypt = Security.decrypt(seed, [this.master, haveKey, cached.image]);
|
||||
component.props.className = 'bd-decryptedImage';
|
||||
component.props.src = component.props.original = 'data:;base64,' + decrypt;
|
||||
} catch (err) { return } finally { component.props.readyState = 'READY' }
|
||||
|
@ -207,7 +216,7 @@ export default new class E2EE extends BuiltinModule {
|
|||
handleChannelTextAreaSubmit(component, args, retVal) {
|
||||
const key = this.getKey(DiscordApi.currentChannel.id);
|
||||
if (!this.encryptNewMessages || !key) return;
|
||||
component.props.value = this.encrypt(this.decrypt(this.decrypt(seed, this.master), key), component.props.value, '$:');
|
||||
component.props.value = Security.encrypt(Security.decrypt(seed, [this.master, key]), component.props.value, '$:');
|
||||
}
|
||||
|
||||
async disabled(e) {
|
||||
|
|
|
@ -14,16 +14,20 @@ import aes256 from 'aes256';
|
|||
export default class Security {
|
||||
|
||||
static encrypt(key, content, prefix = '') {
|
||||
if (key instanceof Array) return this.deepEncrypt(key, content, prefix);
|
||||
if (key instanceof Array || content instanceof Array) return this.deepEncrypt(key, content, prefix);
|
||||
return `${prefix}${aes256.encrypt(key, content)}`;
|
||||
}
|
||||
|
||||
static decrypt(key, content, prefix = '') {
|
||||
if (key instanceof Array) return this.deepDecrypt(key, content, prefix);
|
||||
if (key instanceof Array || content instanceof Array) {
|
||||
console.log('deep decrypting');
|
||||
return this.deepDecrypt(key, content, prefix);
|
||||
}
|
||||
return aes256.decrypt(key, content.replace(prefix, ''));
|
||||
}
|
||||
|
||||
static deepEncrypt(keys, content, prefix = '') {
|
||||
if (content && content instanceof Array) return this.deepEncryptContent(keys, content, prefix);
|
||||
let encrypt = null;
|
||||
for (const key of keys) {
|
||||
if (encrypt === null) encrypt = this.encrypt(key, content, prefix);
|
||||
|
@ -32,7 +36,17 @@ export default class Security {
|
|||
return encrypt;
|
||||
}
|
||||
|
||||
static deepEncryptContent(key, contents, prefix = '') {
|
||||
let encrypt = null;
|
||||
for (const content of contents) {
|
||||
if (encrypt === null) encrypt = this.encrypt(key, content, prefix);
|
||||
else encrypt = this.encrypt(encrypt, content, prefix);
|
||||
}
|
||||
return encrypt;
|
||||
}
|
||||
|
||||
static deepDecrypt(keys, content, prefix = '') {
|
||||
if (content && content instanceof Array) return this.deepDecryptContent(keys, content, prefix);
|
||||
let decrypt = null;
|
||||
for (const key of keys.reverse()) {
|
||||
if (decrypt === null) decrypt = this.decrypt(key, content, prefix);
|
||||
|
@ -41,6 +55,15 @@ export default class Security {
|
|||
return decrypt;
|
||||
}
|
||||
|
||||
static deepDecryptContent(key, contents, prefix = '') {
|
||||
let decrypt = null;
|
||||
for (const content of contents) {
|
||||
if (decrypt === null) decrypt = this.decrypt(key, content, prefix);
|
||||
else decrypt = this.decrypt(decrypt, content, prefix);
|
||||
}
|
||||
return decrypt;
|
||||
}
|
||||
|
||||
static randomBytes(length = 64, to = 'hex') {
|
||||
return nodecrypto.randomBytes(length).toString(to);
|
||||
}
|
||||
|
|
|
@ -22,13 +22,12 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import aes256 from 'aes256';
|
||||
import { DiscordApi } from 'modules';
|
||||
import { E2EE } from 'builtin';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
masterKey: 'temporarymasterkey',
|
||||
valueChanged: false
|
||||
}
|
||||
},
|
||||
|
@ -42,7 +41,7 @@
|
|||
},
|
||||
valueBlur(e) {
|
||||
if (!this.valueChanged) return;
|
||||
const value = aes256.encrypt(this.masterKey, e.target.value);
|
||||
const value = E2EE.encrypt(null, e.target.value);
|
||||
this.setting.value = { key: this.setting.value.key, value }
|
||||
this.valueChanged = false;
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue