@protontech/openpgp 6.1.1-patch.0 → 6.1.1-patch.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/lightweight/argon2id.min.mjs +1 -1
  2. package/dist/lightweight/argon2id.mjs +1 -1
  3. package/dist/lightweight/legacy_ciphers.min.mjs +1 -1
  4. package/dist/lightweight/legacy_ciphers.mjs +1 -1
  5. package/dist/lightweight/noble_curves.min.mjs +1 -1
  6. package/dist/lightweight/noble_curves.mjs +1 -1
  7. package/dist/lightweight/noble_hashes.min.mjs +1 -1
  8. package/dist/lightweight/noble_hashes.mjs +1 -1
  9. package/dist/lightweight/noble_post_quantum.min.mjs +1 -1
  10. package/dist/lightweight/noble_post_quantum.mjs +1 -1
  11. package/dist/lightweight/openpgp.min.mjs +4 -4
  12. package/dist/lightweight/openpgp.min.mjs.map +1 -1
  13. package/dist/lightweight/openpgp.mjs +190 -27
  14. package/dist/lightweight/seek-bzip.min.mjs +1 -1
  15. package/dist/lightweight/seek-bzip.mjs +1 -1
  16. package/dist/lightweight/sha3.min.mjs +1 -1
  17. package/dist/lightweight/sha3.mjs +1 -1
  18. package/dist/lightweight/sha512.min.mjs +1 -1
  19. package/dist/lightweight/sha512.mjs +1 -1
  20. package/dist/node/openpgp.cjs +190 -26
  21. package/dist/node/openpgp.min.cjs +16 -16
  22. package/dist/node/openpgp.min.cjs.map +1 -1
  23. package/dist/node/openpgp.min.mjs +16 -16
  24. package/dist/node/openpgp.min.mjs.map +1 -1
  25. package/dist/node/openpgp.mjs +190 -27
  26. package/dist/openpgp.js +190 -26
  27. package/dist/openpgp.min.js +16 -16
  28. package/dist/openpgp.min.js.map +1 -1
  29. package/dist/openpgp.min.mjs +16 -16
  30. package/dist/openpgp.min.mjs.map +1 -1
  31. package/dist/openpgp.mjs +190 -27
  32. package/openpgp.d.ts +4 -241
  33. package/package.json +3 -2
  34. package/src/config/config.d.ts +68 -0
  35. package/src/config/index.d.ts +13 -0
  36. package/src/enums.d.ts +195 -0
@@ -1,4 +1,4 @@
1
- /*! OpenPGP.js v6.1.1-patch.0 - 2025-02-12 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
1
+ /*! OpenPGP.js v6.1.1-patch.2 - 2025-05-14 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
2
2
  'use strict';
3
3
 
4
4
  const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -1572,6 +1572,8 @@ var config = {
1572
1572
  * by v6 keys and v6 signatures, respectively.
1573
1573
  * However, generation of v5 entities was supported behind config flag in OpenPGP.js v5, and some other libraries,
1574
1574
  * hence parsing them might be necessary in some cases.
1575
+ * @memberof module:config
1576
+ * @property {Boolean} enableParsingV5Entities
1575
1577
  */
1576
1578
  enableParsingV5Entities: false,
1577
1579
  /**
@@ -1708,10 +1710,22 @@ var config = {
1708
1710
  * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error
1709
1711
  */
1710
1712
  ignoreMalformedPackets: false,
1713
+ /**
1714
+ * @memberof module:config
1715
+ * @property {Boolean} enforceGrammar whether parsed OpenPGP messages must comform to the OpenPGP grammar
1716
+ * defined in https://www.rfc-editor.org/rfc/rfc9580.html#name-openpgp-messages .
1717
+ */
1718
+ enforceGrammar: true,
1719
+ /**
1720
+ * @memberof module:config
1721
+ * @property {function(string): any} pluggableGrammarErrorReporter callback meant to collect GrammarError reports even with `config.enforceGrammar` disabled.
1722
+ */
1723
+ pluggableGrammarErrorReporter: null,
1711
1724
  /**
1712
1725
  * Parsing of packets is normally restricted to a predefined set of packets. For example a Sym. Encrypted Integrity Protected Data Packet can only
1713
1726
  * contain a certain set of packets including LiteralDataPacket. With this setting we can allow additional packets, which is probably not advisable
1714
1727
  * as a global config setting, but can be used for specific function calls (e.g. decrypt method of Message).
1728
+ * NB: `config.enforceGrammar` may need to be disabled as well.
1715
1729
  * @memberof module:config
1716
1730
  * @property {Array} additionalAllowedPackets Allow additional packets on parsing. Defined as array of packet classes, e.g. [PublicKeyPacket]
1717
1731
  */
@@ -1730,7 +1744,7 @@ var config = {
1730
1744
  * @memberof module:config
1731
1745
  * @property {String} versionString A version string to be included in armored messages
1732
1746
  */
1733
- versionString: 'OpenPGP.js 6.1.1-patch.0',
1747
+ versionString: 'OpenPGP.js 6.1.1-patch.2',
1734
1748
  /**
1735
1749
  * @memberof module:config
1736
1750
  * @property {String} commentString A comment string to be included in armored messages
@@ -2102,6 +2116,21 @@ const util = {
2102
2116
  return true;
2103
2117
  },
2104
2118
 
2119
+ /**
2120
+ * Same as Array.findLastIndex, which is not supported on Safari 14 .
2121
+ * @param {Array} arr
2122
+ * @param {function(element, index, arr): boolean} findFn
2123
+ * @return index of last element matching `findFn`, -1 if not found
2124
+ */
2125
+ findLastIndex: function(arr, findFn) {
2126
+ for (let i = arr.length; i >= 0; i--) {
2127
+ if (findFn(arr[i], i, arr)) {
2128
+ return i;
2129
+ }
2130
+ }
2131
+ return -1;
2132
+ },
2133
+
2105
2134
  /**
2106
2135
  * Calculates a 16bit sum of a Uint8Array by adding each character
2107
2136
  * codes modulus 65535
@@ -6928,11 +6957,7 @@ async function generate$a(algo) {
6928
6957
  seed: b64ToUint8Array(privateKey.d, true)
6929
6958
  };
6930
6959
  } catch (err) {
6931
- if (
6932
- err.name !== 'NotSupportedError' &&
6933
- err.name !== 'OperationError' && // Temporary (hopefully) fix for WebKit on Linux
6934
- err.name !== 'SyntaxError' // Temporary fix for Palemoon throwing 'SyntaxError'
6935
- ) {
6960
+ if (err.name !== 'NotSupportedError' && err.name !== 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
6936
6961
  throw err;
6937
6962
  }
6938
6963
  const seed = getRandomBytes(getPayloadSize$1(algo));
@@ -6984,7 +7009,7 @@ async function sign$9(algo, hashAlgo, message, publicKey, privateKey, hashed) {
6984
7009
 
6985
7010
  return { RS: signature };
6986
7011
  } catch (err) {
6987
- if (err.name !== 'NotSupportedError' && err.name !== 'SyntaxError') { // Temporary fix for Palemoon throwing 'SyntaxError'
7012
+ if (err.name !== 'NotSupportedError') {
6988
7013
  throw err;
6989
7014
  }
6990
7015
  const secretKey = util.concatUint8Array([privateKey, publicKey]);
@@ -7030,7 +7055,7 @@ async function verify$9(algo, hashAlgo, { RS }, m, publicKey, hashed) {
7030
7055
  const verified = await webCrypto.verify('Ed25519', key, RS, hashed);
7031
7056
  return verified;
7032
7057
  } catch (err) {
7033
- if (err.name !== 'NotSupportedError' && err.name !== 'SyntaxError') { // Temporary fix for Palemoon throwing 'SyntaxError'
7058
+ if (err.name !== 'NotSupportedError') {
7034
7059
  throw err;
7035
7060
  }
7036
7061
  return verify$a(RS, hashed, publicKey);
@@ -15179,6 +15204,106 @@ OnePassSignaturePacket.prototype.hash = SignaturePacket.prototype.hash;
15179
15204
  OnePassSignaturePacket.prototype.toHash = SignaturePacket.prototype.toHash;
15180
15205
  OnePassSignaturePacket.prototype.toSign = SignaturePacket.prototype.toSign;
15181
15206
 
15207
+ class GrammarError extends Error {
15208
+ constructor(...params) {
15209
+ super(...params);
15210
+ if (Error.captureStackTrace) {
15211
+ Error.captureStackTrace(this, GrammarError);
15212
+ }
15213
+ this.name = 'GrammarError';
15214
+ }
15215
+ }
15216
+ const isValidLiteralMessage = (tagList, _acceptPartial) => tagList.length === 1 && tagList[0] === enums.packet.literalData;
15217
+ const isValidCompressedMessage = (tagList, _acceptPartial) => tagList.length === 1 && tagList[0] === enums.packet.compressedData;
15218
+ const isValidEncryptedMessage = (tagList, acceptPartial) => {
15219
+ // Encrypted Message: Encrypted Data | ESK Sequence, Encrypted Data.
15220
+ const isValidESKSequence = (tagList, _acceptPartial) => (tagList.every(packetTag => new Set([enums.packet.publicKeyEncryptedSessionKey, enums.packet.symEncryptedSessionKey]).has(packetTag)));
15221
+ const encryptedDataPacketIndex = tagList.findIndex(tag => new Set([enums.packet.aeadEncryptedData, enums.packet.symmetricallyEncryptedData, enums.packet.symEncryptedIntegrityProtectedData]).has(tag));
15222
+ if (encryptedDataPacketIndex < 0) {
15223
+ return isValidESKSequence(tagList);
15224
+ }
15225
+ return (encryptedDataPacketIndex === tagList.length - 1) &&
15226
+ isValidESKSequence(tagList.slice(0, encryptedDataPacketIndex));
15227
+ };
15228
+ const isValidSignedMessage = (tagList, acceptPartial) => {
15229
+ // Signature Packet, OpenPGP Message | One-Pass Signed Message.
15230
+ if (tagList.findIndex(tag => tag === enums.packet.signature) === 0) {
15231
+ return isValidOpenPGPMessage(tagList.slice(1), acceptPartial);
15232
+ }
15233
+ // One-Pass Signed Message:
15234
+ // One-Pass Signature Packet, OpenPGP Message, Corresponding Signature Packet.
15235
+ if (tagList.findIndex(tag => tag === enums.packet.onePassSignature) === 0) {
15236
+ const correspondingSigPacketIndex = util.findLastIndex(tagList, tag => tag === enums.packet.signature);
15237
+ if (correspondingSigPacketIndex !== tagList.length - 1 && !acceptPartial) {
15238
+ return false;
15239
+ }
15240
+ return isValidOpenPGPMessage(tagList.slice(1, correspondingSigPacketIndex < 0 ? undefined : correspondingSigPacketIndex), acceptPartial);
15241
+ }
15242
+ return false;
15243
+ };
15244
+ const isUnknownPacketTag = (tag) => {
15245
+ try {
15246
+ enums.read(enums.packet, tag);
15247
+ return false;
15248
+ }
15249
+ catch (e) {
15250
+ return true;
15251
+ }
15252
+ };
15253
+ /**
15254
+ * Implements grammar checks based on https://www.rfc-editor.org/rfc/rfc9580.html#section-10.3 .
15255
+ * @param notNormalizedList - list of packet tags to validate
15256
+ * @param acceptPartial - whether the list of tags corresponds to a partially-parsed message
15257
+ * @returns whether the list of tags is valid
15258
+ */
15259
+ const isValidOpenPGPMessage = (notNormalizedList /** might have unknown tags */, acceptPartial) => {
15260
+ // Take care of packet tags that can appear anywhere in the sequence:
15261
+ // 1. A Marker packet (Section 5.8) can appear anywhere in the sequence.
15262
+ // 2. An implementation MUST be able to process Padding packets anywhere else in an OpenPGP stream so that future revisions of this document may specify further locations for padding.
15263
+ // 3. An unknown non-critical packet MUST be ignored (criticality is enforced on parsing).
15264
+ const normalizedList = notNormalizedList.filter(tag => (tag !== enums.packet.marker &&
15265
+ tag !== enums.packet.padding &&
15266
+ !isUnknownPacketTag(tag)));
15267
+ return isValidLiteralMessage(normalizedList) ||
15268
+ isValidCompressedMessage(normalizedList) ||
15269
+ isValidEncryptedMessage(normalizedList) ||
15270
+ isValidSignedMessage(normalizedList, acceptPartial);
15271
+ };
15272
+ /**
15273
+ * If `delayReporting === false`, the grammar validator throws as soon as an invalid packet sequence is detected during parsing.
15274
+ * This setting MUST NOT be used when parsing unauthenticated decrypted data, to avoid instantiating decryption oracles.
15275
+ * Passing `delayReporting === true` allows checking the grammar validity in an async manner, by
15276
+ * only reporting the validity status after parsing is done (i.e. and authentication is expected to
15277
+ * have been enstablished)
15278
+ */
15279
+ const getMessageGrammarValidator = ({ delayReporting }) => {
15280
+ let logged = false;
15281
+ /**
15282
+ * @returns `true` on successful grammar validation; if `delayReporting` is set, `null` is returned
15283
+ * if validation is still pending (partial parsing, waiting for authentication to be confirmed).
15284
+ * @throws on grammar error, provided `config.enforceGrammar` is enabled.
15285
+ */
15286
+ return (list, isPartial, config) => {
15287
+ if (delayReporting && isPartial)
15288
+ return null; // delay until the full message has been parsed (i.e. authenticated)
15289
+ if (!isValidOpenPGPMessage(list, isPartial)) {
15290
+ const error = new GrammarError(`Data does not respect OpenPGP grammar [${list}]`);
15291
+ if (!logged) {
15292
+ config.pluggableGrammarErrorReporter?.(error.message);
15293
+ util.printDebugError(error);
15294
+ logged = true;
15295
+ }
15296
+ if (config.enforceGrammar) {
15297
+ throw error;
15298
+ }
15299
+ else {
15300
+ return true;
15301
+ }
15302
+ }
15303
+ return true;
15304
+ };
15305
+ };
15306
+
15182
15307
  /**
15183
15308
  * Instantiate a new packet given its tag
15184
15309
  * @function newPacketFromTag
@@ -15218,9 +15343,9 @@ class PacketList extends Array {
15218
15343
  * @throws on parsing errors
15219
15344
  * @async
15220
15345
  */
15221
- static async fromBinary(bytes, allowedPackets, config$1 = config) {
15346
+ static async fromBinary(bytes, allowedPackets, config$1 = config, grammarValidator = null) {
15222
15347
  const packets = new PacketList();
15223
- await packets.read(bytes, allowedPackets, config$1);
15348
+ await packets.read(bytes, allowedPackets, config$1, grammarValidator);
15224
15349
  return packets;
15225
15350
  }
15226
15351
 
@@ -15229,15 +15354,17 @@ class PacketList extends Array {
15229
15354
  * @param {Uint8Array | ReadableStream<Uint8Array>} bytes - binary data to parse
15230
15355
  * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class
15231
15356
  * @param {Object} [config] - full configuration, defaults to openpgp.config
15357
+ * @param {function(enums.packet[], boolean, Object): void} [grammarValidator]
15232
15358
  * @throws on parsing errors
15233
15359
  * @async
15234
15360
  */
15235
- async read(bytes, allowedPackets, config$1 = config) {
15361
+ async read(bytes, allowedPackets, config$1 = config, grammarValidator = null) {
15236
15362
  if (config$1.additionalAllowedPackets.length) {
15237
15363
  allowedPackets = { ...allowedPackets, ...util.constructAllowedPackets(config$1.additionalAllowedPackets) };
15238
15364
  }
15239
15365
  this.stream = transformPair(bytes, async (readable, writable) => {
15240
15366
  const writer = getWriter(writable);
15367
+ const writtenTags = [];
15241
15368
  try {
15242
15369
  while (true) {
15243
15370
  await writer.ready;
@@ -15255,6 +15382,12 @@ class PacketList extends Array {
15255
15382
  packet.fromStream = util.isStream(parsed.packet);
15256
15383
  await packet.read(parsed.packet, config$1);
15257
15384
  await writer.write(packet);
15385
+ writtenTags.push(parsed.tag);
15386
+ // The `writtenTags` are only sensitive if we are parsing an _unauthenticated_ decrypted stream,
15387
+ // since they can enable an decryption oracle.
15388
+ // It's responsibility of the caller to pass a `grammarValidator` that takes care of
15389
+ // postponing error reporting until the data has been authenticated.
15390
+ grammarValidator?.(writtenTags, true, config$1);
15258
15391
  } catch (e) {
15259
15392
  // If an implementation encounters a critical packet where the packet type is unknown in a packet sequence,
15260
15393
  // it MUST reject the whole packet sequence. On the other hand, an unknown non-critical packet MUST be ignored.
@@ -15269,7 +15402,8 @@ class PacketList extends Array {
15269
15402
 
15270
15403
  const throwUnsupportedError = !config$1.ignoreUnsupportedPackets && e instanceof UnsupportedError;
15271
15404
  const throwMalformedError = !config$1.ignoreMalformedPackets && !(e instanceof UnsupportedError);
15272
- if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) {
15405
+ const throwGrammarError = e instanceof GrammarError;
15406
+ if (throwUnsupportedError || throwMalformedError || throwGrammarError || supportsStreaming(parsed.tag)) {
15273
15407
  // The packets that support streaming are the ones that contain message data.
15274
15408
  // Those are also the ones we want to be more strict about and throw on parse errors
15275
15409
  // (since we likely cannot process the message without these packets anyway).
@@ -15277,11 +15411,16 @@ class PacketList extends Array {
15277
15411
  } else {
15278
15412
  const unparsedPacket = new UnparseablePacket(parsed.tag, parsed.packet);
15279
15413
  await writer.write(unparsedPacket);
15414
+ writtenTags.push(parsed.tag);
15415
+ grammarValidator?.(writtenTags, true, config$1);
15280
15416
  }
15281
15417
  util.printDebugError(e);
15282
15418
  }
15283
15419
  });
15284
15420
  if (done) {
15421
+ // Here we are past the MDC check for SEIPDv1 data, hence
15422
+ // the data is always authenticated at this point.
15423
+ grammarValidator?.(writtenTags, false, config$1);
15285
15424
  await writer.ready;
15286
15425
  await writer.close();
15287
15426
  return;
@@ -15504,7 +15643,8 @@ class CompressedDataPacket {
15504
15643
  throw new Error(`${compressionName} decompression not supported`);
15505
15644
  }
15506
15645
 
15507
- this.packets = await PacketList.fromBinary(await decompressionFn(this.compressed), allowedPackets$5, config$1);
15646
+ // Decompressing a Compressed Data packet MUST also yield a valid OpenPGP Message
15647
+ this.packets = await PacketList.fromBinary(await decompressionFn(this.compressed), allowedPackets$5, config$1, getMessageGrammarValidator({ enforceDelay: false }));
15508
15648
  }
15509
15649
 
15510
15650
  /**
@@ -15794,16 +15934,23 @@ class SymEncryptedIntegrityProtectedDataPacket {
15794
15934
  if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted);
15795
15935
 
15796
15936
  let packetbytes;
15937
+ let grammarValidator;
15797
15938
  if (this.version === 2) {
15798
15939
  if (this.cipherAlgorithm !== sessionKeyAlgorithm) {
15799
15940
  // sanity check
15800
15941
  throw new Error('Unexpected session key algorithm');
15801
15942
  }
15802
15943
  packetbytes = await runAEAD(this, 'decrypt', key, encrypted);
15944
+ grammarValidator = getMessageGrammarValidator({ delayReporting: false });
15803
15945
  } else {
15804
15946
  const { blockSize } = getCipherParams(sessionKeyAlgorithm);
15805
15947
  const decrypted = await decrypt$1(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize));
15806
15948
 
15949
+ // Grammar validation cannot be run before message integrity has been enstablished,
15950
+ // to avoid leaking info about the unauthenticated message structure.
15951
+ const releaseUnauthenticatedStream = util.isStream(encrypted) && config$1.allowUnauthenticatedStream;
15952
+ grammarValidator = getMessageGrammarValidator({ delayReporting: releaseUnauthenticatedStream });
15953
+
15807
15954
  // there must be a modification detection code packet as the
15808
15955
  // last packet and everything gets hashed except the hash itself
15809
15956
  const realHash = slice(passiveClone(decrypted), -20);
@@ -15815,17 +15962,23 @@ class SymEncryptedIntegrityProtectedDataPacket {
15815
15962
  if (!util.equalsUint8Array(hash, mdc)) {
15816
15963
  throw new Error('Modification detected.');
15817
15964
  }
15965
+ // this last chunk comes at the end of the stream passed to Packetlist.read's streamTransformPair,
15966
+ // which can thus be 'done' only after the MDC has been checked.
15818
15967
  return new Uint8Array();
15819
15968
  });
15820
15969
  const bytes = slice(tohash, blockSize + 2); // Remove random prefix
15821
15970
  packetbytes = slice(bytes, 0, -2); // Remove MDC packet
15822
15971
  packetbytes = concat([packetbytes, fromAsync(() => verifyHash)]);
15823
- if (!util.isStream(encrypted) || !config$1.allowUnauthenticatedStream) {
15972
+ if (!releaseUnauthenticatedStream) {
15824
15973
  packetbytes = await readToEnd(packetbytes);
15825
15974
  }
15826
15975
  }
15827
15976
 
15828
- this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$4, config$1);
15977
+ // - Decrypting a version 1 Symmetrically Encrypted and Integrity Protected Data packet
15978
+ // MUST yield a valid OpenPGP Message.
15979
+ // - Decrypting a version 2 Symmetrically Encrypted and Integrity Protected Data packet
15980
+ // MUST yield a valid Optionally Padded Message.
15981
+ this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$4, config$1, grammarValidator);
15829
15982
  return true;
15830
15983
  }
15831
15984
  }
@@ -16040,7 +16193,8 @@ class AEADEncryptedDataPacket {
16040
16193
  this.packets = await PacketList.fromBinary(
16041
16194
  await runAEAD(this, 'decrypt', key, clone(this.encrypted)),
16042
16195
  allowedPackets$3,
16043
- config$1
16196
+ config$1,
16197
+ getMessageGrammarValidator({ enforceDelay: false })
16044
16198
  );
16045
16199
  }
16046
16200
 
@@ -16967,6 +17121,10 @@ class SymmetricallyEncryptedDataPacket {
16967
17121
  encrypted.subarray(2, blockSize + 2)
16968
17122
  );
16969
17123
 
17124
+ // Decrypting a Symmetrically Encrypted Data packet MUST yield a valid OpenPGP Message.
17125
+ // But due to the lack of authentication over the decrypted data,
17126
+ // we do not run any grammarValidator, to avoid enabling a decryption oracle
17127
+ // (plus, there is probably a higher chance that these messages have an expected structure).
16970
17128
  this.packets = await PacketList.fromBinary(decrypted, allowedPackets$2, config$1);
16971
17129
  }
16972
17130
 
@@ -21569,7 +21727,7 @@ async function readMessage({ armoredMessage, binaryMessage, config: config$1, ..
21569
21727
  }
21570
21728
  input = data;
21571
21729
  }
21572
- const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config$1);
21730
+ const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config$1, getMessageGrammarValidator({ delayReporting: false }));
21573
21731
  const message = new Message(packetlist);
21574
21732
  message.fromStream = streamType;
21575
21733
  return message;
@@ -22189,7 +22347,7 @@ async function decrypt({ message, decryptionKeys, passwords, sessionKeys, verifi
22189
22347
  result.signatures = signature ? await decrypted.verifyDetached(signature, verificationKeys, date, config$1) : await decrypted.verify(verificationKeys, date, config$1);
22190
22348
  result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText();
22191
22349
  result.filename = decrypted.getFilename();
22192
- linkStreams(result, message);
22350
+ linkStreams(result, message, ...new Set([decrypted, decrypted.unwrapCompressed()]));
22193
22351
  if (expectSigned) {
22194
22352
  if (verificationKeys.length === 0) {
22195
22353
  throw new Error('Verification keys are required to verify message signatures');
@@ -22324,7 +22482,9 @@ async function verify({ message, verificationKeys, expectSigned = false, format
22324
22482
  result.signatures = await message.verify(verificationKeys, date, config$1);
22325
22483
  }
22326
22484
  result.data = format === 'binary' ? message.getLiteralData() : message.getText();
22327
- if (message.fromStream && !signature) linkStreams(result, message);
22485
+ if (message.fromStream && !signature) {
22486
+ linkStreams(result, ...new Set([message, message.unwrapCompressed()]));
22487
+ }
22328
22488
  if (expectSigned) {
22329
22489
  if (result.signatures.length === 0) {
22330
22490
  throw new Error('Message is not signed');
@@ -22521,22 +22681,25 @@ async function convertStream(data) {
22521
22681
  }
22522
22682
 
22523
22683
  /**
22524
- * Link result.data to the message stream for cancellation.
22525
- * Also, forward errors in the message to result.data.
22684
+ * Link result.data to the input message stream for cancellation.
22685
+ * Also, forward errors in the input message and intermediate messages to result.data.
22526
22686
  * @param {Object} result - the data to convert
22527
- * @param {Message} message - message object
22687
+ * @param {Message} message - message object provided by the user
22688
+ * @param {Message} intermediateMessages - intermediate message object with packet streams to link
22528
22689
  * @returns {Object}
22529
22690
  * @private
22530
22691
  */
22531
- function linkStreams(result, message) {
22532
- result.data = transformPair(message.packets.stream, async (readable, writable) => {
22692
+ function linkStreams(result, inputMessage, ...intermediateMessages) {
22693
+ result.data = transformPair(inputMessage.packets.stream, async (readable, writable) => {
22533
22694
  await pipe(result.data, writable, {
22534
22695
  preventClose: true
22535
22696
  });
22536
22697
  const writer = getWriter(writable);
22537
22698
  try {
22538
- // Forward errors in the message stream to result.data.
22699
+ // Forward errors in the message streams to result.data.
22539
22700
  await readToEnd(readable, _ => _);
22701
+ await Promise.all(intermediateMessages.map(intermediate => readToEnd(intermediate.packets.stream, _ => _)));
22702
+ // if result.data throws, the writable will be in errored state, and `close()` fails, but its ok.
22540
22703
  await writer.close();
22541
22704
  } catch (e) {
22542
22705
  await writer.abort(e);
@@ -31106,6 +31269,7 @@ exports.Argon2OutOfMemoryError = Argon2OutOfMemoryError;
31106
31269
  exports.Argon2S2K = Argon2S2K;
31107
31270
  exports.CleartextMessage = CleartextMessage;
31108
31271
  exports.CompressedDataPacket = CompressedDataPacket;
31272
+ exports.GrammarError = GrammarError;
31109
31273
  exports.KDFParams = KDFParams;
31110
31274
  exports.LiteralDataPacket = LiteralDataPacket;
31111
31275
  exports.MarkerPacket = MarkerPacket;