modern-pdf-lib 0.33.0 → 0.35.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 +10 -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-BqYQ9lsY.d.cts → index-CIdDdXlK.d.cts} +318 -45
  19. package/dist/index-CIdDdXlK.d.cts.map +1 -0
  20. package/dist/{index-BJtSRrMf.d.mts → index-CwgepM_G.d.mts} +318 -45
  21. package/dist/index-CwgepM_G.d.mts.map +1 -0
  22. package/dist/index.cjs +10 -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-xOcesNCh.mjs → layout-BZ9InKTl.mjs} +2 -2
  27. package/dist/{layout-BYXpcYtC.cjs → layout-DvciSXsr.cjs} +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-D5qz7duP.cjs} +376 -21
  37. package/dist/{pdfDocument-Cgkkk8F8.mjs → pdfDocument-Q0wrwKEZ.mjs} +347 -22
  38. package/dist/{src-zeRl33xQ.mjs → src-BlUlmYsU.mjs} +1300 -25
  39. package/dist/{src-BdVnpRoy.cjs → src-C-mBizNU.cjs} +1327 -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",
@@ -25707,6 +26032,18 @@ Object.defineProperty(exports, "PdfLayerManager", {
25707
26032
  return PdfLayerManager;
25708
26033
  }
25709
26034
  });
26035
+ Object.defineProperty(exports, "PdfLexer", {
26036
+ enumerable: true,
26037
+ get: function() {
26038
+ return PdfLexer;
26039
+ }
26040
+ });
26041
+ Object.defineProperty(exports, "PdfObjectParser", {
26042
+ enumerable: true,
26043
+ get: function() {
26044
+ return PdfObjectParser;
26045
+ }
26046
+ });
25710
26047
  Object.defineProperty(exports, "PdfOutlineItem", {
25711
26048
  enumerable: true,
25712
26049
  get: function() {
@@ -25773,6 +26110,12 @@ Object.defineProperty(exports, "StandardFonts", {
25773
26110
  return StandardFonts;
25774
26111
  }
25775
26112
  });
26113
+ Object.defineProperty(exports, "XrefParser", {
26114
+ enumerable: true,
26115
+ get: function() {
26116
+ return XrefParser;
26117
+ }
26118
+ });
25776
26119
  Object.defineProperty(exports, "addWatermark", {
25777
26120
  enumerable: true,
25778
26121
  get: function() {
@@ -25941,6 +26284,12 @@ Object.defineProperty(exports, "buildPkcs7Signature", {
25941
26284
  return buildPkcs7Signature;
25942
26285
  }
25943
26286
  });
26287
+ Object.defineProperty(exports, "buildSigningCertificateV2Attribute", {
26288
+ enumerable: true,
26289
+ get: function() {
26290
+ return buildSigningCertificateV2Attribute;
26291
+ }
26292
+ });
25944
26293
  Object.defineProperty(exports, "buildViewerPreferencesDict", {
25945
26294
  enumerable: true,
25946
26295
  get: function() {
@@ -26319,6 +26668,12 @@ Object.defineProperty(exports, "extractMetrics", {
26319
26668
  return extractMetrics;
26320
26669
  }
26321
26670
  });
26671
+ Object.defineProperty(exports, "extractSigningCertificateV2", {
26672
+ enumerable: true,
26673
+ get: function() {
26674
+ return extractSigningCertificateV2;
26675
+ }
26676
+ });
26322
26677
  Object.defineProperty(exports, "extractSubjectPublicKeyInfo", {
26323
26678
  enumerable: true,
26324
26679
  get: function() {
@@ -27022,4 +27377,4 @@ Object.defineProperty(exports, "wrapText", {
27022
27377
  }
27023
27378
  });
27024
27379
 
27025
- //# sourceMappingURL=pdfDocument-Bh4ebDqE.cjs.map
27380
+ //# sourceMappingURL=pdfDocument-D5qz7duP.cjs.map