Skip to content

Commit 3f9d701

Browse files
committed
refactor: updating encode/decode function to use native functions
1 parent 522ef6b commit 3f9d701

File tree

2 files changed

+25
-10
lines changed

2 files changed

+25
-10
lines changed

scripts/packages/encryption/renderer/encryption.js

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
const AES = require('crypto-js/aes.js');
2-
const CryptoJS = require('crypto-js/crypto-js.js');
31
const prompt = require('electron-prompt');
42
/**
53
* A class that handles `encryption-*` web events in the renderer process
@@ -45,10 +43,19 @@ class EncryptionService {
4543
}
4644

4745
async encodeAes(data, passphrase) {
48-
// Todo: this looks really dangerous to run file encryption in the main
49-
// thread (of the renderer process). Consider other options.
50-
const encrypted = AES.encrypt(data, passphrase);
51-
return encrypted.toString();
46+
// see https://gist.github.com/chrisveness/43bcda93af9f646d083fad678071b90a
47+
const pwUtf8 = new TextEncoder().encode(passphrase);
48+
const pwHash = await crypto.subtle.digest('SHA-256', pwUtf8);
49+
const iv = crypto.getRandomValues(new Uint8Array(12));
50+
const alg = { name: 'AES-GCM', iv: iv };
51+
const key = await crypto.subtle.importKey('raw', pwHash, alg, false, ['encrypt']);
52+
const ptUint8 = new TextEncoder().encode(data);
53+
const ctBuffer = await crypto.subtle.encrypt(alg, key, ptUint8);
54+
const ctArray = Array.from(new Uint8Array(ctBuffer));
55+
const ctStr = ctArray.map(byte => String.fromCharCode(byte)).join('');
56+
const ctBase64 = btoa(ctStr);
57+
const ivHex = Array.from(iv).map(b => ('00' + b.toString(16)).slice(-2)).join('');
58+
return ivHex+ctBase64;
5259
}
5360

5461
async decode(method, opts) {
@@ -58,7 +65,7 @@ class EncryptionService {
5865
}
5966
}
6067

61-
async decodeAes(data, passphrase) {
68+
async decodeAes(ciphertext, passphrase) {
6269
if (passphrase === undefined) {
6370
const win = require('electron').remote.getCurrentWindow();
6471
passphrase = await prompt({
@@ -70,8 +77,16 @@ class EncryptionService {
7077
}
7178
}
7279
try {
73-
const bytes = AES.decrypt(data, passphrase);
74-
return bytes.toString(CryptoJS.enc.Utf8);
80+
const pwUtf8 = new TextEncoder().encode(passphrase);
81+
const pwHash = await crypto.subtle.digest('SHA-256', pwUtf8);
82+
const iv = ciphertext.slice(0,24).match(/.{2}/g).map(byte => parseInt(byte, 16));
83+
const alg = { name: 'AES-GCM', iv: new Uint8Array(iv) };
84+
const key = await crypto.subtle.importKey('raw', pwHash, alg, false, ['decrypt']);
85+
const ctStr = atob(ciphertext.slice(24));
86+
const ctUint8 = new Uint8Array(ctStr.match(/[\s\S]/g).map(ch => ch.charCodeAt(0)));
87+
const plainBuffer = await crypto.subtle.decrypt(alg, key, ctUint8);
88+
const plaintext = new TextDecoder().decode(plainBuffer);
89+
return plaintext;
7590
} catch (_) {
7691
throw new Error('Invalid password.');
7792
}

scripts/packages/encryption/spec/encryption.renderer.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe('EncryptionService', function() {
3232

3333

3434
describe('Decrypting content', () => {
35-
const encoded = 'U2FsdGVkX19MRBu8liXK/sbNBOQWG1mewbjEBb8cTAw=';
35+
const encoded = '0f8edad5305cbd4012369ed0IbNBdWOJpsToD8EMUJi+B6XfefpULsPuBA==';
3636
let instance;
3737
before(() => {
3838
instance = new EncryptionService();

0 commit comments

Comments
 (0)