@embedpdf/core-signature 3.0.0-next.13

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.
@@ -0,0 +1,328 @@
1
+ import * as pkijs from "pkijs";
2
+ import { DigestAlgorithm, DocumentHandle, SignatureCompleteResult, SignatureDTO, SignaturePrepareInput, SignaturePrepared, SignatureSubFilter } from "@embedpdf/engine-core/runtime";
3
+ //#region src/cms/parse.d.ts
4
+ /** What a detached CMS says about itself. Nothing here is verified. */
5
+ interface ParsedCms {
6
+ digestAlgorithm: DigestAlgorithm;
7
+ /** The `message-digest` signed attribute: what the signer claims the content hashes to. */
8
+ messageDigest: Uint8Array;
9
+ /** The CMS `signing-time` signed attribute, when present (PAdES forbids it; the PDF's `/M` is the claim there). */
10
+ signingTime: Date | null;
11
+ /** DER of the signer's certificate. */
12
+ signerCertificate: Uint8Array;
13
+ /** DER of every certificate carried by the CMS, signer first. */
14
+ certificates: Uint8Array[];
15
+ /** The signature algorithm OID (`1.2.840.113549.1.1.11` = sha256WithRSAEncryption, …). */
16
+ signatureAlgorithm: string;
17
+ /** The ESS `signing-certificate-v2` attribute is present (a CAdES requirement). */
18
+ signingCertificateV2: boolean;
19
+ /** DER of an RFC 3161 timestamp token carried as an unsigned attribute, when present. */
20
+ timestampToken: Uint8Array | null;
21
+ }
22
+ declare class CmsError extends Error {
23
+ readonly reason: 'malformed' | 'unsupported';
24
+ constructor(reason: 'malformed' | 'unsupported', message: string);
25
+ }
26
+ interface ParsedCmsInternal {
27
+ parsed: ParsedCms;
28
+ signedData: pkijs.SignedData;
29
+ signerInfo: pkijs.SignerInfo;
30
+ signerCertificate: pkijs.Certificate;
31
+ certificates: pkijs.Certificate[];
32
+ /** DER of the signing-certificate-v2 attribute's first certHash, when present. */
33
+ essCertHash: Uint8Array | null;
34
+ }
35
+ /** Parse a detached CMS SignedData with exactly one signer. Throws `CmsError`. */
36
+ declare function parseDetachedCms(cms: Uint8Array): ParsedCms;
37
+ //#endregion
38
+ //#region src/cms/verify.d.ts
39
+ type CryptographyVerdict = 'valid' | 'invalid' | 'unsupported';
40
+ /**
41
+ * Does the CMS's signature verify with the certificate it names, over the
42
+ * attributes it signed? Says nothing about the content: the message digest
43
+ * is compared by the caller (`validateSignatures`, `verifyForCompletion`).
44
+ * `unsupported` means the algorithm is unknown to this engine, which is
45
+ * never `invalid`.
46
+ */
47
+ declare function verifyCmsSignature(cms: Uint8Array | ParsedCmsInternal): Promise<CryptographyVerdict>;
48
+ //#endregion
49
+ //#region src/cms/build.d.ts
50
+ type SignatureProfile = 'pkcs7' | 'cades-b';
51
+ type RawSignatureAlgorithm = 'RSA-PKCS1-v1_5' | 'RSA-PSS' | 'ECDSA';
52
+ /**
53
+ * Something that signs bytes with a private key it never hands out: a
54
+ * WebCrypto key, an HSM, a smart card. `sign` receives the DER of the CMS
55
+ * signed attributes and returns the raw signature (for ECDSA: `r || s`,
56
+ * as WebCrypto produces it; the CMS encoding is done here).
57
+ */
58
+ interface RawSigner {
59
+ readonly kind: 'raw';
60
+ /** DER certificates, the signer's first, then its issuers. */
61
+ readonly certificateChain: Uint8Array[];
62
+ readonly algorithm: RawSignatureAlgorithm;
63
+ readonly hash: Exclude<DigestAlgorithm, 'sha1'>;
64
+ sign(signedAttributesDer: Uint8Array): Promise<Uint8Array>;
65
+ }
66
+ interface BuildDetachedCmsInput {
67
+ /** The digest the engine prepared (over the `/ByteRange`). */
68
+ digest: Uint8Array;
69
+ hash: Exclude<DigestAlgorithm, 'sha1'>;
70
+ profile: SignatureProfile;
71
+ signer: RawSigner;
72
+ /** `pkcs7` only: the CMS `signing-time` attribute. PAdES (`cades-b`) never carries one. */
73
+ signingTime?: Date;
74
+ }
75
+ /**
76
+ * Build a detached CMS SignedData around a raw signature: content-type,
77
+ * message-digest, and for CAdES-B the ESS signing-certificate-v2 attribute;
78
+ * the signer's certificate chain; one SignerInfo identified by issuer and
79
+ * serial number.
80
+ */
81
+ declare function buildDetachedCms(input: BuildDetachedCmsInput): Promise<Uint8Array>;
82
+ //#endregion
83
+ //#region src/gate.d.ts
84
+ type CompletionRefusal = 'malformed' | 'too-large' | 'algorithm-mismatch' | 'digest-mismatch' | 'signature-invalid' | 'profile-violation';
85
+ type CompletionGate = {
86
+ ok: true;
87
+ } | {
88
+ ok: false;
89
+ reason: CompletionRefusal;
90
+ detail: string;
91
+ };
92
+ /**
93
+ * The gate between a signer's answer and `signatures.complete`: the CMS
94
+ * must fit the reserved room, hash with the prepared algorithm, carry the
95
+ * prepared digest as its message digest, verify with its own certificate,
96
+ * and match the profile the `/SubFilter` promises (CAdES: ESS
97
+ * signing-certificate-v2 present, no CMS signing-time). A bad CMS never
98
+ * reaches the document.
99
+ */
100
+ declare function verifyForCompletion(input: {
101
+ cms: Uint8Array;
102
+ prepared: SignaturePrepared;
103
+ profile: SignatureProfile;
104
+ }): Promise<CompletionGate>;
105
+ //#endregion
106
+ //#region src/trust.d.ts
107
+ /**
108
+ * Where trust comes from. The engine has no opinion: an application
109
+ * supplies its anchors (a company root, a national trust list, the AATL).
110
+ */
111
+ interface TrustPort {
112
+ /** DER certificates trusted as anchors. */
113
+ anchors(): Promise<Uint8Array[]>;
114
+ }
115
+ /**
116
+ * When a chain is judged. `now` is the honest default; `timestamp` is only
117
+ * legitimate for a verified RFC 3161 token, which is why it carries the
118
+ * proof flag. The signature's own `/M` is a claim and never a validation
119
+ * time.
120
+ */
121
+ type ValidationTime = {
122
+ kind: 'now';
123
+ } | {
124
+ kind: 'timestamp';
125
+ genTime: Date;
126
+ tokenVerified: true;
127
+ };
128
+ type TrustStatus = 'trusted' | 'untrusted' | 'unknown';
129
+ interface TrustVerdict {
130
+ status: TrustStatus;
131
+ /** Why, when not trusted. */
132
+ reason?: string;
133
+ /** DER certificates of the validated path, anchor last, when trusted. */
134
+ path?: Uint8Array[];
135
+ }
136
+ /**
137
+ * Build and validate the certificate path from the CMS's signer to one
138
+ * of the port's anchors at `at`. No port, or a port with no anchors, is
139
+ * `unknown`: nothing was checked, and nothing was refused.
140
+ */
141
+ declare function validateChain(cms: Uint8Array | ParsedCmsInternal, trust: TrustPort | null | undefined, at?: ValidationTime): Promise<TrustVerdict>;
142
+ //#endregion
143
+ //#region src/sign.d.ts
144
+ /** A service that turns a digest into a finished detached CMS (most hosted signing APIs). */
145
+ interface CmsSigner {
146
+ readonly kind: 'cms';
147
+ sign(input: {
148
+ digest: Uint8Array;
149
+ algorithm: Exclude<DigestAlgorithm, 'sha1'>;
150
+ subFilter: SignatureSubFilter;
151
+ }): Promise<Uint8Array>;
152
+ }
153
+ type SignerPort = CmsSigner | RawSigner;
154
+ type SignInput = Omit<SignaturePrepareInput, 'kind'> & {
155
+ signer: SignerPort;
156
+ };
157
+ declare class SigningError extends Error {
158
+ readonly reason: CompletionRefusal;
159
+ constructor(reason: CompletionRefusal, detail: string);
160
+ }
161
+ declare function profileFor(subFilter: SignatureSubFilter): SignatureProfile;
162
+ /**
163
+ * Sign a field in one call: `prepare` on the engine, the signer turns the
164
+ * digest into a CMS (or a raw signature this package wraps), the gate
165
+ * checks the CMS matches what was prepared, `complete` installs it. Any
166
+ * failure aborts the candidate and rethrows; the document is never left
167
+ * with a pending signing.
168
+ */
169
+ declare function sign(doc: DocumentHandle, input: SignInput): Promise<SignatureCompleteResult>;
170
+ //#endregion
171
+ //#region src/verdict.d.ts
172
+ type IntegrityVerdict = 'valid' | 'invalid' | 'indeterminate';
173
+ type ModificationsVerdict = 'unchanged' | 'permitted' | 'forbidden' | 'indeterminate';
174
+ /**
175
+ * Four independent facts and a summary, never one boolean — the shape
176
+ * Acrobat reports ("signature valid", "signer unknown", "document changed,
177
+ * changes allowed") and the shape a UI can explain.
178
+ */
179
+ interface SignatureVerdict {
180
+ signature: SignatureDTO;
181
+ /** The sealed bytes are intact: whole-revision coverage and the CMS message digest matches them. */
182
+ integrity: IntegrityVerdict;
183
+ /** The CMS verifies with its own certificate. */
184
+ cryptography: CryptographyVerdict;
185
+ /** The certificate chains to one of the caller's anchors. */
186
+ trust: TrustStatus;
187
+ trustReason?: string;
188
+ validatedAt: ValidationTime;
189
+ /**
190
+ * What changed after the signature, and which bytes were judged: the loaded
191
+ * file (`persisted`), or the session's unsaved edits snapshotted as one
192
+ * more revision (`working-copy` — only when such edits existed).
193
+ */
194
+ modifications: {
195
+ verdict: ModificationsVerdict;
196
+ detail?: string;
197
+ basis: 'persisted' | 'working-copy';
198
+ /** Revisions appended after the one this signature sealed (present when there are any). */
199
+ laterRevisions?: number;
200
+ /** Some object was changed after the signature and holds the sealed value again. */
201
+ undone?: boolean;
202
+ };
203
+ /** `invalid` only on positive evidence; `indeterminate` whenever a fact could not be established. */
204
+ summary: 'valid' | 'valid-untrusted' | 'invalid' | 'indeterminate';
205
+ cms: ParsedCms | null;
206
+ }
207
+ interface ValidateSignaturesOptions {
208
+ trust?: TrustPort | null;
209
+ at?: ValidationTime;
210
+ /**
211
+ * `persisted` (default): the loaded bytes — what a file on disk says.
212
+ * `working-copy`: unsaved edits are judged too, as the revision a save would
213
+ * write — what the file a save produces will say. A viewer shows this one.
214
+ */
215
+ until?: 'persisted' | 'working-copy';
216
+ }
217
+ /**
218
+ * Validate every signature of a document: integrity from the engine's
219
+ * bytes, cryptography from the CMS, trust from the caller's anchors.
220
+ */
221
+ declare function validateSignatures(doc: DocumentHandle, opts?: ValidateSignaturesOptions): Promise<SignatureVerdict[]>;
222
+ //#endregion
223
+ //#region src/signers/webcrypto.d.ts
224
+ /**
225
+ * A `RawSigner` over a WebCrypto private key: the key never leaves the
226
+ * runtime. The algorithm and hash come from the key itself.
227
+ */
228
+ declare function webCryptoSigner(input: {
229
+ privateKey: CryptoKey;
230
+ certificateChain: Uint8Array[];
231
+ /** Required for ECDSA keys (the key carries no hash); ignored for RSA keys. */
232
+ hash?: Exclude<DigestAlgorithm, 'sha1'>;
233
+ }): RawSigner;
234
+ interface TestSigner extends RawSigner {
235
+ /** DER of the self-signed certificate — also the only trust anchor that validates it. */
236
+ readonly certificate: Uint8Array;
237
+ readonly privateKey: CryptoKey;
238
+ }
239
+ /**
240
+ * A throwaway signer for tests and demos: a fresh key pair and a
241
+ * self-signed certificate, never persisted. Trust it with
242
+ * `{ anchors: async () => [signer.certificate] }`.
243
+ */
244
+ declare function createTestSigner(opts?: {
245
+ commonName?: string;
246
+ algorithm?: 'RSA-PKCS1-v1_5' | 'RSA-PSS' | 'ECDSA';
247
+ hash?: 'sha256' | 'sha384' | 'sha512';
248
+ }): Promise<TestSigner>;
249
+ /** A WebCrypto signing key pair; `extractable: false` keeps the private key inside the runtime for good. */
250
+ declare function generateSigningKeyPair(algorithm: 'RSA-PKCS1-v1_5' | 'RSA-PSS' | 'ECDSA', hash: 'sha256' | 'sha384' | 'sha512', extractable: boolean): Promise<CryptoKeyPair>;
251
+ //#endregion
252
+ //#region src/signers/remote.d.ts
253
+ /**
254
+ * A `CmsSigner` over the customer's own signing service or HSM: the engine's
255
+ * digest goes out, a finished detached CMS comes back. Nothing but the
256
+ * digest (and which hash and profile it is for) ever leaves the runtime.
257
+ */
258
+ declare function remoteSigner(input: {
259
+ sign: (request: {
260
+ digest: Uint8Array;
261
+ algorithm: 'sha256' | 'sha384' | 'sha512';
262
+ subFilter: 'adbe.pkcs7.detached' | 'ETSI.CAdES.detached';
263
+ }) => Promise<Uint8Array>;
264
+ }): CmsSigner;
265
+ //#endregion
266
+ //#region src/signers/personal.d.ts
267
+ /** What a personal signer keeps: a NON-extractable private key and its self-signed certificate. */
268
+ interface PersonalKeyRecord {
269
+ privateKey: CryptoKey;
270
+ certificate: Uint8Array;
271
+ }
272
+ /** Where personal keys live. Keys are structured-cloneable, so a store can keep the `CryptoKey` itself. */
273
+ interface PersonalKeyStore {
274
+ load(subject: string): Promise<PersonalKeyRecord | null>;
275
+ save(subject: string, record: PersonalKeyRecord): Promise<void>;
276
+ remove(subject: string): Promise<void>;
277
+ }
278
+ interface PersonalSigner extends RawSigner {
279
+ /** DER of the self-signed certificate — the only anchor that validates it. */
280
+ readonly certificate: Uint8Array;
281
+ readonly subject: string;
282
+ }
283
+ /**
284
+ * One self-signed identity per subject (a person's name), persisted in the
285
+ * caller's store and created on first use. The private key is generated
286
+ * non-extractable: it can sign, it can be stored by the browser, it can
287
+ * never be read out. This is Preview's "sign with your own signature"
288
+ * experience with real cryptography behind it — a reader who trusts the
289
+ * certificate validates the signature; every other reader sees "validity
290
+ * unknown", which is the honest answer for a self-issued identity.
291
+ */
292
+ declare function personalSigner(input: {
293
+ subject: string;
294
+ store: PersonalKeyStore;
295
+ algorithm?: 'RSA-PKCS1-v1_5' | 'RSA-PSS' | 'ECDSA';
296
+ hash?: 'sha256' | 'sha384' | 'sha512';
297
+ }): Promise<PersonalSigner>;
298
+ /** An in-memory store: tests, and runtimes without IndexedDB. */
299
+ declare function memoryKeyStore(): PersonalKeyStore;
300
+ /**
301
+ * An IndexedDB store: the browser keeps the non-extractable `CryptoKey`
302
+ * itself (structured clone), so the key survives reloads without ever
303
+ * existing as bytes.
304
+ */
305
+ declare function indexedDbKeyStore(dbName: string, opts?: {
306
+ storeName?: string;
307
+ }): PersonalKeyStore;
308
+ //#endregion
309
+ //#region src/signers/self-signed.d.ts
310
+ /**
311
+ * A self-signed certificate over a WebCrypto key pair: the shape a personal
312
+ * signer, a test signer, and a demo all need. It is its own trust anchor and
313
+ * nothing else's — Acrobat shows a signature made with it as "validity
314
+ * unknown" until the reader trusts the certificate explicitly.
315
+ */
316
+ declare function selfSignedCertificate(input: {
317
+ publicKey: CryptoKey;
318
+ privateKey: CryptoKey;
319
+ commonName: string;
320
+ hash: 'sha256' | 'sha384' | 'sha512';
321
+ /** Validity in days; default one year. */
322
+ validityDays?: number;
323
+ }): Promise<Uint8Array>;
324
+ /** The subject common name of a DER certificate, or null when it has none. */
325
+ declare function certificateCommonName(der: Uint8Array): string | null;
326
+ //#endregion
327
+ export { type BuildDetachedCmsInput, CmsError, type CmsSigner, type CompletionGate, type CompletionRefusal, type CryptographyVerdict, type IntegrityVerdict, type ModificationsVerdict, type ParsedCms, type PersonalKeyRecord, type PersonalKeyStore, type PersonalSigner, type RawSignatureAlgorithm, type RawSigner, type SignInput, type SignatureProfile, type SignatureVerdict, type SignerPort, SigningError, type TestSigner, type TrustPort, type TrustStatus, type TrustVerdict, type ValidateSignaturesOptions, type ValidationTime, buildDetachedCms, certificateCommonName, createTestSigner, generateSigningKeyPair, indexedDbKeyStore, memoryKeyStore, parseDetachedCms, personalSigner, profileFor, remoteSigner, selfSignedCertificate, sign, validateChain, validateSignatures, verifyCmsSignature, verifyForCompletion, webCryptoSigner };
328
+ //# sourceMappingURL=index.d.ts.map