Fix armor errors
Also, fix error handling in transformPair()
This commit is contained in:
parent
304cbf4783
commit
55fd292fba
|
@ -212,57 +212,69 @@ function dearmor(input) {
|
||||||
let headersDone;
|
let headersDone;
|
||||||
let text = [];
|
let text = [];
|
||||||
let textDone;
|
let textDone;
|
||||||
|
let resolved = false;
|
||||||
let checksum;
|
let checksum;
|
||||||
let data = base64.decode(stream.transformPair(input, async (readable, writable) => {
|
let data = base64.decode(stream.transformPair(input, async (readable, writable) => {
|
||||||
const reader = stream.getReader(readable);
|
const reader = stream.getReader(readable);
|
||||||
const writer = stream.getWriter(writable);
|
const writer = stream.getWriter(writable);
|
||||||
while (true) {
|
while (true) {
|
||||||
await writer.ready;
|
if (resolved) await writer.ready;
|
||||||
let line = await reader.readLine();
|
try {
|
||||||
if (line === undefined) {
|
let line = await reader.readLine();
|
||||||
writer.abort('Misformed armored text');
|
if (line === undefined) {
|
||||||
break;
|
throw new Error('Misformed armored text');
|
||||||
}
|
|
||||||
// remove trailing whitespace at end of lines
|
|
||||||
// remove leading whitespace for compat with older versions of OpenPGP.js
|
|
||||||
line = line.trim();
|
|
||||||
if (!type) {
|
|
||||||
if (reSplit.test(line)) {
|
|
||||||
type = getType(line);
|
|
||||||
}
|
}
|
||||||
} else if (!headersDone) {
|
// remove trailing whitespace at end of lines
|
||||||
if (reSplit.test(line)) {
|
// remove leading whitespace for compat with older versions of OpenPGP.js
|
||||||
reject(new Error('Mandatory blank line missing between armor headers and armor data'));
|
line = line.trim();
|
||||||
}
|
if (!type) {
|
||||||
if (!reEmptyLine.test(line)) {
|
if (reSplit.test(line)) {
|
||||||
lastHeaders.push(line);
|
type = getType(line);
|
||||||
} else {
|
}
|
||||||
verifyHeaders(lastHeaders);
|
} else if (!headersDone) {
|
||||||
headersDone = true;
|
if (reSplit.test(line)) {
|
||||||
if (textDone || type !== 2) resolve({ text, data, headers, type });
|
reject(new Error('Mandatory blank line missing between armor headers and armor data'));
|
||||||
}
|
}
|
||||||
} else if (!textDone && type === 2) {
|
if (!reEmptyLine.test(line)) {
|
||||||
if (!reSplit.test(line)) {
|
lastHeaders.push(line);
|
||||||
// Reverse dash-escaping for msg
|
|
||||||
text.push(line.replace(/^- /, ''));
|
|
||||||
} else {
|
|
||||||
text = text.join('\r\n');
|
|
||||||
textDone = true;
|
|
||||||
verifyHeaders(lastHeaders);
|
|
||||||
lastHeaders = [];
|
|
||||||
headersDone = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!reSplit.test(line)) {
|
|
||||||
if (line[0] !== '=') {
|
|
||||||
writer.write(line);
|
|
||||||
} else {
|
} else {
|
||||||
checksum = line.substr(1);
|
verifyHeaders(lastHeaders);
|
||||||
|
headersDone = true;
|
||||||
|
if (textDone || type !== 2) {
|
||||||
|
resolve({ text, data, headers, type });
|
||||||
|
resolved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!textDone && type === 2) {
|
||||||
|
if (!reSplit.test(line)) {
|
||||||
|
// Reverse dash-escaping for msg
|
||||||
|
text.push(line.replace(/^- /, ''));
|
||||||
|
} else {
|
||||||
|
text = text.join('\r\n');
|
||||||
|
textDone = true;
|
||||||
|
verifyHeaders(lastHeaders);
|
||||||
|
lastHeaders = [];
|
||||||
|
headersDone = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writer.close();
|
if (!reSplit.test(line)) {
|
||||||
break;
|
if (line[0] !== '=') {
|
||||||
|
await writer.write(line);
|
||||||
|
} else {
|
||||||
|
checksum = line.substr(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await writer.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch(e) {
|
||||||
|
if (resolved) {
|
||||||
|
await writer.abort(e);
|
||||||
|
} else {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -275,10 +287,10 @@ function dearmor(input) {
|
||||||
const writer = stream.getWriter(writable);
|
const writer = stream.getWriter(writable);
|
||||||
await writer.ready;
|
await writer.ready;
|
||||||
if (checksum !== checksumVerifiedString && (checksum || config.checksum_required)) {
|
if (checksum !== checksumVerifiedString && (checksum || config.checksum_required)) {
|
||||||
writer.abort(new Error("Ascii armor integrity check on message failed: '" + checksum + "' should be '" +
|
await writer.abort(new Error("Ascii armor integrity check on message failed: '" + checksum + "' should be '" +
|
||||||
checksumVerifiedString + "'"));
|
checksumVerifiedString + "'"));
|
||||||
} else {
|
} else {
|
||||||
writer.close();
|
await writer.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
|
|
@ -38,31 +38,35 @@ function List() {
|
||||||
List.prototype.read = async function (bytes) {
|
List.prototype.read = async function (bytes) {
|
||||||
this.stream = stream.transformPair(bytes, async (readable, writable) => {
|
this.stream = stream.transformPair(bytes, async (readable, writable) => {
|
||||||
const writer = stream.getWriter(writable);
|
const writer = stream.getWriter(writable);
|
||||||
while (true) {
|
try {
|
||||||
await writer.ready;
|
while (true) {
|
||||||
const done = await packetParser.read(readable, async parsed => {
|
|
||||||
try {
|
|
||||||
const tag = enums.read(enums.packet, parsed.tag);
|
|
||||||
const packet = packets.newPacketFromTag(tag);
|
|
||||||
packet.packets = new List();
|
|
||||||
packet.fromStream = util.isStream(parsed.packet);
|
|
||||||
await packet.read(parsed.packet);
|
|
||||||
await writer.write(packet);
|
|
||||||
} catch (e) {
|
|
||||||
if (!config.tolerant ||
|
|
||||||
parsed.tag === enums.packet.symmetricallyEncrypted ||
|
|
||||||
parsed.tag === enums.packet.literal ||
|
|
||||||
parsed.tag === enums.packet.compressed) {
|
|
||||||
writer.abort(e);
|
|
||||||
}
|
|
||||||
util.print_debug_error(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (done) {
|
|
||||||
await writer.ready;
|
await writer.ready;
|
||||||
writer.close();
|
const done = await packetParser.read(readable, async parsed => {
|
||||||
return;
|
try {
|
||||||
|
const tag = enums.read(enums.packet, parsed.tag);
|
||||||
|
const packet = packets.newPacketFromTag(tag);
|
||||||
|
packet.packets = new List();
|
||||||
|
packet.fromStream = util.isStream(parsed.packet);
|
||||||
|
await packet.read(parsed.packet);
|
||||||
|
await writer.write(packet);
|
||||||
|
} catch (e) {
|
||||||
|
if (!config.tolerant ||
|
||||||
|
parsed.tag === enums.packet.symmetricallyEncrypted ||
|
||||||
|
parsed.tag === enums.packet.literal ||
|
||||||
|
parsed.tag === enums.packet.compressed) {
|
||||||
|
await writer.abort(e);
|
||||||
|
}
|
||||||
|
util.print_debug_error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (done) {
|
||||||
|
await writer.ready;
|
||||||
|
await writer.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch(e) {
|
||||||
|
await writer.abort(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -147,41 +147,45 @@ SymEncryptedAEADProtected.prototype.crypt = async function (fn, key, data) {
|
||||||
return stream.transformPair(data, async (readable, writable) => {
|
return stream.transformPair(data, async (readable, writable) => {
|
||||||
const reader = stream.getReader(readable);
|
const reader = stream.getReader(readable);
|
||||||
const writer = stream.getWriter(writable);
|
const writer = stream.getWriter(writable);
|
||||||
while (true) {
|
try {
|
||||||
await writer.ready;
|
while (true) {
|
||||||
let chunk = await reader.readBytes(chunkSize + tagLengthIfDecrypting) || new Uint8Array();
|
await writer.ready;
|
||||||
const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting);
|
let chunk = await reader.readBytes(chunkSize + tagLengthIfDecrypting) || new Uint8Array();
|
||||||
chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting);
|
const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting);
|
||||||
let cryptedPromise;
|
chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting);
|
||||||
let done;
|
let cryptedPromise;
|
||||||
if (!chunkIndex || chunk.length) {
|
let done;
|
||||||
reader.unshift(finalChunk);
|
if (!chunkIndex || chunk.length) {
|
||||||
cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray);
|
reader.unshift(finalChunk);
|
||||||
} else {
|
cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray);
|
||||||
// After the last chunk, we either encrypt a final, empty
|
} else {
|
||||||
// data chunk to get the final authentication tag or
|
// After the last chunk, we either encrypt a final, empty
|
||||||
// validate that final authentication tag.
|
// data chunk to get the final authentication tag or
|
||||||
adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...)
|
// validate that final authentication tag.
|
||||||
cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray);
|
adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...)
|
||||||
done = true;
|
cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray);
|
||||||
}
|
done = true;
|
||||||
cryptedBytes += chunk.length - tagLengthIfDecrypting;
|
}
|
||||||
queuedBytes += chunk.length - tagLengthIfDecrypting;
|
cryptedBytes += chunk.length - tagLengthIfDecrypting;
|
||||||
// eslint-disable-next-line no-loop-func
|
queuedBytes += chunk.length - tagLengthIfDecrypting;
|
||||||
latestPromise = latestPromise.then(() => cryptedPromise).then(crypted => {
|
// eslint-disable-next-line no-loop-func
|
||||||
writer.write(crypted);
|
latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => {
|
||||||
queuedBytes -= chunk.length;
|
await writer.write(crypted);
|
||||||
}).catch(err => writer.abort(err));
|
queuedBytes -= chunk.length;
|
||||||
// console.log(fn, done, queuedBytes, writer.desiredSize);
|
}).catch(err => writer.abort(err));
|
||||||
if (done || queuedBytes > writer.desiredSize) {
|
// console.log(fn, done, queuedBytes, writer.desiredSize);
|
||||||
await latestPromise; // Respect backpressure
|
if (done || queuedBytes > writer.desiredSize) {
|
||||||
}
|
await latestPromise; // Respect backpressure
|
||||||
if (!done) {
|
}
|
||||||
adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...)
|
if (!done) {
|
||||||
} else {
|
adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...)
|
||||||
writer.close();
|
} else {
|
||||||
break;
|
await writer.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch(e) {
|
||||||
|
await writer.abort(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -53,7 +53,7 @@ async function pipe(input, target, options) {
|
||||||
}
|
}
|
||||||
writer.releaseLock();
|
writer.releaseLock();
|
||||||
}
|
}
|
||||||
return input.pipeTo(target, options);
|
return input.pipeTo(target, options).catch(function() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
function transformRaw(input, options) {
|
function transformRaw(input, options) {
|
||||||
|
@ -125,22 +125,13 @@ function transformPair(input, fn) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const canceledErr = new Error('Readable side was canceled.');
|
const pipeDonePromise = pipe(input, incoming.writable);
|
||||||
const pipeDonePromise = pipe(input, incoming.writable).catch(e => {
|
|
||||||
if (e !== canceledErr) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const outgoing = transformWithCancel(async function() {
|
const outgoing = transformWithCancel(async function() {
|
||||||
incomingTransformController.error(canceledErr);
|
incomingTransformController.error(new Error('Readable side was canceled.'));
|
||||||
await pipeDonePromise;
|
await pipeDonePromise;
|
||||||
});
|
});
|
||||||
Promise.resolve(fn(incoming.readable, outgoing.writable)).catch(e => {
|
fn(incoming.readable, outgoing.writable);
|
||||||
if (e !== canceledErr) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return outgoing.readable;
|
return outgoing.readable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,16 +174,20 @@ function passiveClone(input) {
|
||||||
const transformed = transformPair(input, async (readable, writable) => {
|
const transformed = transformPair(input, async (readable, writable) => {
|
||||||
const reader = getReader(readable);
|
const reader = getReader(readable);
|
||||||
const writer = getWriter(writable);
|
const writer = getWriter(writable);
|
||||||
while (true) {
|
try {
|
||||||
await writer.ready;
|
while (true) {
|
||||||
const { done, value } = await reader.read();
|
await writer.ready;
|
||||||
if (done) {
|
const { done, value } = await reader.read();
|
||||||
try { controller.close(); } catch(e) {}
|
if (done) {
|
||||||
await writer.close();
|
try { controller.close(); } catch(e) {}
|
||||||
return;
|
await writer.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try { controller.enqueue(value); } catch(e) {}
|
||||||
|
await writer.write(value);
|
||||||
}
|
}
|
||||||
try { controller.enqueue(value); } catch(e) {}
|
} catch(e) {
|
||||||
await writer.write(value);
|
await writer.abort(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
overwrite(input, transformed);
|
overwrite(input, transformed);
|
||||||
|
|
|
@ -416,11 +416,7 @@ describe('Streaming', function() {
|
||||||
let plaintext = [];
|
let plaintext = [];
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let canceled = false;
|
let canceled = false;
|
||||||
let controller;
|
|
||||||
const data = new ReadableStream({
|
const data = new ReadableStream({
|
||||||
start(_controller) {
|
|
||||||
controller = _controller;
|
|
||||||
},
|
|
||||||
async pull(controller) {
|
async pull(controller) {
|
||||||
await new Promise(setTimeout);
|
await new Promise(setTimeout);
|
||||||
if (i++ < 10) {
|
if (i++ < 10) {
|
||||||
|
@ -435,16 +431,22 @@ describe('Streaming', function() {
|
||||||
canceled = true;
|
canceled = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
data.controller = controller;
|
|
||||||
|
|
||||||
const transformed = stream.transformPair(stream.slice(data, 0, 5000), async (readable, writable) => {
|
const transformed = stream.transformPair(stream.slice(data, 0, 5000), async (readable, writable) => {
|
||||||
const reader = stream.getReader(readable);
|
const reader = stream.getReader(readable);
|
||||||
const writer = stream.getWriter(writable);
|
const writer = stream.getWriter(writable);
|
||||||
while (true) {
|
try {
|
||||||
await writer.ready;
|
while (true) {
|
||||||
const { done, value } = await reader.read();
|
await writer.ready;
|
||||||
if (done) return writer.close();
|
const { done, value } = await reader.read();
|
||||||
writer.write(value);
|
if (done) {
|
||||||
|
await writer.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await writer.write(value);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
await writer.abort(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await new Promise(resolve => setTimeout(resolve));
|
await new Promise(resolve => setTimeout(resolve));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user