modern-pdf-lib 0.32.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 +11 -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-Ddc6zdqj.d.mts → index-C240uDcb.d.mts} +232 -45
- package/dist/index-C240uDcb.d.mts.map +1 -0
- package/dist/{index-JejepHCR.d.cts → index-Z4U1Jx0K.d.cts} +232 -45
- package/dist/index-Z4U1Jx0K.d.cts.map +1 -0
- package/dist/index.cjs +11 -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-DNe0XZhx.mjs → src-CiUkSS81.mjs} +780 -150
- package/dist/{src-CeKIKI1W.cjs → src-PxZwqIKQ.cjs} +815 -149
- package/package.json +1 -1
- package/dist/index-Ddc6zdqj.d.mts.map +0 -1
- package/dist/index-JejepHCR.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",
|
|
@@ -25941,6 +26266,12 @@ Object.defineProperty(exports, "buildPkcs7Signature", {
|
|
|
25941
26266
|
return buildPkcs7Signature;
|
|
25942
26267
|
}
|
|
25943
26268
|
});
|
|
26269
|
+
Object.defineProperty(exports, "buildSigningCertificateV2Attribute", {
|
|
26270
|
+
enumerable: true,
|
|
26271
|
+
get: function() {
|
|
26272
|
+
return buildSigningCertificateV2Attribute;
|
|
26273
|
+
}
|
|
26274
|
+
});
|
|
25944
26275
|
Object.defineProperty(exports, "buildViewerPreferencesDict", {
|
|
25945
26276
|
enumerable: true,
|
|
25946
26277
|
get: function() {
|
|
@@ -26319,6 +26650,12 @@ Object.defineProperty(exports, "extractMetrics", {
|
|
|
26319
26650
|
return extractMetrics;
|
|
26320
26651
|
}
|
|
26321
26652
|
});
|
|
26653
|
+
Object.defineProperty(exports, "extractSigningCertificateV2", {
|
|
26654
|
+
enumerable: true,
|
|
26655
|
+
get: function() {
|
|
26656
|
+
return extractSigningCertificateV2;
|
|
26657
|
+
}
|
|
26658
|
+
});
|
|
26322
26659
|
Object.defineProperty(exports, "extractSubjectPublicKeyInfo", {
|
|
26323
26660
|
enumerable: true,
|
|
26324
26661
|
get: function() {
|
|
@@ -27022,4 +27359,4 @@ Object.defineProperty(exports, "wrapText", {
|
|
|
27022
27359
|
}
|
|
27023
27360
|
});
|
|
27024
27361
|
|
|
27025
|
-
//# sourceMappingURL=pdfDocument-
|
|
27362
|
+
//# sourceMappingURL=pdfDocument-Dyj4AmT1.cjs.map
|