modern-pdf-lib 0.33.0 → 0.34.0

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 (42) hide show
  1. package/README.md +3 -3
  2. package/dist/browser.cjs +6 -3
  3. package/dist/browser.d.cts +5 -5
  4. package/dist/browser.d.mts +5 -5
  5. package/dist/browser.mjs +4 -4
  6. package/dist/{compressionAnalysis-0m5jJG1_.d.mts → compressionAnalysis-4EW8MJBa.d.mts} +2 -2
  7. package/dist/{compressionAnalysis-0m5jJG1_.d.mts.map → compressionAnalysis-4EW8MJBa.d.mts.map} +1 -1
  8. package/dist/{compressionAnalysis-CSBcmi0_.d.cts → compressionAnalysis-Cz3yWa-O.d.cts} +2 -2
  9. package/dist/{compressionAnalysis-CSBcmi0_.d.cts.map → compressionAnalysis-Cz3yWa-O.d.cts.map} +1 -1
  10. package/dist/create.cjs +2 -2
  11. package/dist/create.d.cts +2 -2
  12. package/dist/create.d.mts +2 -2
  13. package/dist/create.mjs +2 -2
  14. package/dist/{fontEmbed-Bzv89wgp.d.mts → fontEmbed-CTTeV1mZ.d.mts} +2 -2
  15. package/dist/{fontEmbed-Bzv89wgp.d.mts.map → fontEmbed-CTTeV1mZ.d.mts.map} +1 -1
  16. package/dist/{fontEmbed-Dwl1XeEA.d.cts → fontEmbed-DxvWoqOt.d.cts} +2 -2
  17. package/dist/{fontEmbed-Dwl1XeEA.d.cts.map → fontEmbed-DxvWoqOt.d.cts.map} +1 -1
  18. package/dist/{index-BJtSRrMf.d.mts → index-C240uDcb.d.mts} +95 -45
  19. package/dist/index-C240uDcb.d.mts.map +1 -0
  20. package/dist/{index-BqYQ9lsY.d.cts → index-Z4U1Jx0K.d.cts} +95 -45
  21. package/dist/index-Z4U1Jx0K.d.cts.map +1 -0
  22. package/dist/index.cjs +6 -3
  23. package/dist/index.d.cts +5 -5
  24. package/dist/index.d.mts +5 -5
  25. package/dist/index.mjs +4 -4
  26. package/dist/{layout-BYXpcYtC.cjs → layout-ClbkITM3.cjs} +2 -2
  27. package/dist/{layout-xOcesNCh.mjs → layout-XgQY_Uba.mjs} +2 -2
  28. package/dist/parse.cjs +1 -1
  29. package/dist/parse.d.cts +2 -2
  30. package/dist/parse.d.mts +2 -2
  31. package/dist/parse.mjs +1 -1
  32. package/dist/{pdfDocument-B8tQcZqj.d.cts → pdfDocument-BX5o5hI7.d.cts} +13 -1
  33. package/dist/{pdfDocument-B-8iPl_j.d.mts.map → pdfDocument-BX5o5hI7.d.cts.map} +1 -1
  34. package/dist/{pdfDocument-B-8iPl_j.d.mts → pdfDocument-C7TItmPQ.d.mts} +13 -1
  35. package/dist/{pdfDocument-B8tQcZqj.d.cts.map → pdfDocument-C7TItmPQ.d.mts.map} +1 -1
  36. package/dist/{pdfDocument-Bh4ebDqE.cjs → pdfDocument-Dyj4AmT1.cjs} +358 -21
  37. package/dist/{pdfDocument-Cgkkk8F8.mjs → pdfDocument-EcHxUnR6.mjs} +347 -22
  38. package/dist/{src-zeRl33xQ.mjs → src-CiUkSS81.mjs} +263 -23
  39. package/dist/{src-BdVnpRoy.cjs → src-PxZwqIKQ.cjs} +268 -22
  40. package/package.json +1 -1
  41. package/dist/index-BJtSRrMf.d.mts.map +0 -1
  42. package/dist/index-BqYQ9lsY.d.cts.map +0 -1
@@ -21926,7 +21926,200 @@ function findSignatures(pdfBytes) {
21926
21926
  return results;
21927
21927
  }
21928
21928
  //#endregion
21929
+ //#region src/signature/cadesAttributes.ts
21930
+ /**
21931
+ * @module signature/cadesAttributes
21932
+ *
21933
+ * CAdES-BES / PAdES-B-B baseline signed attributes.
21934
+ *
21935
+ * Implements the ESS `signing-certificate-v2` attribute that binds a
21936
+ * signature to the exact signer certificate that produced it, defeating
21937
+ * certificate-substitution attacks. This is the mandatory signed
21938
+ * attribute for the CAdES-BES and PAdES-B-B (a.k.a. PAdES Baseline)
21939
+ * conformance levels.
21940
+ *
21941
+ * Structure (RFC 5035 §3, "ESS Update: Adding CertID Algorithm Agility"):
21942
+ * ```
21943
+ * id-aa-signingCertificateV2 OBJECT IDENTIFIER ::= { iso(1)
21944
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
21945
+ * smime(16) id-aa(2) 47 } -- 1.2.840.113549.1.9.16.2.47
21946
+ *
21947
+ * Attribute ::= SEQUENCE {
21948
+ * attrType OBJECT IDENTIFIER, -- id-aa-signingCertificateV2
21949
+ * attrValues SET OF SigningCertificateV2 }
21950
+ *
21951
+ * SigningCertificateV2 ::= SEQUENCE {
21952
+ * certs SEQUENCE OF ESSCertIDv2,
21953
+ * policies SEQUENCE OF PolicyInformation OPTIONAL } -- omitted here
21954
+ *
21955
+ * ESSCertIDv2 ::= SEQUENCE {
21956
+ * hashAlgorithm AlgorithmIdentifier DEFAULT {algorithm id-sha256},
21957
+ * certHash Hash, -- OCTET STRING
21958
+ * issuerSerial IssuerSerial OPTIONAL } -- omitted here
21959
+ *
21960
+ * Hash ::= OCTET STRING
21961
+ * ```
21962
+ *
21963
+ * Because `hashAlgorithm` carries `DEFAULT {algorithm id-sha256}`, DER
21964
+ * (X.690 §11.5) requires the field to be **omitted** when the hash is
21965
+ * SHA-256, and **present** for any other algorithm (e.g. SHA-384,
21966
+ * SHA-512). `certHash` is the digest of the WHOLE DER certificate.
21967
+ *
21968
+ * References:
21969
+ * - RFC 5035 (Enhanced Security Services (ESS) Update — signing-certificate-v2)
21970
+ * - ETSI EN 319 122-1 (CAdES baseline) — requires id-aa-signingCertificateV2
21971
+ * - ETSI EN 319 142-1 (PAdES baseline) — PAdES-B-B uses the same attribute
21972
+ *
21973
+ * Every OID and ASN.1 element here was verified against RFC 5035.
21974
+ *
21975
+ * @packageDocumentation
21976
+ */
21977
+ /** id-aa-signingCertificateV2 — RFC 5035 §3. */
21978
+ const ID_AA_SIGNING_CERTIFICATE_V2 = "1.2.840.113549.1.9.16.2.47";
21979
+ /** Hash algorithm OIDs (NIST CSOR; same values used throughout pkcs7.ts). */
21980
+ const SHA256_OID = "2.16.840.1.101.3.4.2.1";
21981
+ const SHA384_OID = "2.16.840.1.101.3.4.2.2";
21982
+ const SHA512_OID = "2.16.840.1.101.3.4.2.3";
21983
+ /** DER literal for an explicit NULL value (tag 0x05, length 0). */
21984
+ const DER_NULL = new Uint8Array([5, 0]);
21985
+ /**
21986
+ * Encode an AlgorithmIdentifier SEQUENCE for a SHA-2 hash with NULL
21987
+ * parameters: `SEQUENCE { OID, NULL }`.
21988
+ *
21989
+ * RFC 5035's ESSCertIDv2 uses the same AlgorithmIdentifier as the rest
21990
+ * of the CMS structure; SHA-2 digest algorithms carry NULL parameters
21991
+ * (RFC 5754 permits either NULL or absent — we emit NULL to match the
21992
+ * digestAlgorithm encoding already used by pkcs7.ts).
21993
+ */
21994
+ function encodeHashAlgorithmIdentifier(hashOid) {
21995
+ return encodeSequence([encodeOID(hashOid), DER_NULL]);
21996
+ }
21997
+ /** Map a Web Crypto hash name to its OID. */
21998
+ function hashNameToOid(hash) {
21999
+ switch (hash) {
22000
+ case "SHA-256": return SHA256_OID;
22001
+ case "SHA-384": return SHA384_OID;
22002
+ case "SHA-512": return SHA512_OID;
22003
+ default: throw new Error(`Unsupported hash algorithm: ${String(hash)}`);
22004
+ }
22005
+ }
22006
+ /**
22007
+ * Build the ESS `signing-certificate-v2` signed attribute (RFC 5035).
22008
+ *
22009
+ * The returned bytes are a complete DER-encoded `Attribute` SEQUENCE
22010
+ * suitable for insertion into the CMS `SignedAttributes` SET.
22011
+ *
22012
+ * Encoding rules applied (verified against RFC 5035):
22013
+ * - `hashAlgorithm` is OMITTED when `hashAlgorithm === 'SHA-256'` (the
22014
+ * `DEFAULT {algorithm id-sha256}`), and INCLUDED for SHA-384/SHA-512.
22015
+ * - `certHash` is `subtle.digest(hashAlgorithm, <whole DER cert>)`.
22016
+ * - `issuerSerial` and `policies` are OPTIONAL and omitted.
22017
+ *
22018
+ * @param certDer The DER-encoded X.509 signer certificate.
22019
+ * @param hashAlgorithm The digest used for `certHash`.
22020
+ * @returns DER-encoded `Attribute` SEQUENCE.
22021
+ */
22022
+ async function buildSigningCertificateV2Attribute(certDer, hashAlgorithm) {
22023
+ const digestBuffer = await getSubtle().digest(hashAlgorithm, toBuffer(certDer));
22024
+ const certHash = new Uint8Array(digestBuffer);
22025
+ const essCertIdParts = [];
22026
+ if (hashAlgorithm !== "SHA-256") essCertIdParts.push(encodeHashAlgorithmIdentifier(hashNameToOid(hashAlgorithm)));
22027
+ essCertIdParts.push(encodeOctetString(certHash));
22028
+ const signingCertificateV2 = encodeSequence([encodeSequence([encodeSequence(essCertIdParts)])]);
22029
+ return encodeSequence([encodeOID(ID_AA_SIGNING_CERTIFICATE_V2), encodeSet([signingCertificateV2])]);
22030
+ }
22031
+ /**
22032
+ * Best-effort DER scan for the `signing-certificate-v2` attribute inside
22033
+ * an encoded `SignedAttributes` SET (or any SET/SEQUENCE OF Attribute).
22034
+ *
22035
+ * When found, the embedded `certHash` OCTET STRING is returned so callers
22036
+ * can compare it against the signer certificate's digest.
22037
+ *
22038
+ * This walks: SET -> Attribute SEQUENCE { OID, SET { SigningCertificateV2
22039
+ * SEQUENCE { certs SEQUENCE OF { ESSCertIDv2 SEQUENCE { [algId], certHash } } } } }.
22040
+ *
22041
+ * @param signedAttrsDer DER bytes of a SET (or constructed container) of Attributes.
22042
+ * @returns `{ present, certHash? }`.
22043
+ */
22044
+ function extractSigningCertificateV2(signedAttrsDer) {
22045
+ try {
22046
+ const container = parseDerTlv(signedAttrsDer, 0);
22047
+ for (const attr of container.children) {
22048
+ if (attr.tag !== 48 || attr.children.length < 2) continue;
22049
+ const oidNode = attr.children[0];
22050
+ if (oidNode.tag !== 6) continue;
22051
+ if (decodeOidBytes(oidNode.data) !== ID_AA_SIGNING_CERTIFICATE_V2) continue;
22052
+ const signingCertV2 = attr.children[1].children[0];
22053
+ if (!signingCertV2) return {
22054
+ present: true,
22055
+ certHash: void 0
22056
+ };
22057
+ const certsSeqOf = signingCertV2.children[0];
22058
+ if (!certsSeqOf) return {
22059
+ present: true,
22060
+ certHash: void 0
22061
+ };
22062
+ const essCertId = certsSeqOf.children[0];
22063
+ if (!essCertId) return {
22064
+ present: true,
22065
+ certHash: void 0
22066
+ };
22067
+ for (const child of essCertId.children) if (child.tag === 4) return {
22068
+ present: true,
22069
+ certHash: child.data
22070
+ };
22071
+ return {
22072
+ present: true,
22073
+ certHash: void 0
22074
+ };
22075
+ }
22076
+ } catch {}
22077
+ return {
22078
+ present: false,
22079
+ certHash: void 0
22080
+ };
22081
+ }
22082
+ //#endregion
21929
22083
  //#region src/signature/pkcs7.ts
22084
+ /**
22085
+ * @module signature/pkcs7
22086
+ *
22087
+ * PKCS#7 / CMS SignedData structure builder for PDF digital signatures.
22088
+ *
22089
+ * Builds a minimal but valid PKCS#7 SignedData structure using pure
22090
+ * TypeScript ASN.1 DER encoding. Uses the Web Crypto API for
22091
+ * RSASSA-PKCS1-v1_5 or ECDSA signing.
22092
+ *
22093
+ * Structure overview:
22094
+ * ```
22095
+ * ContentInfo {
22096
+ * contentType: signedData (1.2.840.113549.1.7.2)
22097
+ * content: SignedData {
22098
+ * version: 1
22099
+ * digestAlgorithms: { SHA-256 }
22100
+ * encapContentInfo: { data (1.2.840.113549.1.7.1) }
22101
+ * certificates: [0] IMPLICIT { certificate }
22102
+ * signerInfos: {
22103
+ * SignerInfo {
22104
+ * version: 1
22105
+ * issuerAndSerialNumber
22106
+ * digestAlgorithm: SHA-256
22107
+ * signedAttrs: { contentType, signingTime, messageDigest }
22108
+ * signatureAlgorithm
22109
+ * signature
22110
+ * }
22111
+ * }
22112
+ * }
22113
+ * }
22114
+ * ```
22115
+ *
22116
+ * References:
22117
+ * - RFC 5652 (Cryptographic Message Syntax)
22118
+ * - RFC 3161 (Internet X.509 PKI Time-Stamp Protocol)
22119
+ * - PKCS#7 / CMS SignedData
22120
+ *
22121
+ * @packageDocumentation
22122
+ */
21930
22123
  /** OID constants for ASN.1 structures. */
21931
22124
  const OID = {
21932
22125
  signedData: "1.2.840.113549.1.7.2",
@@ -21938,6 +22131,8 @@ const OID = {
21938
22131
  sha256WithRSA: "1.2.840.113549.1.1.11",
21939
22132
  sha384WithRSA: "1.2.840.113549.1.1.12",
21940
22133
  sha512WithRSA: "1.2.840.113549.1.1.13",
22134
+ rsaPss: "1.2.840.113549.1.1.10",
22135
+ mgf1: "1.2.840.113549.1.1.8",
21941
22136
  ecPublicKey: "1.2.840.10045.2.1",
21942
22137
  ecdsaWithSHA256: "1.2.840.10045.4.3.2",
21943
22138
  ecdsaWithSHA384: "1.2.840.10045.4.3.3",
@@ -22188,6 +22383,52 @@ function encodeSignatureAlgorithm(keyAlgo, hashAlgo) {
22188
22383
  throw new Error(`Unsupported key algorithm: ${keyAlgo}`);
22189
22384
  }
22190
22385
  /**
22386
+ * Encode the AlgorithmIdentifier for an RSASSA-PSS signature (RFC 4055 §3.1).
22387
+ *
22388
+ * ```
22389
+ * AlgorithmIdentifier ::= SEQUENCE {
22390
+ * algorithm id-RSASSA-PSS, -- 1.2.840.113549.1.1.10
22391
+ * parameters RSASSA-PSS-params }
22392
+ *
22393
+ * RSASSA-PSS-params ::= SEQUENCE {
22394
+ * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
22395
+ * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
22396
+ * saltLength [2] INTEGER DEFAULT 20,
22397
+ * trailerField [3] INTEGER DEFAULT 1 }
22398
+ * ```
22399
+ *
22400
+ * The `[0]`/`[1]`/`[2]` tags are EXPLICIT (the fields are tagged in the
22401
+ * ASN.1 module without `IMPLICIT`, and the CMS modules import EXPLICIT
22402
+ * tagging by default), so each wraps the full underlying TLV. Per
22403
+ * RFC 4055, when the hash is SHA-256 the hashAlgorithm AlgorithmIdentifier
22404
+ * is `{ id-sha256, NULL }` and the maskGenAlgorithm is
22405
+ * `{ id-mgf1, { id-sha256, NULL } }`. `trailerField` is the default (1)
22406
+ * and is omitted (RFC 4055 mandates generators omit it).
22407
+ *
22408
+ * Salt length equals the hash output length: 32 (SHA-256), 48 (SHA-384),
22409
+ * 64 (SHA-512).
22410
+ */
22411
+ function encodeRsaPssSignatureAlgorithm(hashAlgo) {
22412
+ const hashOid = HASH_OID_MAP[hashAlgo];
22413
+ if (!hashOid) throw new Error(`Unsupported hash for RSA-PSS: ${hashAlgo}`);
22414
+ const saltLength = PSS_SALT_LENGTH[hashAlgo];
22415
+ if (saltLength === void 0) throw new Error(`Unsupported hash for RSA-PSS: ${hashAlgo}`);
22416
+ const hashAlgId = encodeSequence([encodeOID(hashOid), encodeTlv(TAG.NULL, /* @__PURE__ */ new Uint8Array(0))]);
22417
+ const mgfAlgId = encodeSequence([encodeOID(OID.mgf1), hashAlgId]);
22418
+ const params = encodeSequence([
22419
+ encodeContextTag(0, hashAlgId),
22420
+ encodeContextTag(1, mgfAlgId),
22421
+ encodeContextTag(2, encodeIntegerValue(saltLength))
22422
+ ]);
22423
+ return encodeSequence([encodeOID(OID.rsaPss), params]);
22424
+ }
22425
+ /** PSS salt length (= hash output length in bytes) per hash algorithm. */
22426
+ const PSS_SALT_LENGTH = {
22427
+ "SHA-256": 32,
22428
+ "SHA-384": 48,
22429
+ "SHA-512": 64
22430
+ };
22431
+ /**
22191
22432
  * Parse a single DER TLV from a byte array at the given offset.
22192
22433
  */
22193
22434
  function parseDerTlv(data, offset) {
@@ -22351,11 +22592,11 @@ function getSubtle() {
22351
22592
  /**
22352
22593
  * Import a PKCS#8 private key for signing.
22353
22594
  */
22354
- async function importPrivateKey(pkcs8Der, keyAlgorithm, hashAlgorithm, namedCurve) {
22595
+ async function importPrivateKey(pkcs8Der, keyAlgorithm, hashAlgorithm, namedCurve, rsaScheme = "pkcs1v15") {
22355
22596
  const subtle = getSubtle();
22356
22597
  let algorithm;
22357
22598
  if (keyAlgorithm === "RSA") algorithm = {
22358
- name: "RSASSA-PKCS1-v1_5",
22599
+ name: rsaScheme === "pss" ? "RSA-PSS" : "RSASSA-PKCS1-v1_5",
22359
22600
  hash: hashAlgorithm
22360
22601
  };
22361
22602
  else algorithm = {
@@ -22367,10 +22608,17 @@ async function importPrivateKey(pkcs8Der, keyAlgorithm, hashAlgorithm, namedCurv
22367
22608
  /**
22368
22609
  * Sign data using the imported private key.
22369
22610
  */
22370
- async function signData(key, data, keyAlgorithm, hashAlgorithm) {
22611
+ async function signData(key, data, keyAlgorithm, hashAlgorithm, rsaScheme = "pkcs1v15") {
22371
22612
  const subtle = getSubtle();
22372
22613
  let algorithm;
22373
- if (keyAlgorithm === "RSA") algorithm = { name: "RSASSA-PKCS1-v1_5" };
22614
+ if (keyAlgorithm === "RSA") if (rsaScheme === "pss") {
22615
+ const saltLength = PSS_SALT_LENGTH[hashAlgorithm];
22616
+ if (saltLength === void 0) throw new Error(`Unsupported hash for RSA-PSS: ${hashAlgorithm}`);
22617
+ algorithm = {
22618
+ name: "RSA-PSS",
22619
+ saltLength
22620
+ };
22621
+ } else algorithm = { name: "RSASSA-PKCS1-v1_5" };
22374
22622
  else algorithm = {
22375
22623
  name: "ECDSA",
22376
22624
  hash: hashAlgorithm
@@ -22394,11 +22642,12 @@ async function buildPkcs7Signature(dataHash, options) {
22394
22642
  const hashAlgorithm = signerInfoOpts.hashAlgorithm;
22395
22643
  const keyAlgo = detectKeyAlgorithm(signerInfoOpts.certificate);
22396
22644
  const namedCurve = keyAlgo === "EC" ? detectNamedCurve(signerInfoOpts.certificate) : void 0;
22645
+ const rsaScheme = keyAlgo === "RSA" && signerInfoOpts.signatureScheme === "pss" ? "pss" : "pkcs1v15";
22397
22646
  const { issuerDer, serialDer } = extractIssuerAndSerial(signerInfoOpts.certificate);
22398
- const privateKey = await importPrivateKey(signerInfoOpts.privateKey, keyAlgo, hashAlgorithm, namedCurve);
22399
- const signedAttrs = buildSignedAttributes(dataHash, hashAlgorithm, options.signingDate ?? /* @__PURE__ */ new Date());
22400
- const signatureValue = await signData(privateKey, encodeSet(signedAttrs), keyAlgo, hashAlgorithm);
22401
- const signerInfoValue = buildSignerInfo(issuerDer, serialDer, hashAlgorithm, keyAlgo, signedAttrs, keyAlgo === "EC" ? convertEcdsaToDer(signatureValue) : signatureValue);
22647
+ const privateKey = await importPrivateKey(signerInfoOpts.privateKey, keyAlgo, hashAlgorithm, namedCurve, rsaScheme);
22648
+ const signedAttrs = await buildSignedAttributes(dataHash, hashAlgorithm, options.signingDate ?? /* @__PURE__ */ new Date(), options.cades === true ? signerInfoOpts.certificate : void 0);
22649
+ const signatureValue = await signData(privateKey, encodeSet(signedAttrs), keyAlgo, hashAlgorithm, rsaScheme);
22650
+ const signerInfoValue = buildSignerInfo(issuerDer, serialDer, hashAlgorithm, keyAlgo, signedAttrs, keyAlgo === "EC" ? convertEcdsaToDer(signatureValue) : signatureValue, rsaScheme);
22402
22651
  const signedData = buildSignedData(hashAlgorithm, signerInfoOpts.certificate, signerInfoValue);
22403
22652
  return encodeSequence([encodeOID(OID.signedData), encodeContextTag(0, signedData)]);
22404
22653
  }
@@ -22409,24 +22658,61 @@ async function buildPkcs7Signature(dataHash, options) {
22409
22658
  * 1. contentType (data)
22410
22659
  * 2. signingTime
22411
22660
  * 3. messageDigest (the hash of the PDF content)
22412
- */
22413
- function buildSignedAttributes(dataHash, _hashAlgorithm, signingTime) {
22414
- return [
22415
- encodeSequence([encodeOID(OID.contentType), encodeSet([encodeOID(OID.data)])]),
22416
- encodeSequence([encodeOID(OID.signingTime), encodeSet([encodeUTCTime(signingTime)])]),
22417
- encodeSequence([encodeOID(OID.messageDigest), encodeSet([encodeOctetString(dataHash)])])
22661
+ *
22662
+ * When `cadesCertDer` is provided, the ESS `signing-certificate-v2`
22663
+ * attribute (RFC 5035) is added and the whole SET OF is re-sorted into
22664
+ * DER order (X.690 §11.6) so the resulting SignedAttributes encoding is
22665
+ * valid. When omitted, the original three attributes are returned in
22666
+ * their original order so the output stays byte-identical to prior
22667
+ * versions.
22668
+ */
22669
+ async function buildSignedAttributes(dataHash, _hashAlgorithm, signingTime, cadesCertDer) {
22670
+ const contentTypeAttr = encodeSequence([encodeOID(OID.contentType), encodeSet([encodeOID(OID.data)])]);
22671
+ const signingTimeAttr = encodeSequence([encodeOID(OID.signingTime), encodeSet([encodeUTCTime(signingTime)])]);
22672
+ const messageDigestAttr = encodeSequence([encodeOID(OID.messageDigest), encodeSet([encodeOctetString(dataHash)])]);
22673
+ if (cadesCertDer === void 0) return [
22674
+ contentTypeAttr,
22675
+ signingTimeAttr,
22676
+ messageDigestAttr
22418
22677
  ];
22678
+ return sortDerSetMembers([
22679
+ contentTypeAttr,
22680
+ signingTimeAttr,
22681
+ messageDigestAttr,
22682
+ await buildSigningCertificateV2Attribute(cadesCertDer, _hashAlgorithm)
22683
+ ]);
22684
+ }
22685
+ /**
22686
+ * Sort the members of a SET OF into DER canonical order (X.690 §11.6):
22687
+ * by ascending lexicographic comparison of their complete DER encodings,
22688
+ * padding the shorter encoding with conceptual trailing zero octets.
22689
+ */
22690
+ function sortDerSetMembers(members) {
22691
+ return [...members].sort(compareDerEncodings);
22692
+ }
22693
+ /**
22694
+ * Compare two DER encodings as unsigned octet strings, treating a
22695
+ * shorter array as if padded with trailing zero octets (X.690 §11.6).
22696
+ */
22697
+ function compareDerEncodings(a, b) {
22698
+ const len = Math.max(a.length, b.length);
22699
+ for (let i = 0; i < len; i++) {
22700
+ const av = a[i] ?? 0;
22701
+ const bv = b[i] ?? 0;
22702
+ if (av !== bv) return av - bv;
22703
+ }
22704
+ return 0;
22419
22705
  }
22420
22706
  /**
22421
22707
  * Build a SignerInfo SEQUENCE.
22422
22708
  */
22423
- function buildSignerInfo(issuerDer, serialDer, hashAlgorithm, keyAlgorithm, signedAttrs, signatureValue) {
22709
+ function buildSignerInfo(issuerDer, serialDer, hashAlgorithm, keyAlgorithm, signedAttrs, signatureValue, rsaScheme = "pkcs1v15") {
22424
22710
  return encodeSequence([
22425
22711
  encodeIntegerValue(1),
22426
22712
  encodeSequence([issuerDer, serialDer]),
22427
22713
  encodeDigestAlgorithm(hashAlgorithm),
22428
22714
  encodeContextTag(0, concat(...signedAttrs)),
22429
- encodeSignatureAlgorithm(keyAlgorithm, hashAlgorithm),
22715
+ keyAlgorithm === "RSA" && rsaScheme === "pss" ? encodeRsaPssSignatureAlgorithm(hashAlgorithm) : encodeSignatureAlgorithm(keyAlgorithm, hashAlgorithm),
22430
22716
  encodeOctetString(signatureValue)
22431
22717
  ]);
22432
22718
  }
@@ -22725,6 +23011,9 @@ function parsePkcs7Structure(pkcs7Bytes) {
22725
23011
  signedAttrsRaw = encodeSet(signedAttrs);
22726
23012
  idx++;
22727
23013
  }
23014
+ let signatureAlgorithmOid = "";
23015
+ const sigAlgoNode = signerInfo.children[idx];
23016
+ if (sigAlgoNode && sigAlgoNode.children.length > 0) signatureAlgorithmOid = decodeOidBytes(sigAlgoNode.children[0].data);
22728
23017
  idx++;
22729
23018
  const signatureNode = signerInfo.children[idx];
22730
23019
  const signatureValue = signatureNode ? signatureNode.data : /* @__PURE__ */ new Uint8Array(0);
@@ -22733,7 +23022,8 @@ function parsePkcs7Structure(pkcs7Bytes) {
22733
23022
  signedAttrs,
22734
23023
  signedAttrsRaw,
22735
23024
  signatureValue,
22736
- digestAlgorithm
23025
+ digestAlgorithm,
23026
+ signatureAlgorithmOid
22737
23027
  };
22738
23028
  } catch {
22739
23029
  return null;
@@ -22881,6 +23171,23 @@ async function verifySignatures(pdfBytes) {
22881
23171
  } catch {
22882
23172
  certificateValid = false;
22883
23173
  }
23174
+ let cadesSigningCertPresent;
23175
+ let cadesSigningCertHashValid;
23176
+ try {
23177
+ const ess = extractSigningCertificateV2(parsed.signedAttrsRaw);
23178
+ cadesSigningCertPresent = ess.present;
23179
+ if (ess.present && ess.certHash) {
23180
+ const algo = {
23181
+ 32: "SHA-256",
23182
+ 48: "SHA-384",
23183
+ 64: "SHA-512"
23184
+ }[ess.certHash.length];
23185
+ if (algo) {
23186
+ const digest = new Uint8Array(await getSubtle().digest(algo, toBuffer(parsed.certificate)));
23187
+ cadesSigningCertHashValid = digest.length === ess.certHash.length && digest.every((b, i) => b === ess.certHash[i]);
23188
+ }
23189
+ }
23190
+ } catch {}
22884
23191
  results.push({
22885
23192
  fieldName: fieldInfo.fieldName,
22886
23193
  signedBy,
@@ -22888,7 +23195,9 @@ async function verifySignatures(pdfBytes) {
22888
23195
  integrityValid,
22889
23196
  certificateValid,
22890
23197
  signingDate,
22891
- reason: fieldInfo.reason
23198
+ reason: fieldInfo.reason,
23199
+ cadesSigningCertPresent,
23200
+ cadesSigningCertHashValid
22892
23201
  });
22893
23202
  }
22894
23203
  return results;
@@ -22911,17 +23220,33 @@ async function verifySignature(pdfBytes, byteRange, signatureBytes, certificateB
22911
23220
  if (!parsed) return false;
22912
23221
  const subtle = getSubtle();
22913
23222
  const keyAlgo = detectKeyAlgorithm(certificateBytes);
23223
+ const isPss = parsed.signatureAlgorithmOid === "1.2.840.113549.1.1.10";
23224
+ const PSS_SALT_LENGTH = {
23225
+ "SHA-256": 32,
23226
+ "SHA-384": 48,
23227
+ "SHA-512": 64
23228
+ };
22914
23229
  const spki = extractSubjectPublicKeyInfo(certificateBytes);
22915
23230
  let importAlgo;
22916
23231
  let verifyAlgo;
22917
23232
  let sigBytes = parsed.signatureValue;
22918
- if (keyAlgo === "RSA") {
23233
+ if (keyAlgo === "RSA") if (isPss) {
23234
+ importAlgo = {
23235
+ name: "RSA-PSS",
23236
+ hash: parsed.digestAlgorithm
23237
+ };
23238
+ verifyAlgo = {
23239
+ name: "RSA-PSS",
23240
+ saltLength: PSS_SALT_LENGTH[parsed.digestAlgorithm] ?? 32
23241
+ };
23242
+ } else {
22919
23243
  importAlgo = {
22920
23244
  name: "RSASSA-PKCS1-v1_5",
22921
23245
  hash: parsed.digestAlgorithm
22922
23246
  };
22923
23247
  verifyAlgo = { name: "RSASSA-PKCS1-v1_5" };
22924
- } else {
23248
+ }
23249
+ else {
22925
23250
  const namedCurve = detectNamedCurve(certificateBytes);
22926
23251
  importAlgo = {
22927
23252
  name: "ECDSA",
@@ -25659,6 +25984,6 @@ function createPdf() {
25659
25984
  return new PdfDocument();
25660
25985
  }
25661
25986
  //#endregion
25662
- export { PdfOutlineTree as $, deviceNColor as $n, setCharacterSpacing as $r, getRedactionMarks as $t, encodeUTCTime as A, endArtifact as An, curveToFinal as Ar, pngEmbed_exports as At, prepareForSigning as B, rotationMatrix as Bn, rectangle as Br, PageSizes as Bt, encodeInteger as C, pdfCatalog_exports as Cn, clip as Cr, parseTiffIfd as Ct, encodePrintableString as D, beginMarkedContentSequence as Dn, closeFillEvenOddAndStroke as Dr, detectImageFormat as Dt, encodeOctetString as E, beginMarkedContent as En, closeFillAndStroke as Er, isWebPLossless as Et, parseDerTlv as F, degreesToRadians as Fn, fillAndStroke as Fr, extractMetrics as Ft, isAccessible as G, translate as Gn, setLineWidth as Gr, encodeQrCode as Gt, mergePdfs as H, scale as Hn, setFlatness as Hr, wrapText as Ht, toBuffer as I, radians as In, fillEvenOdd as Ir, PdfStreamWriter as It, PdfStructureTree as J, cmyk as Jn, beginText as Jr, buildPatternObjects as Jt, summarizeIssues as K, applyFillColor as Kn, setMiterLimit as Kr, qrCodeToOperators as Kt, computeSignatureHash as L, radiansToDegrees as Ln, fillEvenOddAndStroke as Lr, PdfWriter as Lt, extractIssuerAndSerial as M, wrapInMarkedContent as Mn, ellipsePath as Mr, isTrueType as Mt, extractSubjectPublicKeyInfo as N, concatMatrix as Nn, endPath as Nr, EmbeddedFont as Nt, encodeSequence as O, beginMarkedContentWithProperties as On, closePath as Or, getImageFormatName as Ot, getSubtle as P, degrees as Pn, fill as Pr, fontSubset_exports as Pt, PdfOutlineItem as Q, componentsToColor as Qn, nextLine as Qr, applyRedactions as Qt, embedSignature as R, restoreState as Rn, lineTo as Rr, serializePdf as Rt, encodeContextTag as S, formatPdfDate$1 as Sn, circlePath as Sr, isTiff as St, encodeOID as T, beginArtifactWithType as Tn, closeAndStroke as Tr, isWebP as Tt, splitPdf as U, setGraphicsState as Un, setLineCap as Ur, renderMultiPageTable as Ut, copyPages as V, saveState as Vn, setDashPattern as Vr, PdfPage as Vt, checkAccessibility as W, skew as Wn, setLineJoin as Wr, renderTable as Wt, buildViewerPreferencesDict as X, colorToComponents as Xn, moveText as Xr, radialGradient as Xt, PdfViewerPreferences as Y, cmykToRgb as Yn, endText as Yr, linearGradient as Yt, parseViewerPreferences as Z, colorToHex as Zn, moveTextSetLeading as Zr, tilingPattern as Zt, signPdf as _, createAnnotation as _n, spotColor as _r, formatHexContext as _t, getPageLabels as a, setTextRise as ai, drawSvgOnPage as an, setColorSpace as ar, sha256 as at, detectKeyAlgorithm as b, buildInfoDict as bn, drawImageXObject as br, decodeTiffPage as bt, embedPageAsFormXObject as c, showTextArray as ci, interpolateLinearRgb as cn, setFillColorGray as cr, decodePermissions as ct, attachFile as d, showTextWithSpacing as di, parseSvgPath as dn, setStrokeColor as dr, aesEncryptCBC as dt, setFont as ei, markForRedaction as en, deviceNResourceName as er, loadPdf as et, buildEmbeddedFilesNameTree as f, parseSvgTransform as fn, setStrokeColorCmyk as fr, rc4 as ft, getSignatures as g, buildAnnotationDict as gn, setStrokingColor as gr, PdfParseError as gt, verifySignatures as h, annotationFromDict as hn, setStrokeColorSpace as hr, base64Encode as ht, PdfPluginManager as i, setTextRenderingMode as ii, endLayerContent as in, rgbToCmyk as ir, verifyUserPassword as it, encodeUtf8String as j, endMarkedContent as jn, curveToInitial as jr, isOpenTypeCFF as jt, encodeSet as k, createMarkedContentScope as kn, curveTo as kr, getSupportedFormats as kt, addWatermark as l, showTextHex as li, parseSvg as ln, setFillColorRgb as lr, encodePermissions as lt, verifySignature as m, PdfAnnotation as mn, setStrokeColorRgb as mr, base64Decode as mt, StandardFonts as n, setLeading as ni, PdfLayerManager as nn, hexToColor as nr, computeFileEncryptionKey as nt, removePageLabels as o, setWordSpacing as oi, svgToPdfOperators as on, setFillColor as or, sha384 as ot, getAttachments as p, AnnotationFlags as pn, setStrokeColorGray as pr, md5 as pt, PdfStructureElement as q, applyStrokeColor as qn, stroke as qr, buildGradientObjects as qt, createPdf as r, setTextMatrix as ri, beginLayerContent as rn, rgb as rr, verifyOwnerPassword as rt, setPageLabels as s, showText as si, applySpreadMethod as sn, setFillColorCmyk as sr, sha512 as st, PdfDocument as t, setFontSize as ti, PdfLayer as tn, grayscale as tr, PdfEncryptionHandler as tt, addWatermarkToPage as u, showTextNextLine as ui, parseSvgColor as un, setFillingColor as ur, aesDecryptCBC as ut, buildPkcs7Signature as v, buildCatalog as vn, spotResourceName as vr, decodeTiff as vt, encodeLength as w, beginArtifact as wn, clipEvenOdd as wr, decodeWebP as wt, detectNamedCurve as x, buildPageTree as xn, drawXObject as xr, getTiffPageCount as xt, decodeOidBytes as y, buildDocumentStructure as yn, drawImageWithMatrix as yr, decodeTiffAll as yt, findSignatures as z, rotate as zn, moveTo as zr, libdeflateWasm_exports as zt };
25987
+ export { parseViewerPreferences as $, colorToHex as $n, moveTextSetLeading as $r, tilingPattern as $t, encodeUTCTime as A, beginMarkedContentWithProperties as An, closePath as Ar, getImageFormatName as At, embedSignature as B, restoreState as Bn, lineTo as Br, serializePdf as Bt, encodeInteger as C, buildPageTree as Cn, drawXObject as Cr, getTiffPageCount as Ct, encodePrintableString as D, beginArtifactWithType as Dn, closeAndStroke as Dr, isWebP as Dt, encodeOctetString as E, beginArtifact as En, clipEvenOdd as Er, decodeWebP as Et, parseDerTlv as F, concatMatrix as Fn, endPath as Fr, EmbeddedFont as Ft, splitPdf as G, setGraphicsState as Gn, setLineCap as Gr, renderMultiPageTable as Gt, prepareForSigning as H, rotationMatrix as Hn, rectangle as Hr, PageSizes as Ht, toBuffer as I, degrees as In, fill as Ir, fontSubset_exports as It, summarizeIssues as J, applyFillColor as Jn, setMiterLimit as Jr, qrCodeToOperators as Jt, checkAccessibility as K, skew as Kn, setLineJoin as Kr, renderTable as Kt, buildSigningCertificateV2Attribute as L, degreesToRadians as Ln, fillAndStroke as Lr, extractMetrics as Lt, extractIssuerAndSerial as M, endArtifact as Mn, curveToFinal as Mr, pngEmbed_exports as Mt, extractSubjectPublicKeyInfo as N, endMarkedContent as Nn, curveToInitial as Nr, isOpenTypeCFF as Nt, encodeSequence as O, beginMarkedContent as On, closeFillAndStroke as Or, isWebPLossless as Ot, getSubtle as P, wrapInMarkedContent as Pn, ellipsePath as Pr, isTrueType as Pt, buildViewerPreferencesDict as Q, colorToComponents as Qn, moveText as Qr, radialGradient as Qt, extractSigningCertificateV2 as R, radians as Rn, fillEvenOdd as Rr, PdfStreamWriter as Rt, encodeContextTag as S, buildInfoDict as Sn, drawImageXObject as Sr, decodeTiffPage as St, encodeOID as T, pdfCatalog_exports as Tn, clip as Tr, parseTiffIfd as Tt, copyPages as U, saveState as Un, setDashPattern as Ur, PdfPage as Ut, findSignatures as V, rotate as Vn, moveTo as Vr, libdeflateWasm_exports as Vt, mergePdfs as W, scale as Wn, setFlatness as Wr, wrapText as Wt, PdfStructureTree as X, cmyk as Xn, beginText as Xr, buildPatternObjects as Xt, PdfStructureElement as Y, applyStrokeColor as Yn, stroke as Yr, buildGradientObjects as Yt, PdfViewerPreferences as Z, cmykToRgb as Zn, endText as Zr, linearGradient as Zt, signPdf as _, annotationFromDict as _n, setStrokeColorSpace as _r, base64Encode as _t, getPageLabels as a, setTextMatrix as ai, beginLayerContent as an, rgb as ar, verifyOwnerPassword as at, detectKeyAlgorithm as b, buildCatalog as bn, spotResourceName as br, decodeTiff as bt, embedPageAsFormXObject as c, setWordSpacing as ci, svgToPdfOperators as cn, setFillColor as cr, sha384 as ct, attachFile as d, showTextHex as di, parseSvg as dn, setFillColorRgb as dr, encodePermissions as dt, nextLine as ei, applyRedactions as en, componentsToColor as er, PdfOutlineItem as et, buildEmbeddedFilesNameTree as f, showTextNextLine as fi, parseSvgColor as fn, setFillingColor as fr, aesDecryptCBC as ft, getSignatures as g, PdfAnnotation as gn, setStrokeColorRgb as gr, base64Decode as gt, verifySignatures as h, AnnotationFlags as hn, setStrokeColorGray as hr, md5 as ht, PdfPluginManager as i, setLeading as ii, PdfLayerManager as in, hexToColor as ir, computeFileEncryptionKey as it, encodeUtf8String as j, createMarkedContentScope as jn, curveTo as jr, getSupportedFormats as jt, encodeSet as k, beginMarkedContentSequence as kn, closeFillEvenOddAndStroke as kr, detectImageFormat as kt, addWatermark as l, showText as li, applySpreadMethod as ln, setFillColorCmyk as lr, sha512 as lt, verifySignature as m, parseSvgTransform as mn, setStrokeColorCmyk as mr, rc4 as mt, StandardFonts as n, setFont as ni, markForRedaction as nn, deviceNResourceName as nr, loadPdf as nt, removePageLabels as o, setTextRenderingMode as oi, endLayerContent as on, rgbToCmyk as or, verifyUserPassword as ot, getAttachments as p, showTextWithSpacing as pi, parseSvgPath as pn, setStrokeColor as pr, aesEncryptCBC as pt, isAccessible as q, translate as qn, setLineWidth as qr, encodeQrCode as qt, createPdf as r, setFontSize as ri, PdfLayer as rn, grayscale as rr, PdfEncryptionHandler as rt, setPageLabels as s, setTextRise as si, drawSvgOnPage as sn, setColorSpace as sr, sha256 as st, PdfDocument as t, setCharacterSpacing as ti, getRedactionMarks as tn, deviceNColor as tr, PdfOutlineTree as tt, addWatermarkToPage as u, showTextArray as ui, interpolateLinearRgb as un, setFillColorGray as ur, decodePermissions as ut, buildPkcs7Signature as v, buildAnnotationDict as vn, setStrokingColor as vr, PdfParseError as vt, encodeLength as w, formatPdfDate$1 as wn, circlePath as wr, isTiff as wt, detectNamedCurve as x, buildDocumentStructure as xn, drawImageWithMatrix as xr, decodeTiffAll as xt, decodeOidBytes as y, createAnnotation as yn, spotColor as yr, formatHexContext as yt, computeSignatureHash as z, radiansToDegrees as zn, fillEvenOddAndStroke as zr, PdfWriter as zt };
25663
25988
 
25664
- //# sourceMappingURL=pdfDocument-Cgkkk8F8.mjs.map
25989
+ //# sourceMappingURL=pdfDocument-EcHxUnR6.mjs.map