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.
- package/README.md +3 -3
- package/dist/browser.cjs +10 -3
- package/dist/browser.d.cts +5 -5
- package/dist/browser.d.mts +5 -5
- package/dist/browser.mjs +4 -4
- package/dist/{compressionAnalysis-0m5jJG1_.d.mts → compressionAnalysis-4EW8MJBa.d.mts} +2 -2
- package/dist/{compressionAnalysis-0m5jJG1_.d.mts.map → compressionAnalysis-4EW8MJBa.d.mts.map} +1 -1
- package/dist/{compressionAnalysis-CSBcmi0_.d.cts → compressionAnalysis-Cz3yWa-O.d.cts} +2 -2
- package/dist/{compressionAnalysis-CSBcmi0_.d.cts.map → compressionAnalysis-Cz3yWa-O.d.cts.map} +1 -1
- package/dist/create.cjs +2 -2
- package/dist/create.d.cts +2 -2
- package/dist/create.d.mts +2 -2
- package/dist/create.mjs +2 -2
- package/dist/{fontEmbed-Bzv89wgp.d.mts → fontEmbed-CTTeV1mZ.d.mts} +2 -2
- package/dist/{fontEmbed-Bzv89wgp.d.mts.map → fontEmbed-CTTeV1mZ.d.mts.map} +1 -1
- package/dist/{fontEmbed-Dwl1XeEA.d.cts → fontEmbed-DxvWoqOt.d.cts} +2 -2
- package/dist/{fontEmbed-Dwl1XeEA.d.cts.map → fontEmbed-DxvWoqOt.d.cts.map} +1 -1
- package/dist/{index-BqYQ9lsY.d.cts → index-CIdDdXlK.d.cts} +318 -45
- package/dist/index-CIdDdXlK.d.cts.map +1 -0
- package/dist/{index-BJtSRrMf.d.mts → index-CwgepM_G.d.mts} +318 -45
- package/dist/index-CwgepM_G.d.mts.map +1 -0
- package/dist/index.cjs +10 -3
- package/dist/index.d.cts +5 -5
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +4 -4
- package/dist/{layout-xOcesNCh.mjs → layout-BZ9InKTl.mjs} +2 -2
- package/dist/{layout-BYXpcYtC.cjs → layout-DvciSXsr.cjs} +2 -2
- package/dist/parse.cjs +1 -1
- package/dist/parse.d.cts +2 -2
- package/dist/parse.d.mts +2 -2
- package/dist/parse.mjs +1 -1
- package/dist/{pdfDocument-B8tQcZqj.d.cts → pdfDocument-BX5o5hI7.d.cts} +13 -1
- package/dist/{pdfDocument-B-8iPl_j.d.mts.map → pdfDocument-BX5o5hI7.d.cts.map} +1 -1
- package/dist/{pdfDocument-B-8iPl_j.d.mts → pdfDocument-C7TItmPQ.d.mts} +13 -1
- package/dist/{pdfDocument-B8tQcZqj.d.cts.map → pdfDocument-C7TItmPQ.d.mts.map} +1 -1
- package/dist/{pdfDocument-Bh4ebDqE.cjs → pdfDocument-D5qz7duP.cjs} +376 -21
- package/dist/{pdfDocument-Cgkkk8F8.mjs → pdfDocument-Q0wrwKEZ.mjs} +347 -22
- package/dist/{src-zeRl33xQ.mjs → src-BlUlmYsU.mjs} +1300 -25
- package/dist/{src-BdVnpRoy.cjs → src-C-mBizNU.cjs} +1327 -22
- package/package.json +1 -1
- package/dist/index-BJtSRrMf.d.mts.map +0 -1
- 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")
|
|
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
|
-
|
|
22414
|
-
|
|
22415
|
-
|
|
22416
|
-
|
|
22417
|
-
|
|
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
|
-
}
|
|
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 {
|
|
25987
|
+
export { parseViewerPreferences as $, cmyk as $n, beginText as $r, buildPatternObjects as $t, encodeUTCTime as A, beginArtifactWithType as An, closeAndStroke as Ar, isWebP as At, embedSignature as B, degreesToRadians as Bn, fillAndStroke as Br, extractMetrics as Bt, encodeInteger as C, buildCatalog as Cn, spotResourceName as Cr, decodeTiff as Ct, encodePrintableString as D, formatPdfDate$1 as Dn, circlePath as Dr, isTiff as Dt, encodeOctetString as E, buildPageTree as En, drawXObject as Er, getTiffPageCount as Et, parseDerTlv as F, endArtifact as Fn, curveToFinal as Fr, pngEmbed_exports as Ft, splitPdf as G, rotationMatrix as Gn, rectangle as Gr, PageSizes as Gt, prepareForSigning as H, radiansToDegrees as Hn, fillEvenOddAndStroke as Hr, PdfWriter as Ht, toBuffer as I, endMarkedContent as In, curveToInitial as Ir, isOpenTypeCFF as It, summarizeIssues as J, setGraphicsState as Jn, setLineCap as Jr, renderMultiPageTable as Jt, checkAccessibility as K, saveState as Kn, setDashPattern as Kr, PdfPage as Kt, buildSigningCertificateV2Attribute as L, wrapInMarkedContent as Ln, ellipsePath as Lr, isTrueType as Lt, extractIssuerAndSerial as M, beginMarkedContentSequence as Mn, closeFillEvenOddAndStroke as Mr, detectImageFormat as Mt, extractSubjectPublicKeyInfo as N, beginMarkedContentWithProperties as Nn, closePath as Nr, getImageFormatName as Nt, encodeSequence as O, pdfCatalog_exports as On, clip as Or, parseTiffIfd as Ot, getSubtle as P, createMarkedContentScope as Pn, curveTo as Pr, getSupportedFormats as Pt, buildViewerPreferencesDict as Q, applyStrokeColor as Qn, stroke as Qr, buildGradientObjects as Qt, extractSigningCertificateV2 as R, concatMatrix as Rn, endPath as Rr, EmbeddedFont as Rt, encodeContextTag as S, createAnnotation as Sn, spotColor as Sr, formatHexContext as St, encodeOID as T, buildInfoDict as Tn, drawImageXObject as Tr, decodeTiffPage as Tt, copyPages as U, restoreState as Un, lineTo as Ur, serializePdf as Ut, findSignatures as V, radians as Vn, fillEvenOdd as Vr, PdfStreamWriter as Vt, mergePdfs as W, rotate as Wn, moveTo as Wr, libdeflateWasm_exports as Wt, PdfStructureTree as X, translate as Xn, setLineWidth as Xr, encodeQrCode as Xt, PdfStructureElement as Y, skew as Yn, setLineJoin as Yr, renderTable as Yt, PdfViewerPreferences as Z, applyFillColor as Zn, setMiterLimit as Zr, qrCodeToOperators as Zt, signPdf as _, parseSvgTransform as _n, setStrokeColorCmyk as _r, base64Encode as _t, getPageLabels as a, setFont as ai, markForRedaction as an, deviceNResourceName as ar, verifyOwnerPassword as at, detectKeyAlgorithm as b, annotationFromDict as bn, setStrokeColorSpace as br, PdfLexer as bt, embedPageAsFormXObject as c, setTextMatrix as ci, beginLayerContent as cn, rgb as cr, sha384 as ct, attachFile as d, setWordSpacing as di, svgToPdfOperators as dn, setFillColor as dr, encodePermissions as dt, endText as ei, linearGradient as en, cmykToRgb as er, PdfOutlineItem as et, buildEmbeddedFilesNameTree as f, showText as fi, applySpreadMethod as fn, setFillColorCmyk as fr, aesDecryptCBC as ft, getSignatures as g, showTextWithSpacing as gi, parseSvgPath as gn, setStrokeColor as gr, base64Decode as gt, verifySignatures as h, showTextNextLine as hi, parseSvgColor as hn, setFillingColor as hr, md5 as ht, PdfPluginManager as i, setCharacterSpacing as ii, getRedactionMarks as in, deviceNColor as ir, computeFileEncryptionKey as it, encodeUtf8String as j, beginMarkedContent as jn, closeFillAndStroke as jr, isWebPLossless as jt, encodeSet as k, beginArtifact as kn, clipEvenOdd as kr, decodeWebP as kt, addWatermark as l, setTextRenderingMode as li, endLayerContent as ln, rgbToCmyk as lr, sha512 as lt, verifySignature as m, showTextHex as mi, parseSvg as mn, setFillColorRgb as mr, rc4 as mt, StandardFonts as n, moveTextSetLeading as ni, tilingPattern as nn, colorToHex as nr, loadPdf as nt, removePageLabels as o, setFontSize as oi, PdfLayer as on, grayscale as or, verifyUserPassword as ot, getAttachments as p, showTextArray as pi, interpolateLinearRgb as pn, setFillColorGray as pr, aesEncryptCBC as pt, isAccessible as q, scale as qn, setFlatness as qr, wrapText as qt, createPdf as r, nextLine as ri, applyRedactions as rn, componentsToColor as rr, PdfEncryptionHandler as rt, setPageLabels as s, setLeading as si, PdfLayerManager as sn, hexToColor as sr, sha256 as st, PdfDocument as t, moveText as ti, radialGradient as tn, colorToComponents as tr, PdfOutlineTree as tt, addWatermarkToPage as u, setTextRise as ui, drawSvgOnPage as un, setColorSpace as ur, decodePermissions as ut, buildPkcs7Signature as v, AnnotationFlags as vn, setStrokeColorGray as vr, XrefParser as vt, encodeLength as w, buildDocumentStructure as wn, drawImageWithMatrix as wr, decodeTiffAll as wt, detectNamedCurve as x, buildAnnotationDict as xn, setStrokingColor as xr, PdfParseError as xt, decodeOidBytes as y, PdfAnnotation as yn, setStrokeColorRgb as yr, PdfObjectParser as yt, computeSignatureHash as z, degrees as zn, fill as zr, fontSubset_exports as zt };
|
|
25663
25988
|
|
|
25664
|
-
//# sourceMappingURL=pdfDocument-
|
|
25989
|
+
//# sourceMappingURL=pdfDocument-Q0wrwKEZ.mjs.map
|