@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
  const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
3
3
 
4
4
  import { createRequire } from 'module';
@@ -1549,6 +1549,8 @@ var config = {
1549
1549
  * by v6 keys and v6 signatures, respectively.
1550
1550
  * However, generation of v5 entities was supported behind config flag in OpenPGP.js v5, and some other libraries,
1551
1551
  * hence parsing them might be necessary in some cases.
1552
+ * @memberof module:config
1553
+ * @property {Boolean} enableParsingV5Entities
1552
1554
  */
1553
1555
  enableParsingV5Entities: false,
1554
1556
  /**
@@ -1685,10 +1687,22 @@ var config = {
1685
1687
  * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error
1686
1688
  */
1687
1689
  ignoreMalformedPackets: false,
1690
+ /**
1691
+ * @memberof module:config
1692
+ * @property {Boolean} enforceGrammar whether parsed OpenPGP messages must comform to the OpenPGP grammar
1693
+ * defined in https://www.rfc-editor.org/rfc/rfc9580.html#name-openpgp-messages .
1694
+ */
1695
+ enforceGrammar: true,
1696
+ /**
1697
+ * @memberof module:config
1698
+ * @property {function(string): any} pluggableGrammarErrorReporter callback meant to collect GrammarError reports even with `config.enforceGrammar` disabled.
1699
+ */
1700
+ pluggableGrammarErrorReporter: null,
1688
1701
  /**
1689
1702
  * Parsing of packets is normally restricted to a predefined set of packets. For example a Sym. Encrypted Integrity Protected Data Packet can only
1690
1703
  * contain a certain set of packets including LiteralDataPacket. With this setting we can allow additional packets, which is probably not advisable
1691
1704
  * as a global config setting, but can be used for specific function calls (e.g. decrypt method of Message).
1705
+ * NB: `config.enforceGrammar` may need to be disabled as well.
1692
1706
  * @memberof module:config
1693
1707
  * @property {Array} additionalAllowedPackets Allow additional packets on parsing. Defined as array of packet classes, e.g. [PublicKeyPacket]
1694
1708
  */
@@ -1707,7 +1721,7 @@ var config = {
1707
1721
  * @memberof module:config
1708
1722
  * @property {String} versionString A version string to be included in armored messages
1709
1723
  */
1710
- versionString: 'OpenPGP.js 6.1.1-patch.0',
1724
+ versionString: 'OpenPGP.js 6.1.1-patch.2',
1711
1725
  /**
1712
1726
  * @memberof module:config
1713
1727
  * @property {String} commentString A comment string to be included in armored messages
@@ -2079,6 +2093,21 @@ const util = {
2079
2093
  return true;
2080
2094
  },
2081
2095
 
2096
+ /**
2097
+ * Same as Array.findLastIndex, which is not supported on Safari 14 .
2098
+ * @param {Array} arr
2099
+ * @param {function(element, index, arr): boolean} findFn
2100
+ * @return index of last element matching `findFn`, -1 if not found
2101
+ */
2102
+ findLastIndex: function(arr, findFn) {
2103
+ for (let i = arr.length; i >= 0; i--) {
2104
+ if (findFn(arr[i], i, arr)) {
2105
+ return i;
2106
+ }
2107
+ }
2108
+ return -1;
2109
+ },
2110
+
2082
2111
  /**
2083
2112
  * Calculates a 16bit sum of a Uint8Array by adding each character
2084
2113
  * codes modulus 65535
@@ -6905,11 +6934,7 @@ async function generate$a(algo) {
6905
6934
  seed: b64ToUint8Array(privateKey.d, true)
6906
6935
  };
6907
6936
  } catch (err) {
6908
- if (
6909
- err.name !== 'NotSupportedError' &&
6910
- err.name !== 'OperationError' && // Temporary (hopefully) fix for WebKit on Linux
6911
- err.name !== 'SyntaxError' // Temporary fix for Palemoon throwing 'SyntaxError'
6912
- ) {
6937
+ if (err.name !== 'NotSupportedError' && err.name !== 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
6913
6938
  throw err;
6914
6939
  }
6915
6940
  const seed = getRandomBytes(getPayloadSize$1(algo));
@@ -6961,7 +6986,7 @@ async function sign$9(algo, hashAlgo, message, publicKey, privateKey, hashed) {
6961
6986
 
6962
6987
  return { RS: signature };
6963
6988
  } catch (err) {
6964
- if (err.name !== 'NotSupportedError' && err.name !== 'SyntaxError') { // Temporary fix for Palemoon throwing 'SyntaxError'
6989
+ if (err.name !== 'NotSupportedError') {
6965
6990
  throw err;
6966
6991
  }
6967
6992
  const secretKey = util.concatUint8Array([privateKey, publicKey]);
@@ -7007,7 +7032,7 @@ async function verify$9(algo, hashAlgo, { RS }, m, publicKey, hashed) {
7007
7032
  const verified = await webCrypto.verify('Ed25519', key, RS, hashed);
7008
7033
  return verified;
7009
7034
  } catch (err) {
7010
- if (err.name !== 'NotSupportedError' && err.name !== 'SyntaxError') { // Temporary fix for Palemoon throwing 'SyntaxError'
7035
+ if (err.name !== 'NotSupportedError') {
7011
7036
  throw err;
7012
7037
  }
7013
7038
  return verify$a(RS, hashed, publicKey);
@@ -15156,6 +15181,106 @@ OnePassSignaturePacket.prototype.hash = SignaturePacket.prototype.hash;
15156
15181
  OnePassSignaturePacket.prototype.toHash = SignaturePacket.prototype.toHash;
15157
15182
  OnePassSignaturePacket.prototype.toSign = SignaturePacket.prototype.toSign;
15158
15183
 
15184
+ class GrammarError extends Error {
15185
+ constructor(...params) {
15186
+ super(...params);
15187
+ if (Error.captureStackTrace) {
15188
+ Error.captureStackTrace(this, GrammarError);
15189
+ }
15190
+ this.name = 'GrammarError';
15191
+ }
15192
+ }
15193
+ const isValidLiteralMessage = (tagList, _acceptPartial) => tagList.length === 1 && tagList[0] === enums.packet.literalData;
15194
+ const isValidCompressedMessage = (tagList, _acceptPartial) => tagList.length === 1 && tagList[0] === enums.packet.compressedData;
15195
+ const isValidEncryptedMessage = (tagList, acceptPartial) => {
15196
+ // Encrypted Message: Encrypted Data | ESK Sequence, Encrypted Data.
15197
+ const isValidESKSequence = (tagList, _acceptPartial) => (tagList.every(packetTag => new Set([enums.packet.publicKeyEncryptedSessionKey, enums.packet.symEncryptedSessionKey]).has(packetTag)));
15198
+ const encryptedDataPacketIndex = tagList.findIndex(tag => new Set([enums.packet.aeadEncryptedData, enums.packet.symmetricallyEncryptedData, enums.packet.symEncryptedIntegrityProtectedData]).has(tag));
15199
+ if (encryptedDataPacketIndex < 0) {
15200
+ return isValidESKSequence(tagList);
15201
+ }
15202
+ return (encryptedDataPacketIndex === tagList.length - 1) &&
15203
+ isValidESKSequence(tagList.slice(0, encryptedDataPacketIndex));
15204
+ };
15205
+ const isValidSignedMessage = (tagList, acceptPartial) => {
15206
+ // Signature Packet, OpenPGP Message | One-Pass Signed Message.
15207
+ if (tagList.findIndex(tag => tag === enums.packet.signature) === 0) {
15208
+ return isValidOpenPGPMessage(tagList.slice(1), acceptPartial);
15209
+ }
15210
+ // One-Pass Signed Message:
15211
+ // One-Pass Signature Packet, OpenPGP Message, Corresponding Signature Packet.
15212
+ if (tagList.findIndex(tag => tag === enums.packet.onePassSignature) === 0) {
15213
+ const correspondingSigPacketIndex = util.findLastIndex(tagList, tag => tag === enums.packet.signature);
15214
+ if (correspondingSigPacketIndex !== tagList.length - 1 && !acceptPartial) {
15215
+ return false;
15216
+ }
15217
+ return isValidOpenPGPMessage(tagList.slice(1, correspondingSigPacketIndex < 0 ? undefined : correspondingSigPacketIndex), acceptPartial);
15218
+ }
15219
+ return false;
15220
+ };
15221
+ const isUnknownPacketTag = (tag) => {
15222
+ try {
15223
+ enums.read(enums.packet, tag);
15224
+ return false;
15225
+ }
15226
+ catch (e) {
15227
+ return true;
15228
+ }
15229
+ };
15230
+ /**
15231
+ * Implements grammar checks based on https://www.rfc-editor.org/rfc/rfc9580.html#section-10.3 .
15232
+ * @param notNormalizedList - list of packet tags to validate
15233
+ * @param acceptPartial - whether the list of tags corresponds to a partially-parsed message
15234
+ * @returns whether the list of tags is valid
15235
+ */
15236
+ const isValidOpenPGPMessage = (notNormalizedList /** might have unknown tags */, acceptPartial) => {
15237
+ // Take care of packet tags that can appear anywhere in the sequence:
15238
+ // 1. A Marker packet (Section 5.8) can appear anywhere in the sequence.
15239
+ // 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.
15240
+ // 3. An unknown non-critical packet MUST be ignored (criticality is enforced on parsing).
15241
+ const normalizedList = notNormalizedList.filter(tag => (tag !== enums.packet.marker &&
15242
+ tag !== enums.packet.padding &&
15243
+ !isUnknownPacketTag(tag)));
15244
+ return isValidLiteralMessage(normalizedList) ||
15245
+ isValidCompressedMessage(normalizedList) ||
15246
+ isValidEncryptedMessage(normalizedList) ||
15247
+ isValidSignedMessage(normalizedList, acceptPartial);
15248
+ };
15249
+ /**
15250
+ * If `delayReporting === false`, the grammar validator throws as soon as an invalid packet sequence is detected during parsing.
15251
+ * This setting MUST NOT be used when parsing unauthenticated decrypted data, to avoid instantiating decryption oracles.
15252
+ * Passing `delayReporting === true` allows checking the grammar validity in an async manner, by
15253
+ * only reporting the validity status after parsing is done (i.e. and authentication is expected to
15254
+ * have been enstablished)
15255
+ */
15256
+ const getMessageGrammarValidator = ({ delayReporting }) => {
15257
+ let logged = false;
15258
+ /**
15259
+ * @returns `true` on successful grammar validation; if `delayReporting` is set, `null` is returned
15260
+ * if validation is still pending (partial parsing, waiting for authentication to be confirmed).
15261
+ * @throws on grammar error, provided `config.enforceGrammar` is enabled.
15262
+ */
15263
+ return (list, isPartial, config) => {
15264
+ if (delayReporting && isPartial)
15265
+ return null; // delay until the full message has been parsed (i.e. authenticated)
15266
+ if (!isValidOpenPGPMessage(list, isPartial)) {
15267
+ const error = new GrammarError(`Data does not respect OpenPGP grammar [${list}]`);
15268
+ if (!logged) {
15269
+ config.pluggableGrammarErrorReporter?.(error.message);
15270
+ util.printDebugError(error);
15271
+ logged = true;
15272
+ }
15273
+ if (config.enforceGrammar) {
15274
+ throw error;
15275
+ }
15276
+ else {
15277
+ return true;
15278
+ }
15279
+ }
15280
+ return true;
15281
+ };
15282
+ };
15283
+
15159
15284
  /**
15160
15285
  * Instantiate a new packet given its tag
15161
15286
  * @function newPacketFromTag
@@ -15195,9 +15320,9 @@ class PacketList extends Array {
15195
15320
  * @throws on parsing errors
15196
15321
  * @async
15197
15322
  */
15198
- static async fromBinary(bytes, allowedPackets, config$1 = config) {
15323
+ static async fromBinary(bytes, allowedPackets, config$1 = config, grammarValidator = null) {
15199
15324
  const packets = new PacketList();
15200
- await packets.read(bytes, allowedPackets, config$1);
15325
+ await packets.read(bytes, allowedPackets, config$1, grammarValidator);
15201
15326
  return packets;
15202
15327
  }
15203
15328
 
@@ -15206,15 +15331,17 @@ class PacketList extends Array {
15206
15331
  * @param {Uint8Array | ReadableStream<Uint8Array>} bytes - binary data to parse
15207
15332
  * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class
15208
15333
  * @param {Object} [config] - full configuration, defaults to openpgp.config
15334
+ * @param {function(enums.packet[], boolean, Object): void} [grammarValidator]
15209
15335
  * @throws on parsing errors
15210
15336
  * @async
15211
15337
  */
15212
- async read(bytes, allowedPackets, config$1 = config) {
15338
+ async read(bytes, allowedPackets, config$1 = config, grammarValidator = null) {
15213
15339
  if (config$1.additionalAllowedPackets.length) {
15214
15340
  allowedPackets = { ...allowedPackets, ...util.constructAllowedPackets(config$1.additionalAllowedPackets) };
15215
15341
  }
15216
15342
  this.stream = transformPair(bytes, async (readable, writable) => {
15217
15343
  const writer = getWriter(writable);
15344
+ const writtenTags = [];
15218
15345
  try {
15219
15346
  while (true) {
15220
15347
  await writer.ready;
@@ -15232,6 +15359,12 @@ class PacketList extends Array {
15232
15359
  packet.fromStream = util.isStream(parsed.packet);
15233
15360
  await packet.read(parsed.packet, config$1);
15234
15361
  await writer.write(packet);
15362
+ writtenTags.push(parsed.tag);
15363
+ // The `writtenTags` are only sensitive if we are parsing an _unauthenticated_ decrypted stream,
15364
+ // since they can enable an decryption oracle.
15365
+ // It's responsibility of the caller to pass a `grammarValidator` that takes care of
15366
+ // postponing error reporting until the data has been authenticated.
15367
+ grammarValidator?.(writtenTags, true, config$1);
15235
15368
  } catch (e) {
15236
15369
  // If an implementation encounters a critical packet where the packet type is unknown in a packet sequence,
15237
15370
  // it MUST reject the whole packet sequence. On the other hand, an unknown non-critical packet MUST be ignored.
@@ -15246,7 +15379,8 @@ class PacketList extends Array {
15246
15379
 
15247
15380
  const throwUnsupportedError = !config$1.ignoreUnsupportedPackets && e instanceof UnsupportedError;
15248
15381
  const throwMalformedError = !config$1.ignoreMalformedPackets && !(e instanceof UnsupportedError);
15249
- if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) {
15382
+ const throwGrammarError = e instanceof GrammarError;
15383
+ if (throwUnsupportedError || throwMalformedError || throwGrammarError || supportsStreaming(parsed.tag)) {
15250
15384
  // The packets that support streaming are the ones that contain message data.
15251
15385
  // Those are also the ones we want to be more strict about and throw on parse errors
15252
15386
  // (since we likely cannot process the message without these packets anyway).
@@ -15254,11 +15388,16 @@ class PacketList extends Array {
15254
15388
  } else {
15255
15389
  const unparsedPacket = new UnparseablePacket(parsed.tag, parsed.packet);
15256
15390
  await writer.write(unparsedPacket);
15391
+ writtenTags.push(parsed.tag);
15392
+ grammarValidator?.(writtenTags, true, config$1);
15257
15393
  }
15258
15394
  util.printDebugError(e);
15259
15395
  }
15260
15396
  });
15261
15397
  if (done) {
15398
+ // Here we are past the MDC check for SEIPDv1 data, hence
15399
+ // the data is always authenticated at this point.
15400
+ grammarValidator?.(writtenTags, false, config$1);
15262
15401
  await writer.ready;
15263
15402
  await writer.close();
15264
15403
  return;
@@ -15481,7 +15620,8 @@ class CompressedDataPacket {
15481
15620
  throw new Error(`${compressionName} decompression not supported`);
15482
15621
  }
15483
15622
 
15484
- this.packets = await PacketList.fromBinary(await decompressionFn(this.compressed), allowedPackets$5, config$1);
15623
+ // Decompressing a Compressed Data packet MUST also yield a valid OpenPGP Message
15624
+ this.packets = await PacketList.fromBinary(await decompressionFn(this.compressed), allowedPackets$5, config$1, getMessageGrammarValidator({ enforceDelay: false }));
15485
15625
  }
15486
15626
 
15487
15627
  /**
@@ -15771,16 +15911,23 @@ class SymEncryptedIntegrityProtectedDataPacket {
15771
15911
  if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted);
15772
15912
 
15773
15913
  let packetbytes;
15914
+ let grammarValidator;
15774
15915
  if (this.version === 2) {
15775
15916
  if (this.cipherAlgorithm !== sessionKeyAlgorithm) {
15776
15917
  // sanity check
15777
15918
  throw new Error('Unexpected session key algorithm');
15778
15919
  }
15779
15920
  packetbytes = await runAEAD(this, 'decrypt', key, encrypted);
15921
+ grammarValidator = getMessageGrammarValidator({ delayReporting: false });
15780
15922
  } else {
15781
15923
  const { blockSize } = getCipherParams(sessionKeyAlgorithm);
15782
15924
  const decrypted = await decrypt$1(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize));
15783
15925
 
15926
+ // Grammar validation cannot be run before message integrity has been enstablished,
15927
+ // to avoid leaking info about the unauthenticated message structure.
15928
+ const releaseUnauthenticatedStream = util.isStream(encrypted) && config$1.allowUnauthenticatedStream;
15929
+ grammarValidator = getMessageGrammarValidator({ delayReporting: releaseUnauthenticatedStream });
15930
+
15784
15931
  // there must be a modification detection code packet as the
15785
15932
  // last packet and everything gets hashed except the hash itself
15786
15933
  const realHash = slice(passiveClone(decrypted), -20);
@@ -15792,17 +15939,23 @@ class SymEncryptedIntegrityProtectedDataPacket {
15792
15939
  if (!util.equalsUint8Array(hash, mdc)) {
15793
15940
  throw new Error('Modification detected.');
15794
15941
  }
15942
+ // this last chunk comes at the end of the stream passed to Packetlist.read's streamTransformPair,
15943
+ // which can thus be 'done' only after the MDC has been checked.
15795
15944
  return new Uint8Array();
15796
15945
  });
15797
15946
  const bytes = slice(tohash, blockSize + 2); // Remove random prefix
15798
15947
  packetbytes = slice(bytes, 0, -2); // Remove MDC packet
15799
15948
  packetbytes = concat([packetbytes, fromAsync(() => verifyHash)]);
15800
- if (!util.isStream(encrypted) || !config$1.allowUnauthenticatedStream) {
15949
+ if (!releaseUnauthenticatedStream) {
15801
15950
  packetbytes = await readToEnd(packetbytes);
15802
15951
  }
15803
15952
  }
15804
15953
 
15805
- this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$4, config$1);
15954
+ // - Decrypting a version 1 Symmetrically Encrypted and Integrity Protected Data packet
15955
+ // MUST yield a valid OpenPGP Message.
15956
+ // - Decrypting a version 2 Symmetrically Encrypted and Integrity Protected Data packet
15957
+ // MUST yield a valid Optionally Padded Message.
15958
+ this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$4, config$1, grammarValidator);
15806
15959
  return true;
15807
15960
  }
15808
15961
  }
@@ -16017,7 +16170,8 @@ class AEADEncryptedDataPacket {
16017
16170
  this.packets = await PacketList.fromBinary(
16018
16171
  await runAEAD(this, 'decrypt', key, clone(this.encrypted)),
16019
16172
  allowedPackets$3,
16020
- config$1
16173
+ config$1,
16174
+ getMessageGrammarValidator({ enforceDelay: false })
16021
16175
  );
16022
16176
  }
16023
16177
 
@@ -16944,6 +17098,10 @@ class SymmetricallyEncryptedDataPacket {
16944
17098
  encrypted.subarray(2, blockSize + 2)
16945
17099
  );
16946
17100
 
17101
+ // Decrypting a Symmetrically Encrypted Data packet MUST yield a valid OpenPGP Message.
17102
+ // But due to the lack of authentication over the decrypted data,
17103
+ // we do not run any grammarValidator, to avoid enabling a decryption oracle
17104
+ // (plus, there is probably a higher chance that these messages have an expected structure).
16947
17105
  this.packets = await PacketList.fromBinary(decrypted, allowedPackets$2, config$1);
16948
17106
  }
16949
17107
 
@@ -21546,7 +21704,7 @@ async function readMessage({ armoredMessage, binaryMessage, config: config$1, ..
21546
21704
  }
21547
21705
  input = data;
21548
21706
  }
21549
- const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config$1);
21707
+ const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config$1, getMessageGrammarValidator({ delayReporting: false }));
21550
21708
  const message = new Message(packetlist);
21551
21709
  message.fromStream = streamType;
21552
21710
  return message;
@@ -22166,7 +22324,7 @@ async function decrypt({ message, decryptionKeys, passwords, sessionKeys, verifi
22166
22324
  result.signatures = signature ? await decrypted.verifyDetached(signature, verificationKeys, date, config$1) : await decrypted.verify(verificationKeys, date, config$1);
22167
22325
  result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText();
22168
22326
  result.filename = decrypted.getFilename();
22169
- linkStreams(result, message);
22327
+ linkStreams(result, message, ...new Set([decrypted, decrypted.unwrapCompressed()]));
22170
22328
  if (expectSigned) {
22171
22329
  if (verificationKeys.length === 0) {
22172
22330
  throw new Error('Verification keys are required to verify message signatures');
@@ -22301,7 +22459,9 @@ async function verify({ message, verificationKeys, expectSigned = false, format
22301
22459
  result.signatures = await message.verify(verificationKeys, date, config$1);
22302
22460
  }
22303
22461
  result.data = format === 'binary' ? message.getLiteralData() : message.getText();
22304
- if (message.fromStream && !signature) linkStreams(result, message);
22462
+ if (message.fromStream && !signature) {
22463
+ linkStreams(result, ...new Set([message, message.unwrapCompressed()]));
22464
+ }
22305
22465
  if (expectSigned) {
22306
22466
  if (result.signatures.length === 0) {
22307
22467
  throw new Error('Message is not signed');
@@ -22498,22 +22658,25 @@ async function convertStream(data) {
22498
22658
  }
22499
22659
 
22500
22660
  /**
22501
- * Link result.data to the message stream for cancellation.
22502
- * Also, forward errors in the message to result.data.
22661
+ * Link result.data to the input message stream for cancellation.
22662
+ * Also, forward errors in the input message and intermediate messages to result.data.
22503
22663
  * @param {Object} result - the data to convert
22504
- * @param {Message} message - message object
22664
+ * @param {Message} message - message object provided by the user
22665
+ * @param {Message} intermediateMessages - intermediate message object with packet streams to link
22505
22666
  * @returns {Object}
22506
22667
  * @private
22507
22668
  */
22508
- function linkStreams(result, message) {
22509
- result.data = transformPair(message.packets.stream, async (readable, writable) => {
22669
+ function linkStreams(result, inputMessage, ...intermediateMessages) {
22670
+ result.data = transformPair(inputMessage.packets.stream, async (readable, writable) => {
22510
22671
  await pipe(result.data, writable, {
22511
22672
  preventClose: true
22512
22673
  });
22513
22674
  const writer = getWriter(writable);
22514
22675
  try {
22515
- // Forward errors in the message stream to result.data.
22676
+ // Forward errors in the message streams to result.data.
22516
22677
  await readToEnd(readable, _ => _);
22678
+ await Promise.all(intermediateMessages.map(intermediate => readToEnd(intermediate.packets.stream, _ => _)));
22679
+ // if result.data throws, the writable will be in errored state, and `close()` fails, but its ok.
22517
22680
  await writer.close();
22518
22681
  } catch (e) {
22519
22682
  await writer.abort(e);
@@ -31078,4 +31241,4 @@ var index = /*#__PURE__*/_mergeNamespaces({
31078
31241
  __proto__: null
31079
31242
  }, [lib]);
31080
31243
 
31081
- 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 };
31244
+ 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 };