@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
package/dist/openpgp.mjs CHANGED
@@ -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
  const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
3
3
 
4
4
  function _mergeNamespaces(n, m) {
@@ -1545,6 +1545,8 @@ var config = {
1545
1545
  * by v6 keys and v6 signatures, respectively.
1546
1546
  * However, generation of v5 entities was supported behind config flag in OpenPGP.js v5, and some other libraries,
1547
1547
  * hence parsing them might be necessary in some cases.
1548
+ * @memberof module:config
1549
+ * @property {Boolean} enableParsingV5Entities
1548
1550
  */
1549
1551
  enableParsingV5Entities: false,
1550
1552
  /**
@@ -1681,10 +1683,22 @@ var config = {
1681
1683
  * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error
1682
1684
  */
1683
1685
  ignoreMalformedPackets: false,
1686
+ /**
1687
+ * @memberof module:config
1688
+ * @property {Boolean} enforceGrammar whether parsed OpenPGP messages must comform to the OpenPGP grammar
1689
+ * defined in https://www.rfc-editor.org/rfc/rfc9580.html#name-openpgp-messages .
1690
+ */
1691
+ enforceGrammar: true,
1692
+ /**
1693
+ * @memberof module:config
1694
+ * @property {function(string): any} pluggableGrammarErrorReporter callback meant to collect GrammarError reports even with `config.enforceGrammar` disabled.
1695
+ */
1696
+ pluggableGrammarErrorReporter: null,
1684
1697
  /**
1685
1698
  * Parsing of packets is normally restricted to a predefined set of packets. For example a Sym. Encrypted Integrity Protected Data Packet can only
1686
1699
  * contain a certain set of packets including LiteralDataPacket. With this setting we can allow additional packets, which is probably not advisable
1687
1700
  * as a global config setting, but can be used for specific function calls (e.g. decrypt method of Message).
1701
+ * NB: `config.enforceGrammar` may need to be disabled as well.
1688
1702
  * @memberof module:config
1689
1703
  * @property {Array} additionalAllowedPackets Allow additional packets on parsing. Defined as array of packet classes, e.g. [PublicKeyPacket]
1690
1704
  */
@@ -1703,7 +1717,7 @@ var config = {
1703
1717
  * @memberof module:config
1704
1718
  * @property {String} versionString A version string to be included in armored messages
1705
1719
  */
1706
- versionString: 'OpenPGP.js 6.1.1-patch.0',
1720
+ versionString: 'OpenPGP.js 6.1.1-patch.2',
1707
1721
  /**
1708
1722
  * @memberof module:config
1709
1723
  * @property {String} commentString A comment string to be included in armored messages
@@ -2076,6 +2090,21 @@ const util = {
2076
2090
  return true;
2077
2091
  },
2078
2092
 
2093
+ /**
2094
+ * Same as Array.findLastIndex, which is not supported on Safari 14 .
2095
+ * @param {Array} arr
2096
+ * @param {function(element, index, arr): boolean} findFn
2097
+ * @return index of last element matching `findFn`, -1 if not found
2098
+ */
2099
+ findLastIndex: function(arr, findFn) {
2100
+ for (let i = arr.length; i >= 0; i--) {
2101
+ if (findFn(arr[i], i, arr)) {
2102
+ return i;
2103
+ }
2104
+ }
2105
+ return -1;
2106
+ },
2107
+
2079
2108
  /**
2080
2109
  * Calculates a 16bit sum of a Uint8Array by adding each character
2081
2110
  * codes modulus 65535
@@ -6895,11 +6924,7 @@ async function generate$a(algo) {
6895
6924
  seed: b64ToUint8Array(privateKey.d, true)
6896
6925
  };
6897
6926
  } catch (err) {
6898
- if (
6899
- err.name !== 'NotSupportedError' &&
6900
- err.name !== 'OperationError' && // Temporary (hopefully) fix for WebKit on Linux
6901
- err.name !== 'SyntaxError' // Temporary fix for Palemoon throwing 'SyntaxError'
6902
- ) {
6927
+ if (err.name !== 'NotSupportedError' && err.name !== 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
6903
6928
  throw err;
6904
6929
  }
6905
6930
  const seed = getRandomBytes(getPayloadSize$1(algo));
@@ -6951,7 +6976,7 @@ async function sign$9(algo, hashAlgo, message, publicKey, privateKey, hashed) {
6951
6976
 
6952
6977
  return { RS: signature };
6953
6978
  } catch (err) {
6954
- if (err.name !== 'NotSupportedError' && err.name !== 'SyntaxError') { // Temporary fix for Palemoon throwing 'SyntaxError'
6979
+ if (err.name !== 'NotSupportedError') {
6955
6980
  throw err;
6956
6981
  }
6957
6982
  const secretKey = util.concatUint8Array([privateKey, publicKey]);
@@ -6997,7 +7022,7 @@ async function verify$9(algo, hashAlgo, { RS }, m, publicKey, hashed) {
6997
7022
  const verified = await webCrypto.verify('Ed25519', key, RS, hashed);
6998
7023
  return verified;
6999
7024
  } catch (err) {
7000
- if (err.name !== 'NotSupportedError' && err.name !== 'SyntaxError') { // Temporary fix for Palemoon throwing 'SyntaxError'
7025
+ if (err.name !== 'NotSupportedError') {
7001
7026
  throw err;
7002
7027
  }
7003
7028
  return verify$a(RS, hashed, publicKey);
@@ -15138,6 +15163,106 @@ OnePassSignaturePacket.prototype.hash = SignaturePacket.prototype.hash;
15138
15163
  OnePassSignaturePacket.prototype.toHash = SignaturePacket.prototype.toHash;
15139
15164
  OnePassSignaturePacket.prototype.toSign = SignaturePacket.prototype.toSign;
15140
15165
 
15166
+ class GrammarError extends Error {
15167
+ constructor(...params) {
15168
+ super(...params);
15169
+ if (Error.captureStackTrace) {
15170
+ Error.captureStackTrace(this, GrammarError);
15171
+ }
15172
+ this.name = 'GrammarError';
15173
+ }
15174
+ }
15175
+ const isValidLiteralMessage = (tagList, _acceptPartial) => tagList.length === 1 && tagList[0] === enums.packet.literalData;
15176
+ const isValidCompressedMessage = (tagList, _acceptPartial) => tagList.length === 1 && tagList[0] === enums.packet.compressedData;
15177
+ const isValidEncryptedMessage = (tagList, acceptPartial) => {
15178
+ // Encrypted Message: Encrypted Data | ESK Sequence, Encrypted Data.
15179
+ const isValidESKSequence = (tagList, _acceptPartial) => (tagList.every(packetTag => new Set([enums.packet.publicKeyEncryptedSessionKey, enums.packet.symEncryptedSessionKey]).has(packetTag)));
15180
+ const encryptedDataPacketIndex = tagList.findIndex(tag => new Set([enums.packet.aeadEncryptedData, enums.packet.symmetricallyEncryptedData, enums.packet.symEncryptedIntegrityProtectedData]).has(tag));
15181
+ if (encryptedDataPacketIndex < 0) {
15182
+ return isValidESKSequence(tagList);
15183
+ }
15184
+ return (encryptedDataPacketIndex === tagList.length - 1) &&
15185
+ isValidESKSequence(tagList.slice(0, encryptedDataPacketIndex));
15186
+ };
15187
+ const isValidSignedMessage = (tagList, acceptPartial) => {
15188
+ // Signature Packet, OpenPGP Message | One-Pass Signed Message.
15189
+ if (tagList.findIndex(tag => tag === enums.packet.signature) === 0) {
15190
+ return isValidOpenPGPMessage(tagList.slice(1), acceptPartial);
15191
+ }
15192
+ // One-Pass Signed Message:
15193
+ // One-Pass Signature Packet, OpenPGP Message, Corresponding Signature Packet.
15194
+ if (tagList.findIndex(tag => tag === enums.packet.onePassSignature) === 0) {
15195
+ const correspondingSigPacketIndex = util.findLastIndex(tagList, tag => tag === enums.packet.signature);
15196
+ if (correspondingSigPacketIndex !== tagList.length - 1 && !acceptPartial) {
15197
+ return false;
15198
+ }
15199
+ return isValidOpenPGPMessage(tagList.slice(1, correspondingSigPacketIndex < 0 ? undefined : correspondingSigPacketIndex), acceptPartial);
15200
+ }
15201
+ return false;
15202
+ };
15203
+ const isUnknownPacketTag = (tag) => {
15204
+ try {
15205
+ enums.read(enums.packet, tag);
15206
+ return false;
15207
+ }
15208
+ catch (e) {
15209
+ return true;
15210
+ }
15211
+ };
15212
+ /**
15213
+ * Implements grammar checks based on https://www.rfc-editor.org/rfc/rfc9580.html#section-10.3 .
15214
+ * @param notNormalizedList - list of packet tags to validate
15215
+ * @param acceptPartial - whether the list of tags corresponds to a partially-parsed message
15216
+ * @returns whether the list of tags is valid
15217
+ */
15218
+ const isValidOpenPGPMessage = (notNormalizedList /** might have unknown tags */, acceptPartial) => {
15219
+ // Take care of packet tags that can appear anywhere in the sequence:
15220
+ // 1. A Marker packet (Section 5.8) can appear anywhere in the sequence.
15221
+ // 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.
15222
+ // 3. An unknown non-critical packet MUST be ignored (criticality is enforced on parsing).
15223
+ const normalizedList = notNormalizedList.filter(tag => (tag !== enums.packet.marker &&
15224
+ tag !== enums.packet.padding &&
15225
+ !isUnknownPacketTag(tag)));
15226
+ return isValidLiteralMessage(normalizedList) ||
15227
+ isValidCompressedMessage(normalizedList) ||
15228
+ isValidEncryptedMessage(normalizedList) ||
15229
+ isValidSignedMessage(normalizedList, acceptPartial);
15230
+ };
15231
+ /**
15232
+ * If `delayReporting === false`, the grammar validator throws as soon as an invalid packet sequence is detected during parsing.
15233
+ * This setting MUST NOT be used when parsing unauthenticated decrypted data, to avoid instantiating decryption oracles.
15234
+ * Passing `delayReporting === true` allows checking the grammar validity in an async manner, by
15235
+ * only reporting the validity status after parsing is done (i.e. and authentication is expected to
15236
+ * have been enstablished)
15237
+ */
15238
+ const getMessageGrammarValidator = ({ delayReporting }) => {
15239
+ let logged = false;
15240
+ /**
15241
+ * @returns `true` on successful grammar validation; if `delayReporting` is set, `null` is returned
15242
+ * if validation is still pending (partial parsing, waiting for authentication to be confirmed).
15243
+ * @throws on grammar error, provided `config.enforceGrammar` is enabled.
15244
+ */
15245
+ return (list, isPartial, config) => {
15246
+ if (delayReporting && isPartial)
15247
+ return null; // delay until the full message has been parsed (i.e. authenticated)
15248
+ if (!isValidOpenPGPMessage(list, isPartial)) {
15249
+ const error = new GrammarError(`Data does not respect OpenPGP grammar [${list}]`);
15250
+ if (!logged) {
15251
+ config.pluggableGrammarErrorReporter?.(error.message);
15252
+ util.printDebugError(error);
15253
+ logged = true;
15254
+ }
15255
+ if (config.enforceGrammar) {
15256
+ throw error;
15257
+ }
15258
+ else {
15259
+ return true;
15260
+ }
15261
+ }
15262
+ return true;
15263
+ };
15264
+ };
15265
+
15141
15266
  /**
15142
15267
  * Instantiate a new packet given its tag
15143
15268
  * @function newPacketFromTag
@@ -15177,9 +15302,9 @@ class PacketList extends Array {
15177
15302
  * @throws on parsing errors
15178
15303
  * @async
15179
15304
  */
15180
- static async fromBinary(bytes, allowedPackets, config$1 = config) {
15305
+ static async fromBinary(bytes, allowedPackets, config$1 = config, grammarValidator = null) {
15181
15306
  const packets = new PacketList();
15182
- await packets.read(bytes, allowedPackets, config$1);
15307
+ await packets.read(bytes, allowedPackets, config$1, grammarValidator);
15183
15308
  return packets;
15184
15309
  }
15185
15310
 
@@ -15188,15 +15313,17 @@ class PacketList extends Array {
15188
15313
  * @param {Uint8Array | ReadableStream<Uint8Array>} bytes - binary data to parse
15189
15314
  * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class
15190
15315
  * @param {Object} [config] - full configuration, defaults to openpgp.config
15316
+ * @param {function(enums.packet[], boolean, Object): void} [grammarValidator]
15191
15317
  * @throws on parsing errors
15192
15318
  * @async
15193
15319
  */
15194
- async read(bytes, allowedPackets, config$1 = config) {
15320
+ async read(bytes, allowedPackets, config$1 = config, grammarValidator = null) {
15195
15321
  if (config$1.additionalAllowedPackets.length) {
15196
15322
  allowedPackets = { ...allowedPackets, ...util.constructAllowedPackets(config$1.additionalAllowedPackets) };
15197
15323
  }
15198
15324
  this.stream = transformPair(bytes, async (readable, writable) => {
15199
15325
  const writer = getWriter(writable);
15326
+ const writtenTags = [];
15200
15327
  try {
15201
15328
  while (true) {
15202
15329
  await writer.ready;
@@ -15214,6 +15341,12 @@ class PacketList extends Array {
15214
15341
  packet.fromStream = util.isStream(parsed.packet);
15215
15342
  await packet.read(parsed.packet, config$1);
15216
15343
  await writer.write(packet);
15344
+ writtenTags.push(parsed.tag);
15345
+ // The `writtenTags` are only sensitive if we are parsing an _unauthenticated_ decrypted stream,
15346
+ // since they can enable an decryption oracle.
15347
+ // It's responsibility of the caller to pass a `grammarValidator` that takes care of
15348
+ // postponing error reporting until the data has been authenticated.
15349
+ grammarValidator?.(writtenTags, true, config$1);
15217
15350
  } catch (e) {
15218
15351
  // If an implementation encounters a critical packet where the packet type is unknown in a packet sequence,
15219
15352
  // it MUST reject the whole packet sequence. On the other hand, an unknown non-critical packet MUST be ignored.
@@ -15228,7 +15361,8 @@ class PacketList extends Array {
15228
15361
 
15229
15362
  const throwUnsupportedError = !config$1.ignoreUnsupportedPackets && e instanceof UnsupportedError;
15230
15363
  const throwMalformedError = !config$1.ignoreMalformedPackets && !(e instanceof UnsupportedError);
15231
- if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) {
15364
+ const throwGrammarError = e instanceof GrammarError;
15365
+ if (throwUnsupportedError || throwMalformedError || throwGrammarError || supportsStreaming(parsed.tag)) {
15232
15366
  // The packets that support streaming are the ones that contain message data.
15233
15367
  // Those are also the ones we want to be more strict about and throw on parse errors
15234
15368
  // (since we likely cannot process the message without these packets anyway).
@@ -15236,11 +15370,16 @@ class PacketList extends Array {
15236
15370
  } else {
15237
15371
  const unparsedPacket = new UnparseablePacket(parsed.tag, parsed.packet);
15238
15372
  await writer.write(unparsedPacket);
15373
+ writtenTags.push(parsed.tag);
15374
+ grammarValidator?.(writtenTags, true, config$1);
15239
15375
  }
15240
15376
  util.printDebugError(e);
15241
15377
  }
15242
15378
  });
15243
15379
  if (done) {
15380
+ // Here we are past the MDC check for SEIPDv1 data, hence
15381
+ // the data is always authenticated at this point.
15382
+ grammarValidator?.(writtenTags, false, config$1);
15244
15383
  await writer.ready;
15245
15384
  await writer.close();
15246
15385
  return;
@@ -15463,7 +15602,8 @@ class CompressedDataPacket {
15463
15602
  throw new Error(`${compressionName} decompression not supported`);
15464
15603
  }
15465
15604
 
15466
- this.packets = await PacketList.fromBinary(await decompressionFn(this.compressed), allowedPackets$5, config$1);
15605
+ // Decompressing a Compressed Data packet MUST also yield a valid OpenPGP Message
15606
+ this.packets = await PacketList.fromBinary(await decompressionFn(this.compressed), allowedPackets$5, config$1, getMessageGrammarValidator({ enforceDelay: false }));
15467
15607
  }
15468
15608
 
15469
15609
  /**
@@ -15753,16 +15893,23 @@ class SymEncryptedIntegrityProtectedDataPacket {
15753
15893
  if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted);
15754
15894
 
15755
15895
  let packetbytes;
15896
+ let grammarValidator;
15756
15897
  if (this.version === 2) {
15757
15898
  if (this.cipherAlgorithm !== sessionKeyAlgorithm) {
15758
15899
  // sanity check
15759
15900
  throw new Error('Unexpected session key algorithm');
15760
15901
  }
15761
15902
  packetbytes = await runAEAD(this, 'decrypt', key, encrypted);
15903
+ grammarValidator = getMessageGrammarValidator({ delayReporting: false });
15762
15904
  } else {
15763
15905
  const { blockSize } = getCipherParams(sessionKeyAlgorithm);
15764
15906
  const decrypted = await decrypt$1(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize));
15765
15907
 
15908
+ // Grammar validation cannot be run before message integrity has been enstablished,
15909
+ // to avoid leaking info about the unauthenticated message structure.
15910
+ const releaseUnauthenticatedStream = util.isStream(encrypted) && config$1.allowUnauthenticatedStream;
15911
+ grammarValidator = getMessageGrammarValidator({ delayReporting: releaseUnauthenticatedStream });
15912
+
15766
15913
  // there must be a modification detection code packet as the
15767
15914
  // last packet and everything gets hashed except the hash itself
15768
15915
  const realHash = slice(passiveClone(decrypted), -20);
@@ -15774,17 +15921,23 @@ class SymEncryptedIntegrityProtectedDataPacket {
15774
15921
  if (!util.equalsUint8Array(hash, mdc)) {
15775
15922
  throw new Error('Modification detected.');
15776
15923
  }
15924
+ // this last chunk comes at the end of the stream passed to Packetlist.read's streamTransformPair,
15925
+ // which can thus be 'done' only after the MDC has been checked.
15777
15926
  return new Uint8Array();
15778
15927
  });
15779
15928
  const bytes = slice(tohash, blockSize + 2); // Remove random prefix
15780
15929
  packetbytes = slice(bytes, 0, -2); // Remove MDC packet
15781
15930
  packetbytes = concat([packetbytes, fromAsync(() => verifyHash)]);
15782
- if (!util.isStream(encrypted) || !config$1.allowUnauthenticatedStream) {
15931
+ if (!releaseUnauthenticatedStream) {
15783
15932
  packetbytes = await readToEnd(packetbytes);
15784
15933
  }
15785
15934
  }
15786
15935
 
15787
- this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$4, config$1);
15936
+ // - Decrypting a version 1 Symmetrically Encrypted and Integrity Protected Data packet
15937
+ // MUST yield a valid OpenPGP Message.
15938
+ // - Decrypting a version 2 Symmetrically Encrypted and Integrity Protected Data packet
15939
+ // MUST yield a valid Optionally Padded Message.
15940
+ this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$4, config$1, grammarValidator);
15788
15941
  return true;
15789
15942
  }
15790
15943
  }
@@ -15999,7 +16152,8 @@ class AEADEncryptedDataPacket {
15999
16152
  this.packets = await PacketList.fromBinary(
16000
16153
  await runAEAD(this, 'decrypt', key, clone(this.encrypted)),
16001
16154
  allowedPackets$3,
16002
- config$1
16155
+ config$1,
16156
+ getMessageGrammarValidator({ enforceDelay: false })
16003
16157
  );
16004
16158
  }
16005
16159
 
@@ -16926,6 +17080,10 @@ class SymmetricallyEncryptedDataPacket {
16926
17080
  encrypted.subarray(2, blockSize + 2)
16927
17081
  );
16928
17082
 
17083
+ // Decrypting a Symmetrically Encrypted Data packet MUST yield a valid OpenPGP Message.
17084
+ // But due to the lack of authentication over the decrypted data,
17085
+ // we do not run any grammarValidator, to avoid enabling a decryption oracle
17086
+ // (plus, there is probably a higher chance that these messages have an expected structure).
16929
17087
  this.packets = await PacketList.fromBinary(decrypted, allowedPackets$2, config$1);
16930
17088
  }
16931
17089
 
@@ -21528,7 +21686,7 @@ async function readMessage({ armoredMessage, binaryMessage, config: config$1, ..
21528
21686
  }
21529
21687
  input = data;
21530
21688
  }
21531
- const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config$1);
21689
+ const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config$1, getMessageGrammarValidator({ delayReporting: false }));
21532
21690
  const message = new Message(packetlist);
21533
21691
  message.fromStream = streamType;
21534
21692
  return message;
@@ -22148,7 +22306,7 @@ async function decrypt({ message, decryptionKeys, passwords, sessionKeys, verifi
22148
22306
  result.signatures = signature ? await decrypted.verifyDetached(signature, verificationKeys, date, config$1) : await decrypted.verify(verificationKeys, date, config$1);
22149
22307
  result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText();
22150
22308
  result.filename = decrypted.getFilename();
22151
- linkStreams(result, message);
22309
+ linkStreams(result, message, ...new Set([decrypted, decrypted.unwrapCompressed()]));
22152
22310
  if (expectSigned) {
22153
22311
  if (verificationKeys.length === 0) {
22154
22312
  throw new Error('Verification keys are required to verify message signatures');
@@ -22283,7 +22441,9 @@ async function verify({ message, verificationKeys, expectSigned = false, format
22283
22441
  result.signatures = await message.verify(verificationKeys, date, config$1);
22284
22442
  }
22285
22443
  result.data = format === 'binary' ? message.getLiteralData() : message.getText();
22286
- if (message.fromStream && !signature) linkStreams(result, message);
22444
+ if (message.fromStream && !signature) {
22445
+ linkStreams(result, ...new Set([message, message.unwrapCompressed()]));
22446
+ }
22287
22447
  if (expectSigned) {
22288
22448
  if (result.signatures.length === 0) {
22289
22449
  throw new Error('Message is not signed');
@@ -22480,22 +22640,25 @@ async function convertStream(data) {
22480
22640
  }
22481
22641
 
22482
22642
  /**
22483
- * Link result.data to the message stream for cancellation.
22484
- * Also, forward errors in the message to result.data.
22643
+ * Link result.data to the input message stream for cancellation.
22644
+ * Also, forward errors in the input message and intermediate messages to result.data.
22485
22645
  * @param {Object} result - the data to convert
22486
- * @param {Message} message - message object
22646
+ * @param {Message} message - message object provided by the user
22647
+ * @param {Message} intermediateMessages - intermediate message object with packet streams to link
22487
22648
  * @returns {Object}
22488
22649
  * @private
22489
22650
  */
22490
- function linkStreams(result, message) {
22491
- result.data = transformPair(message.packets.stream, async (readable, writable) => {
22651
+ function linkStreams(result, inputMessage, ...intermediateMessages) {
22652
+ result.data = transformPair(inputMessage.packets.stream, async (readable, writable) => {
22492
22653
  await pipe(result.data, writable, {
22493
22654
  preventClose: true
22494
22655
  });
22495
22656
  const writer = getWriter(writable);
22496
22657
  try {
22497
- // Forward errors in the message stream to result.data.
22658
+ // Forward errors in the message streams to result.data.
22498
22659
  await readToEnd(readable, _ => _);
22660
+ await Promise.all(intermediateMessages.map(intermediate => readToEnd(intermediate.packets.stream, _ => _)));
22661
+ // if result.data throws, the writable will be in errored state, and `close()` fails, but its ok.
22499
22662
  await writer.close();
22500
22663
  } catch (e) {
22501
22664
  await writer.abort(e);
@@ -31057,4 +31220,4 @@ var index = /*#__PURE__*/_mergeNamespaces({
31057
31220
  __proto__: null
31058
31221
  }, [lib]);
31059
31222
 
31060
- export { AEADEncryptedDataPacket, Argon2OutOfMemoryError, Argon2S2K, CleartextMessage, CompressedDataPacket, KDFParams, LiteralDataPacket, MarkerPacket, Message, OnePassSignaturePacket, PacketList, PaddingPacket, PrivateKey, PublicKey, PublicKeyEncryptedSessionKeyPacket, PublicKeyPacket, PublicSubkeyPacket, SecretKeyPacket, SecretSubkeyPacket, Signature, SignaturePacket, Subkey, SymEncryptedIntegrityProtectedDataPacket, SymEncryptedSessionKeyPacket, SymmetricallyEncryptedDataPacket, TrustPacket, UnparseablePacket, UserAttributePacket, UserIDPacket, armor, config, createCleartextMessage, createMessage, decrypt, decryptKey, decryptSessionKeys, encrypt, encryptKey, encryptSessionKey, enums, generateKey, generateSessionKey, readCleartextMessage, readKey, readKeys, readMessage, readPrivateKey, readPrivateKeys, readSignature, reformatKey, revokeKey, sign, unarmor, verify };
31223
+ export { AEADEncryptedDataPacket, Argon2OutOfMemoryError, Argon2S2K, CleartextMessage, CompressedDataPacket, GrammarError, KDFParams, LiteralDataPacket, MarkerPacket, Message, OnePassSignaturePacket, PacketList, PaddingPacket, PrivateKey, PublicKey, PublicKeyEncryptedSessionKeyPacket, PublicKeyPacket, PublicSubkeyPacket, SecretKeyPacket, SecretSubkeyPacket, Signature, SignaturePacket, Subkey, SymEncryptedIntegrityProtectedDataPacket, SymEncryptedSessionKeyPacket, SymmetricallyEncryptedDataPacket, TrustPacket, UnparseablePacket, UserAttributePacket, UserIDPacket, armor, config, createCleartextMessage, createMessage, decrypt, decryptKey, decryptSessionKeys, encrypt, encryptKey, encryptSessionKey, enums, generateKey, generateSessionKey, readCleartextMessage, readKey, readKeys, readMessage, readPrivateKey, readPrivateKeys, readSignature, reformatKey, revokeKey, sign, unarmor, verify };