From fc0052e35aaa72f76ed0d5ff1c05365bffaf9117 Mon Sep 17 00:00:00 2001 From: Daniel Huigens Date: Fri, 31 Jan 2020 22:48:53 +0100 Subject: [PATCH] Implement streaming non-AES encryption and decryption --- src/crypto/cfb.js | 68 +++++++++++++++++++++------------------- src/packet/secret_key.js | 2 +- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/crypto/cfb.js b/src/crypto/cfb.js index 2b4269c6..902f6459 100644 --- a/src/crypto/cfb.js +++ b/src/crypto/cfb.js @@ -60,23 +60,26 @@ export default { const cipherfn = new cipher[algo](key); const block_size = cipherfn.blockSize; - let blocki = new Uint8Array(block_size); const blockc = iv.slice(); - let pos = 0; - const ciphertext = new Uint8Array(plaintext.length); - let i; - let j = 0; - - while (plaintext.length > block_size * pos) { - const encblock = cipherfn.encrypt(blockc); - blocki = plaintext.subarray((pos * block_size), (pos * block_size) + block_size); - for (i = 0; i < blocki.length; i++) { - blockc[i] = blocki[i] ^ encblock[i]; - ciphertext[j++] = blockc[i]; + let pt = new Uint8Array(); + const process = chunk => { + if (chunk) { + pt = util.concatUint8Array([pt, chunk]); } - pos++; - } - return ciphertext; + const ciphertext = new Uint8Array(pt.length); + let i; + let j = 0; + while (chunk ? pt.length >= block_size : pt.length) { + const encblock = cipherfn.encrypt(blockc); + for (i = 0; i < block_size; i++) { + blockc[i] = pt[i] ^ encblock[i]; + ciphertext[j++] = blockc[i]; + } + pt = pt.subarray(block_size); + } + return ciphertext.subarray(0, j); + }; + return stream.transform(plaintext, process, process); }, decrypt: async function(algo, key, ciphertext, iv) { @@ -87,28 +90,29 @@ export default { return aesDecrypt(algo, key, ciphertext, iv); } - ciphertext = await stream.readToEnd(ciphertext); - const cipherfn = new cipher[algo](key); const block_size = cipherfn.blockSize; let blockp = iv; - let pos = 0; - const plaintext = new Uint8Array(ciphertext.length); - const offset = 0; - let i; - let j = 0; - - while (ciphertext.length > (block_size * pos)) { - const decblock = cipherfn.encrypt(blockp); - blockp = ciphertext.subarray((pos * (block_size)) + offset, (pos * (block_size)) + (block_size) + offset); - for (i = 0; i < blockp.length; i++) { - plaintext[j++] = blockp[i] ^ decblock[i]; + let ct = new Uint8Array(); + const process = chunk => { + if (chunk) { + ct = util.concatUint8Array([ct, chunk]); } - pos++; - } - - return plaintext; + const plaintext = new Uint8Array(ct.length); + let i; + let j = 0; + while (chunk ? ct.length >= block_size : ct.length) { + const decblock = cipherfn.encrypt(blockp); + blockp = ct; + for (i = 0; i < block_size; i++) { + plaintext[j++] = blockp[i] ^ decblock[i]; + } + ct = ct.subarray(block_size); + } + return plaintext.subarray(0, j); + }; + return stream.transform(ciphertext, process, process); } }; diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index 785dc48a..899e485e 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -300,7 +300,7 @@ SecretKey.prototype.encrypt = async function (passphrase) { this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); } else { this.s2k_usage = 254; - this.keyMaterial = crypto.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ + this.keyMaterial = await crypto.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ cleartext, await crypto.hash.sha1(cleartext) ]), this.iv);