From b6e988b6a6b18eb09c1c2a752d4eb2ea4c367b02 Mon Sep 17 00:00:00 2001 From: Daniel Huigens Date: Wed, 20 Jun 2018 14:22:58 +0200 Subject: [PATCH] Convert result.signatures to a Promise Also, throw armor checksum errors inside the data stream --- src/openpgp.js | 38 ++++++++++++++------------------------ src/packet/clone.js | 7 ++++--- test/general/streaming.js | 8 ++++---- 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/src/openpgp.js b/src/openpgp.js index e6bddc00..9ab457b0 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -369,11 +369,22 @@ export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKe result.signatures = signature ? await decrypted.verifyDetached(signature, publicKeys, date) : await decrypted.verify(publicKeys, date, asStream); result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); result.data = await convertStream(result.data, asStream); - result.signatures = await convertStreamArray(result.signatures, asStream); + result.signatures = stream.readToEnd(result.signatures, arr => arr); if (asStream) { result.data = stream.transformPair(message.packets.stream, async (readable, writable) => { - await stream.pipe(result.data, writable); + await stream.pipe(result.data, writable, { + preventClose: true + }); + const writer = stream.getWriter(writable); + try { + await result.signatures; + await writer.close(); + } catch(e) { + await writer.abort(e); + } }); + } else { + result.signatures = await result.signatures; } result.filename = decrypted.getFilename(); return result; @@ -461,7 +472,7 @@ export function verify({ message, publicKeys, asStream, signature=null, date=new result.signatures = signature ? await message.verifyDetached(signature, publicKeys, date) : await message.verify(publicKeys, date, asStream); result.data = message instanceof CleartextMessage ? message.getText() : message.getLiteralData(); result.data = await convertStream(result.data, asStream); - result.signatures = await convertStreamArray(result.signatures, asStream); + result.signatures = stream.readToEnd(result.signatures, arr => arr); return result; }).catch(onError.bind(null, 'Error verifying cleartext signed message')); } @@ -619,27 +630,6 @@ async function convertStream(data, asStream) { return data; } -/** - * Convert data array to or from Stream - * @param {Object} data the data to convert - * @param {Boolean} asStream whether to return a ReadableStream - * @returns {Object} the parse data in the respective format - */ -async function convertStreamArray(data, asStream) { - if (!asStream && util.isStream(data)) { - return stream.readToEnd(data, arr => arr); - } - if (asStream && !util.isStream(data)) { - return new ReadableStream({ - start(controller) { - data.forEach(controller.enqueue.bind(controller)); - controller.close(); - } - }); - } - return data; -} - /** * Global error handler that logs the stack trace and rethrows a high lvl error message. diff --git a/src/packet/clone.js b/src/packet/clone.js index eb9ba4a5..dad2136e 100644 --- a/src/packet/clone.js +++ b/src/packet/clone.js @@ -69,8 +69,9 @@ export function clonePackets(options) { options.signature = options.signature.packets; } if (options.signatures) { - if (util.isStream(options.signatures)) { - options.signatures = stream.transform(options.signatures, verificationObjectToClone); + if (options.signatures instanceof Promise) { + const signatures = options.signatures; + options.signatures = stream.fromAsync(async () => (await signatures).map(verificationObjectToClone)); } else { options.signatures.forEach(verificationObjectToClone); } @@ -116,7 +117,7 @@ export function parseClonedPackets(options) { } if (options.signatures) { if (util.isStream(options.signatures)) { - options.signatures = stream.transform(options.signatures, packetlistCloneToSignatures); + options.signatures = stream.readToEnd(options.signatures, arr => arr).then(signatures => signatures.map(packetlistCloneToSignatures)); } else { options.signatures = options.signatures.map(packetlistCloneToSignatures); } diff --git a/test/general/streaming.js b/test/general/streaming.js index ba73685e..7f2f9bfd 100644 --- a/test/general/streaming.js +++ b/test/general/streaming.js @@ -222,11 +222,11 @@ describe('Streaming', function() { format: 'binary' }); expect(util.isStream(decrypted.data)).to.be.true; - expect(util.isStream(decrypted.signatures)).to.be.true; + expect(util.isStream(decrypted.signatures)).to.be.false; expect(await openpgp.stream.getReader(openpgp.stream.clone(decrypted.data)).readBytes(1024)).to.deep.equal(plaintext[0]); if (i > 10) throw new Error('Data did not arrive early.'); expect(await openpgp.stream.readToEnd(decrypted.data)).to.deep.equal(util.concatUint8Array(plaintext)); - expect(await openpgp.stream.readToEnd(decrypted.signatures, arr => arr)).to.exist.and.have.length(0); + expect(await decrypted.signatures).to.exist.and.have.length(0); } finally { openpgp.config.unsafe_stream = unsafe_streamValue; } @@ -363,8 +363,8 @@ describe('Streaming', function() { expect(util.isStream(decrypted.data)).to.be.true; expect(await openpgp.stream.getReader(openpgp.stream.clone(decrypted.data)).readBytes(10)).not.to.deep.equal(plaintext[0]); if (i > 10) throw new Error('Data did not arrive early.'); - await openpgp.stream.readToEnd(decrypted.data); - expect(openpgp.stream.readToEnd(decrypted.signatures, arr => arr)).to.be.rejectedWith('Ascii armor integrity check on message failed'); + await expect(openpgp.stream.readToEnd(decrypted.data)).to.be.rejectedWith('Ascii armor integrity check on message failed'); + await expect(decrypted.signatures).to.be.rejectedWith('Ascii armor integrity check on message failed'); } finally { openpgp.config.unsafe_stream = unsafe_streamValue; }