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