Don't process armored message data line per line
This cuts down on the overhead of streaming by reducing the amount of calls to reader.read() and writer.write().
This commit is contained in:
parent
b004ddecb2
commit
dc722770d0
|
@ -192,6 +192,26 @@ function verifyHeaders(headers) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits a message into two parts, the body and the checksum. This is an internal function
|
||||||
|
* @param {String} text OpenPGP armored message part
|
||||||
|
* @returns {Object} An object with attribute "body" containing the body
|
||||||
|
* and an attribute "checksum" containing the checksum.
|
||||||
|
*/
|
||||||
|
function splitChecksum(text) {
|
||||||
|
let body = text;
|
||||||
|
let checksum = "";
|
||||||
|
|
||||||
|
const lastEquals = text.lastIndexOf("=");
|
||||||
|
|
||||||
|
if (lastEquals >= 0 && lastEquals !== text.length - 1) { // '=' as the last char means no checksum
|
||||||
|
body = text.slice(0, lastEquals);
|
||||||
|
checksum = text.slice(lastEquals + 1).substr(0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { body: body, checksum: checksum };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DeArmor an OpenPGP armored message; verify the checksum and return
|
* DeArmor an OpenPGP armored message; verify the checksum and return
|
||||||
* the encoded bytes
|
* the encoded bytes
|
||||||
|
@ -204,7 +224,7 @@ function verifyHeaders(headers) {
|
||||||
function dearmor(input) {
|
function dearmor(input) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const reSplit = /^-----[^-]+-----$/;
|
const reSplit = /^-----[^-]+-----$/m;
|
||||||
const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/;
|
const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/;
|
||||||
|
|
||||||
let type;
|
let type;
|
||||||
|
@ -213,21 +233,17 @@ 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);
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (resolved) await writer.ready;
|
let line = await reader.readLine();
|
||||||
try {
|
if (line === undefined) {
|
||||||
const lineUntrimmed = await reader.readLine();
|
|
||||||
if (lineUntrimmed === undefined) {
|
|
||||||
throw new Error('Misformed armored text');
|
throw new Error('Misformed armored text');
|
||||||
}
|
}
|
||||||
// remove trailing whitespace at end of lines
|
// remove trailing whitespace at end of lines
|
||||||
// remove leading whitespace for compat with older versions of OpenPGP.js
|
line = line.replace(/[\t\r\n ]+$/, '');
|
||||||
const line = lineUntrimmed.trim();
|
|
||||||
if (!type) {
|
if (!type) {
|
||||||
if (reSplit.test(line)) {
|
if (reSplit.test(line)) {
|
||||||
type = getType(line);
|
type = getType(line);
|
||||||
|
@ -243,13 +259,13 @@ function dearmor(input) {
|
||||||
headersDone = true;
|
headersDone = true;
|
||||||
if (textDone || type !== 2) {
|
if (textDone || type !== 2) {
|
||||||
resolve({ text, data, headers, type });
|
resolve({ text, data, headers, type });
|
||||||
resolved = true;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!textDone && type === 2) {
|
} else if (!textDone && type === 2) {
|
||||||
if (!reSplit.test(line)) {
|
if (!reSplit.test(line)) {
|
||||||
// Reverse dash-escaping for msg
|
// Reverse dash-escaping for msg
|
||||||
text.push(util.removeTrailingSpaces(lineUntrimmed.replace(/^- /, '').replace(/[\r\n]+$/, '')));
|
text.push(line.replace(/^- /, ''));
|
||||||
} else {
|
} else {
|
||||||
text = text.join('\r\n');
|
text = text.join('\r\n');
|
||||||
textDone = true;
|
textDone = true;
|
||||||
|
@ -257,26 +273,40 @@ function dearmor(input) {
|
||||||
lastHeaders = [];
|
lastHeaders = [];
|
||||||
headersDone = false;
|
headersDone = false;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (!reSplit.test(line)) {
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
} catch(e) {
|
||||||
|
reject(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const writer = stream.getWriter(writable);
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
await writer.ready;
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done) {
|
||||||
|
throw new Error('Misformed armored text');
|
||||||
|
}
|
||||||
|
const line = value + '';
|
||||||
|
if (line.indexOf('=') === -1 && line.indexOf('-') === -1) {
|
||||||
|
await writer.write(line);
|
||||||
|
} else {
|
||||||
|
let remainder = line + await reader.readToEnd();
|
||||||
|
remainder = remainder.replace(/[\t\r ]+$/mg, '');
|
||||||
|
const parts = remainder.split(reSplit);
|
||||||
|
if (parts.length === 1) {
|
||||||
|
throw new Error('Misformed armored text');
|
||||||
|
}
|
||||||
|
const split = splitChecksum(parts[0].slice(0, -1));
|
||||||
|
checksum = split.checksum;
|
||||||
|
await writer.write(split.body);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await writer.ready;
|
||||||
|
await writer.close();
|
||||||
|
} catch(e) {
|
||||||
|
await writer.abort(e);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
data = stream.transformPair(data, async (readable, writable) => {
|
data = stream.transformPair(data, async (readable, writable) => {
|
||||||
|
|
|
@ -142,8 +142,10 @@ function pako_zlib(constructor, options = {}) {
|
||||||
return function(data) {
|
return function(data) {
|
||||||
const obj = new constructor(options);
|
const obj = new constructor(options);
|
||||||
return stream.transform(data, value => {
|
return stream.transform(data, value => {
|
||||||
obj.push(value, pako.Z_SYNC_FLUSH);
|
if (value.length) {
|
||||||
return obj.result;
|
obj.push(value, pako.Z_SYNC_FLUSH);
|
||||||
|
return obj.result;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,14 +256,13 @@ export default {
|
||||||
packet = await reader.readBytes(packet_length);
|
packet = await reader.readBytes(packet_length);
|
||||||
await callback({ tag, packet });
|
await callback({ tag, packet });
|
||||||
}
|
}
|
||||||
const { done, value } = await reader.read();
|
const nextPacket = await reader.peekBytes(2);
|
||||||
if (!done) reader.unshift(value);
|
|
||||||
if (writer) {
|
if (writer) {
|
||||||
await writer.ready;
|
await writer.ready;
|
||||||
await writer.close();
|
await writer.close();
|
||||||
}
|
}
|
||||||
if (streaming) await callbackReturned;
|
if (streaming) await callbackReturned;
|
||||||
return done || !value || !value.length;
|
return !nextPacket || !nextPacket.length;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (writer) {
|
if (writer) {
|
||||||
await writer.abort(e);
|
await writer.abort(e);
|
||||||
|
|
|
@ -304,7 +304,7 @@ describe("ASCII armor", function() {
|
||||||
|
|
||||||
it('Accept header with trailing whitespace', async function () {
|
it('Accept header with trailing whitespace', async function () {
|
||||||
const privKey =
|
const privKey =
|
||||||
['-----BEGIN PGP PRIVATE KEY BLOCK-----\t \r',
|
['-----BEGIN PGP PRIVATE KEY BLOCK-----',
|
||||||
'Version: OpenPGP.js v0.3.0',
|
'Version: OpenPGP.js v0.3.0',
|
||||||
'Comment: https://openpgpjs.org',
|
'Comment: https://openpgpjs.org',
|
||||||
'',
|
'',
|
||||||
|
@ -321,7 +321,8 @@ describe("ASCII armor", function() {
|
||||||
'ABMFAlLm1+4JEBD8MASZrpALAhsMAAC3IgD8DnLGbMnpLtrX72RCkPW1ffLq',
|
'ABMFAlLm1+4JEBD8MASZrpALAhsMAAC3IgD8DnLGbMnpLtrX72RCkPW1ffLq',
|
||||||
'71vlXMJNXvoCeuejiRw=',
|
'71vlXMJNXvoCeuejiRw=',
|
||||||
'=wJNM',
|
'=wJNM',
|
||||||
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n');
|
'-----END PGP PRIVATE KEY BLOCK-----',
|
||||||
|
''].join('\t \r\n');
|
||||||
|
|
||||||
const result = await openpgp.key.readArmored(privKey);
|
const result = await openpgp.key.readArmored(privKey);
|
||||||
expect(result.err).to.not.exist;
|
expect(result.err).to.not.exist;
|
||||||
|
|
|
@ -841,19 +841,19 @@ const wrong_key =
|
||||||
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
|
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
|
||||||
|
|
||||||
const expiredKey =
|
const expiredKey =
|
||||||
`-----BEGIN PGP PRIVATE KEY BLOCK-----
|
`-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
|
|
||||||
xcA4BAAAAAEBAgCgONc0J8rfO6cJw5YTP38x1ze2tAYIO7EcmRCNYwMkXngb
|
xcA4BAAAAAEBAgCgONc0J8rfO6cJw5YTP38x1ze2tAYIO7EcmRCNYwMkXngb
|
||||||
0Qdzg34Q5RW0rNiR56VB6KElPUhePRPVklLFiIvHABEBAAEAAf9qabYMzsz/
|
0Qdzg34Q5RW0rNiR56VB6KElPUhePRPVklLFiIvHABEBAAEAAf9qabYMzsz/
|
||||||
/LeRVZSsTgTljmJTdzd2ambUbpi+vt8MXJsbaWh71vjoLMWSXajaKSPDjVU5
|
/LeRVZSsTgTljmJTdzd2ambUbpi+vt8MXJsbaWh71vjoLMWSXajaKSPDjVU5
|
||||||
waFNt9kLqwGGGLqpAQD5ZdMH2XzTq6GU9Ka69iZs6Pbnzwdz59Vc3i8hXlUj
|
waFNt9kLqwGGGLqpAQD5ZdMH2XzTq6GU9Ka69iZs6Pbnzwdz59Vc3i8hXlUj
|
||||||
zQEApHargCTsrtvSrm+hK/pN51/BHAy9lxCAw9f2etx+AeMA/RGrijkFZtYt
|
zQEApHargCTsrtvSrm+hK/pN51/BHAy9lxCAw9f2etx+AeMA/RGrijkFZtYt
|
||||||
jeWdv/usXL3mgHvEcJv63N5zcEvDX5X4W1bND3Rlc3QxIDxhQGIuY29tPsJ7
|
jeWdv/usXL3mgHvEcJv63N5zcEvDX5X4W1bND3Rlc3QxIDxhQGIuY29tPsJ7
|
||||||
BBABCAAvBQIAAAABBQMAAAU5BgsJBwgDAgkQzcF99nGrkAkEFQgKAgMWAgEC
|
BBABCAAvBQIAAAABBQMAAAU5BgsJBwgDAgkQzcF99nGrkAkEFQgKAgMWAgEC
|
||||||
GQECGwMCHgEAABAlAfwPehmLZs+gOhOTTaSslqQ50bl/REjmv42Nyr1ZBlQS
|
GQECGwMCHgEAABAlAfwPehmLZs+gOhOTTaSslqQ50bl/REjmv42Nyr1ZBlQS
|
||||||
DECl1Qu4QyeXin29uEXWiekMpNlZVsEuc8icCw6ABhIZ
|
DECl1Qu4QyeXin29uEXWiekMpNlZVsEuc8icCw6ABhIZ
|
||||||
=/7PI
|
=/7PI
|
||||||
-----END PGP PRIVATE KEY BLOCK-----`;
|
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||||
|
|
||||||
const multipleBindingSignatures =
|
const multipleBindingSignatures =
|
||||||
`-----BEGIN PGP PUBLIC KEY BLOCK-----
|
`-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
Loading…
Reference in New Issue
Block a user