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.
- package/README.md +3 -3
- package/dist/browser.cjs +6 -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-BJtSRrMf.d.mts → index-C240uDcb.d.mts} +95 -45
- package/dist/index-C240uDcb.d.mts.map +1 -0
- package/dist/{index-BqYQ9lsY.d.cts → index-Z4U1Jx0K.d.cts} +95 -45
- package/dist/index-Z4U1Jx0K.d.cts.map +1 -0
- package/dist/index.cjs +6 -3
- package/dist/index.d.cts +5 -5
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +4 -4
- package/dist/{layout-BYXpcYtC.cjs → layout-ClbkITM3.cjs} +2 -2
- package/dist/{layout-xOcesNCh.mjs → layout-XgQY_Uba.mjs} +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-Dyj4AmT1.cjs} +358 -21
- package/dist/{pdfDocument-Cgkkk8F8.mjs → pdfDocument-EcHxUnR6.mjs} +347 -22
- package/dist/{src-zeRl33xQ.mjs → src-CiUkSS81.mjs} +263 -23
- package/dist/{src-BdVnpRoy.cjs → src-PxZwqIKQ.cjs} +268 -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 $, 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-
|
|
25989
|
+
//# sourceMappingURL=pdfDocument-EcHxUnR6.mjs.map
|