@awacloud/pdf 0.0.0-stage → 1.0.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/CHANGELOG.md +609 -0
- package/LICENSE +661 -0
- package/NOTICE +77 -0
- package/README.md +363 -2
- package/dist/build/index.js +21 -0
- package/dist/build/pdf-full-rw.js +10972 -0
- package/dist/build/pdf-full-rw.meta.json +105 -0
- package/dist/build/pdf-full-rw.min.js +53 -0
- package/dist/build/pdf-full.js +6078 -0
- package/dist/build/pdf-full.meta.json +90 -0
- package/dist/build/pdf-full.min.js +32 -0
- package/dist/build/pdf-large-rw.js +10367 -0
- package/dist/build/pdf-large-rw.meta.json +99 -0
- package/dist/build/pdf-large-rw.min.js +53 -0
- package/dist/build/pdf-large.js +5473 -0
- package/dist/build/pdf-large.meta.json +84 -0
- package/dist/build/pdf-large.min.js +32 -0
- package/dist/build/pdf-legacy-rw.js +12402 -0
- package/dist/build/pdf-legacy-rw.meta.json +110 -0
- package/dist/build/pdf-legacy-rw.min.js +53 -0
- package/dist/build/pdf-legacy.js +7508 -0
- package/dist/build/pdf-legacy.meta.json +95 -0
- package/dist/build/pdf-legacy.min.js +32 -0
- package/dist/build/pdf-rw.js +7578 -0
- package/dist/build/pdf-rw.meta.json +77 -0
- package/dist/build/pdf-rw.min.js +53 -0
- package/dist/build/pdf.js +2684 -0
- package/dist/build/pdf.meta.json +62 -0
- package/dist/build/pdf.min.js +32 -0
- package/dist/standalone/pdf-full-rw.js +16798 -0
- package/dist/standalone/pdf-full-rw.meta.json +78 -0
- package/dist/standalone/pdf-full-rw.min.js +56 -0
- package/dist/standalone/pdf-full.js +11904 -0
- package/dist/standalone/pdf-full.meta.json +63 -0
- package/dist/standalone/pdf-full.min.js +35 -0
- package/dist/standalone/pdf-large-rw.js +16193 -0
- package/dist/standalone/pdf-large-rw.meta.json +72 -0
- package/dist/standalone/pdf-large-rw.min.js +56 -0
- package/dist/standalone/pdf-large.js +11299 -0
- package/dist/standalone/pdf-large.meta.json +57 -0
- package/dist/standalone/pdf-large.min.js +35 -0
- package/dist/standalone/pdf-legacy-rw.js +18228 -0
- package/dist/standalone/pdf-legacy-rw.meta.json +83 -0
- package/dist/standalone/pdf-legacy-rw.min.js +56 -0
- package/dist/standalone/pdf-legacy.js +13334 -0
- package/dist/standalone/pdf-legacy.meta.json +68 -0
- package/dist/standalone/pdf-legacy.min.js +35 -0
- package/dist/standalone/pdf-rw.js +13404 -0
- package/dist/standalone/pdf-rw.meta.json +50 -0
- package/dist/standalone/pdf-rw.min.js +56 -0
- package/dist/standalone/pdf.js +8510 -0
- package/dist/standalone/pdf.meta.json +35 -0
- package/dist/standalone/pdf.min.js +35 -0
- package/docs/README.md +53 -0
- package/docs/api/README.md +38 -0
- package/docs/api/_shared/README.md +91 -0
- package/docs/api/action/README.md +29 -0
- package/docs/api/action/action.md +81 -0
- package/docs/api/action/goTo.md +66 -0
- package/docs/api/action/launch.md +58 -0
- package/docs/api/action/named.md +55 -0
- package/docs/api/action/uri.md +54 -0
- package/docs/api/annot/README.md +53 -0
- package/docs/api/annot/annot.md +114 -0
- package/docs/api/annot/fileAttach.md +53 -0
- package/docs/api/annot/freeText.md +68 -0
- package/docs/api/annot/ink.md +69 -0
- package/docs/api/annot/link.md +74 -0
- package/docs/api/annot/markup.md +83 -0
- package/docs/api/annot/popup.md +52 -0
- package/docs/api/annot/projection.md +56 -0
- package/docs/api/annot/redact.md +67 -0
- package/docs/api/annot/square.md +87 -0
- package/docs/api/annot/stamp.md +54 -0
- package/docs/api/annot/text.md +69 -0
- package/docs/api/annot/widget.md +69 -0
- package/docs/api/associatedFiles/README.md +9 -0
- package/docs/api/associatedFiles/associatedFiles.md +78 -0
- package/docs/api/bundles/README.md +68 -0
- package/docs/api/bundles/dist-matrix.md +165 -0
- package/docs/api/bundles/pdf-full.md +148 -0
- package/docs/api/bundles/pdf-large.md +144 -0
- package/docs/api/bundles/pdf-legacy.md +169 -0
- package/docs/api/content/README.md +29 -0
- package/docs/api/content/color.md +99 -0
- package/docs/api/content/graphics.md +114 -0
- package/docs/api/content/images.md +124 -0
- package/docs/api/content/ops.md +100 -0
- package/docs/api/content/stream.md +107 -0
- package/docs/api/content/text.md +98 -0
- package/docs/api/crypto/README.md +29 -0
- package/docs/api/crypto/aesGcm.md +72 -0
- package/docs/api/crypto/permissions.md +79 -0
- package/docs/api/crypto/security.md +98 -0
- package/docs/api/crypto/standardV4.md +104 -0
- package/docs/api/crypto/standardV5.md +84 -0
- package/docs/api/crypto/standardV6.md +93 -0
- package/docs/api/destination/README.md +9 -0
- package/docs/api/destination/destination.md +79 -0
- package/docs/api/document/README.md +29 -0
- package/docs/api/document/builder.md +281 -0
- package/docs/api/document/catalog.md +98 -0
- package/docs/api/document/document.md +187 -0
- package/docs/api/document/encryptedWriter.md +149 -0
- package/docs/api/document/incrementalWriter.md +148 -0
- package/docs/api/document/page.md +99 -0
- package/docs/api/document/pages.md +82 -0
- package/docs/api/document/resources.md +102 -0
- package/docs/api/document/writer.md +157 -0
- package/docs/api/document/xrefStreamWriter.md +122 -0
- package/docs/api/embedded/README.md +13 -0
- package/docs/api/embedded/collection.md +80 -0
- package/docs/api/embedded/embeddedFile.md +86 -0
- package/docs/api/embedded/fileSpec.md +87 -0
- package/docs/api/errors.md +110 -0
- package/docs/api/extra/3d-richmedia.md +76 -0
- package/docs/api/extra/README.md +99 -0
- package/docs/api/extra/annot-extended.md +71 -0
- package/docs/api/extra/associated-files.md +70 -0
- package/docs/api/extra/ccitt-fax-decoder.md +74 -0
- package/docs/api/extra/color-spaces-extended.md +72 -0
- package/docs/api/extra/content-ops-extended.md +82 -0
- package/docs/api/extra/document-parts.md +69 -0
- package/docs/api/extra/embedded-files-portfolio.md +87 -0
- package/docs/api/extra/font-cid-typed.md +77 -0
- package/docs/api/extra/font-color-tagging.md +76 -0
- package/docs/api/extra/form-actions-extended.md +75 -0
- package/docs/api/extra/info-dict-deprecated.md +72 -0
- package/docs/api/extra/jbig2-read.md +80 -0
- package/docs/api/extra/legacy-deprecated-annots.md +89 -0
- package/docs/api/extra/legacy-deprecated-filters.md +78 -0
- package/docs/api/extra/legacy-rc4-read.md +74 -0
- package/docs/api/extra/legacy-xfa-read.md +65 -0
- package/docs/api/extra/linearization-write.md +71 -0
- package/docs/api/extra/misc.md +93 -0
- package/docs/api/extra/optional-content-extended.md +83 -0
- package/docs/api/extra/pdf-a-output-intent.md +65 -0
- package/docs/api/extra/pdf-sandbox.md +76 -0
- package/docs/api/extra/pdf-ua-tagged.md +63 -0
- package/docs/api/extra/pdf-x-prepress.md +65 -0
- package/docs/api/extra/redaction-iso32005.md +65 -0
- package/docs/api/extra/shading-typed.md +73 -0
- package/docs/api/extra/sig-aes-gcm.md +69 -0
- package/docs/api/extra/sig-pades.md +103 -0
- package/docs/api/extra/tagged-pdf-typed.md +78 -0
- package/docs/api/extra/transparency-typed.md +74 -0
- package/docs/api/extra/well-tagged-pdf.md +61 -0
- package/docs/api/extra/xmp-extended.md +65 -0
- package/docs/api/font/README.md +25 -0
- package/docs/api/font/embed.md +157 -0
- package/docs/api/font/encoding.md +95 -0
- package/docs/api/font/font.md +97 -0
- package/docs/api/font/type3.md +89 -0
- package/docs/api/form/README.md +35 -0
- package/docs/api/form/acroform.md +88 -0
- package/docs/api/form/appearance.md +87 -0
- package/docs/api/form/button.md +97 -0
- package/docs/api/form/choice.md +96 -0
- package/docs/api/form/fieldTree.md +93 -0
- package/docs/api/form/signature.md +90 -0
- package/docs/api/form/text.md +88 -0
- package/docs/api/linearization/README.md +11 -0
- package/docs/api/linearization/linearization.md +81 -0
- package/docs/api/main.md +116 -0
- package/docs/api/metadata/README.md +10 -0
- package/docs/api/metadata/info.md +70 -0
- package/docs/api/metadata/xmp.md +62 -0
- package/docs/api/ocg/README.md +23 -0
- package/docs/api/ocg/config.md +95 -0
- package/docs/api/ocg/ocg.md +77 -0
- package/docs/api/outline/README.md +11 -0
- package/docs/api/outline/outline.md +107 -0
- package/docs/api/pdf.md +152 -0
- package/docs/api/prepress/README.md +10 -0
- package/docs/api/prepress/outputIntent.md +79 -0
- package/docs/api/prepress/pageBoundary.md +75 -0
- package/docs/api/sig/README.md +32 -0
- package/docs/api/sig/byteRange.md +120 -0
- package/docs/api/sig/certChain.md +84 -0
- package/docs/api/sig/dss.md +111 -0
- package/docs/api/sig/oids.md +76 -0
- package/docs/api/sig/sha1.md +72 -0
- package/docs/api/sig/sign.md +317 -0
- package/docs/api/sig/signature.md +178 -0
- package/docs/api/sig/timestamp.md +84 -0
- package/docs/api/syntax/README.md +29 -0
- package/docs/api/syntax/crossRefStream.md +115 -0
- package/docs/api/syntax/filters/README.md +50 -0
- package/docs/api/syntax/filters/ascii85.md +76 -0
- package/docs/api/syntax/filters/asciiHex.md +73 -0
- package/docs/api/syntax/filters/dispatch.md +125 -0
- package/docs/api/syntax/filters/flate.md +134 -0
- package/docs/api/syntax/filters/runLength.md +78 -0
- package/docs/api/syntax/objStream.md +88 -0
- package/docs/api/syntax/parser-obj.md +97 -0
- package/docs/api/syntax/parser.md +151 -0
- package/docs/api/syntax/serializer.md +109 -0
- package/docs/api/syntax/tokenizer.md +104 -0
- package/docs/api/syntax/trailer.md +85 -0
- package/docs/api/syntax/xref.md +139 -0
- package/docs/api/tagged/README.md +25 -0
- package/docs/api/tagged/classMap.md +67 -0
- package/docs/api/tagged/markedContent.md +62 -0
- package/docs/api/tagged/parentTree.md +67 -0
- package/docs/api/tagged/roleMap.md +67 -0
- package/docs/api/tagged/structElement.md +76 -0
- package/docs/api/tagged/structTree.md +75 -0
- package/docs/guide/coverage.md +113 -0
- package/docs/guide/crypto.md +121 -0
- package/docs/guide/extending.md +76 -0
- package/docs/guide/getting-started.md +75 -0
- package/docs/guide/legacy-1.7.md +42 -0
- package/docs/guide/pades-integration.md +579 -0
- package/docs/guide/read-pdf.md +89 -0
- package/package.json +97 -4
- package/src/_shared/index.js +179 -0
- package/src/action/action.js +119 -0
- package/src/action/goTo.js +89 -0
- package/src/action/launch.js +61 -0
- package/src/action/named.js +54 -0
- package/src/action/uri.js +51 -0
- package/src/annot/annot.js +212 -0
- package/src/annot/fileAttach.js +55 -0
- package/src/annot/freeText.js +82 -0
- package/src/annot/ink.js +77 -0
- package/src/annot/link.js +77 -0
- package/src/annot/markup.js +91 -0
- package/src/annot/popup.js +53 -0
- package/src/annot/projection.js +52 -0
- package/src/annot/redact.js +87 -0
- package/src/annot/square.js +132 -0
- package/src/annot/stamp.js +48 -0
- package/src/annot/text.js +54 -0
- package/src/annot/widget.js +61 -0
- package/src/associatedFiles/associatedFiles.js +86 -0
- package/src/bundles/pdf-full.js +91 -0
- package/src/bundles/pdf-large.js +81 -0
- package/src/bundles/pdf-legacy.js +107 -0
- package/src/content/color.js +114 -0
- package/src/content/graphics.js +192 -0
- package/src/content/images.js +160 -0
- package/src/content/ops.js +137 -0
- package/src/content/stream.js +154 -0
- package/src/content/text.js +125 -0
- package/src/crypto/aesGcm.js +123 -0
- package/src/crypto/permissions.js +112 -0
- package/src/crypto/security.js +327 -0
- package/src/crypto/standardV4.js +443 -0
- package/src/crypto/standardV5.js +306 -0
- package/src/crypto/standardV6.js +334 -0
- package/src/destination/destination.js +183 -0
- package/src/document/builder.js +618 -0
- package/src/document/catalog.js +100 -0
- package/src/document/document.js +472 -0
- package/src/document/encryptedWriter.js +554 -0
- package/src/document/incrementalWriter.js +514 -0
- package/src/document/page.js +131 -0
- package/src/document/pages.js +103 -0
- package/src/document/resources.js +146 -0
- package/src/document/writer.js +211 -0
- package/src/document/xrefStreamWriter.js +353 -0
- package/src/embedded/collection.js +102 -0
- package/src/embedded/embeddedFile.js +99 -0
- package/src/embedded/fileSpec.js +137 -0
- package/src/errors.js +78 -0
- package/src/extra/3d-richmedia.js +171 -0
- package/src/extra/annot-extended.js +200 -0
- package/src/extra/associated-files.js +131 -0
- package/src/extra/ccitt-fax-decoder.js +776 -0
- package/src/extra/color-spaces-extended.js +196 -0
- package/src/extra/content-ops-extended.js +153 -0
- package/src/extra/document-parts.js +149 -0
- package/src/extra/embedded-files-portfolio.js +234 -0
- package/src/extra/font-cid-typed.js +185 -0
- package/src/extra/font-color-tagging.js +144 -0
- package/src/extra/form-actions-extended.js +196 -0
- package/src/extra/info-dict-deprecated.js +137 -0
- package/src/extra/jbig2-read.js +169 -0
- package/src/extra/legacy-deprecated-annots.js +198 -0
- package/src/extra/legacy-deprecated-filters.js +167 -0
- package/src/extra/legacy-rc4-read.js +235 -0
- package/src/extra/legacy-xfa-read.js +104 -0
- package/src/extra/linearization-write.js +97 -0
- package/src/extra/misc.js +217 -0
- package/src/extra/optional-content-extended.js +142 -0
- package/src/extra/pdf-a-output-intent.js +112 -0
- package/src/extra/pdf-sandbox.js +88 -0
- package/src/extra/pdf-ua-tagged.js +116 -0
- package/src/extra/pdf-x-prepress.js +114 -0
- package/src/extra/redaction-iso32005.js +136 -0
- package/src/extra/shading-typed.js +222 -0
- package/src/extra/sig-aes-gcm.js +135 -0
- package/src/extra/sig-pades.js +242 -0
- package/src/extra/tagged-pdf-typed.js +203 -0
- package/src/extra/transparency-typed.js +135 -0
- package/src/extra/well-tagged-pdf.js +138 -0
- package/src/extra/xmp-extended.js +190 -0
- package/src/font/embed.js +480 -0
- package/src/font/encoding.js +92 -0
- package/src/font/font.js +101 -0
- package/src/font/type3.js +75 -0
- package/src/form/acroform.js +94 -0
- package/src/form/appearance.js +90 -0
- package/src/form/button.js +105 -0
- package/src/form/choice.js +152 -0
- package/src/form/fieldTree.js +120 -0
- package/src/form/signature.js +100 -0
- package/src/form/text.js +101 -0
- package/src/linearization/linearization.js +107 -0
- package/src/main.js +411 -0
- package/src/metadata/info.js +87 -0
- package/src/metadata/xmp.js +62 -0
- package/src/ocg/config.js +156 -0
- package/src/ocg/ocg.js +124 -0
- package/src/outline/outline.js +157 -0
- package/src/pdf.js +133 -0
- package/src/prepress/outputIntent.js +118 -0
- package/src/prepress/pageBoundary.js +108 -0
- package/src/sig/byteRange.js +306 -0
- package/src/sig/certChain.js +247 -0
- package/src/sig/dss.js +317 -0
- package/src/sig/oids.js +157 -0
- package/src/sig/sha1.js +142 -0
- package/src/sig/sign.js +1899 -0
- package/src/sig/signature.js +1441 -0
- package/src/sig/timestamp.js +236 -0
- package/src/syntax/crossRefStream.js +133 -0
- package/src/syntax/filters/ascii85.js +122 -0
- package/src/syntax/filters/asciiHex.js +83 -0
- package/src/syntax/filters/dispatch.js +176 -0
- package/src/syntax/filters/flate.js +316 -0
- package/src/syntax/filters/runLength.js +96 -0
- package/src/syntax/objStream.js +99 -0
- package/src/syntax/parser-obj.js +52 -0
- package/src/syntax/parser.js +321 -0
- package/src/syntax/serializer.js +221 -0
- package/src/syntax/tokenizer.js +290 -0
- package/src/syntax/trailer.js +76 -0
- package/src/syntax/xref.js +341 -0
- package/src/tagged/classMap.js +81 -0
- package/src/tagged/markedContent.js +123 -0
- package/src/tagged/parentTree.js +126 -0
- package/src/tagged/roleMap.js +107 -0
- package/src/tagged/structElement.js +138 -0
- package/src/tagged/structTree.js +94 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfOutputIntent
|
|
3
|
+
category: pdf/prepress
|
|
4
|
+
dependencies: [pdfErrors, pdfParser]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfOutputIntent
|
|
11
|
+
|
|
12
|
+
> Output intent — ISO 32000-2 §14.11.5.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfOutputIntent` | **Source** `packages/front/office/pdf/src/prepress/outputIntent.js` | **Deps** `pdfErrors`, `pdfParser` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
Describes the target rendering colour environment (`/Type /OutputIntent`), referenced from the Catalog's `/OutputIntents` array. Fields: `/S` (subtype — `GTS_PDFX` / `GTS_PDFA1` / `GTS_PDFA2` / etc., required), `/OutputCondition`, `/OutputConditionIdentifier`, `/RegistryName`, `/Info`, `/DestOutputProfile` (ICC stream ref), `/DestOutputProfileRef` (PDF 2.0 — ref to an external stream), `/MixingHints`, `/SpectralData`.
|
|
17
|
+
|
|
18
|
+
## Resolve
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const oi = runtime.resolve('pdfOutputIntent');
|
|
22
|
+
// Returns: { typeOutputIntent }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
| Method | Signature | Returns |
|
|
28
|
+
|---------|-----------|----------|
|
|
29
|
+
| `typeOutputIntent` | `(dict) => OutputIntent` | Typing. |
|
|
30
|
+
|
|
31
|
+
### Shape
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
{
|
|
35
|
+
subtype, // /S, e.g. 'GTS_PDFA2'
|
|
36
|
+
outputCondition, outputConditionIdentifier,
|
|
37
|
+
registryName, info,
|
|
38
|
+
destOutputProfile, // ICC stream ref
|
|
39
|
+
destOutputProfileRef, // PDF 2.0
|
|
40
|
+
mixingHints, spectralData,
|
|
41
|
+
raw, _extras
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Examples
|
|
46
|
+
|
|
47
|
+
### PDF/A conformance
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
const oi = runtime.resolve('pdfOutputIntent');
|
|
51
|
+
for (const ref of catalog.outputIntents) {
|
|
52
|
+
const o = oi.typeOutputIntent(doc._raw.resolve(ref));
|
|
53
|
+
if (o.subtype === 'GTS_PDFA2') console.log('PDF/A-2 ready');
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### ICC extraction
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
const profile = doc._raw.resolve(o.destOutputProfile);
|
|
61
|
+
// profile.raw → ICC bytes for downstream colour management
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Errors
|
|
65
|
+
|
|
66
|
+
| Code | Class | When |
|
|
67
|
+
|------|--------|------|
|
|
68
|
+
| `pdf/output-intent/not-dict` | `ParseError` | Argument is not a dict. |
|
|
69
|
+
| `pdf/output-intent/bad-type` | `ParseError` | `/Type` is not `/OutputIntent`. |
|
|
70
|
+
| `pdf/output-intent/missing-s` | `ParseError` | `/S` is absent. |
|
|
71
|
+
| `pdf/output-intent/bad-str` | `ParseError` | A string field is mistyped. |
|
|
72
|
+
| `pdf/output-intent/bad-profile` | `ParseError` | `/DestOutputProfile` is neither a stream nor a ref. |
|
|
73
|
+
| `pdf/output-intent/bad-profile-ref` | `ParseError` | `/DestOutputProfileRef` is neither a dict nor a ref. |
|
|
74
|
+
| `pdf/output-intent/bad-mixing` | `ParseError` | `/MixingHints` is not a dict. |
|
|
75
|
+
| `pdf/output-intent/bad-spectral` | `ParseError` | `/SpectralData` is not a dict. |
|
|
76
|
+
|
|
77
|
+
## See also
|
|
78
|
+
|
|
79
|
+
- [`pdfPageBoundary`](./pageBoundary.md) · [`pdfCatalog`](../document/catalog.md)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfPageBoundary
|
|
3
|
+
category: pdf/prepress
|
|
4
|
+
dependencies: [pdfErrors, pdfParser]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfPageBoundary
|
|
11
|
+
|
|
12
|
+
> Page boundary boxes — ISO 32000-2 §14.11.2.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfPageBoundary` | **Source** `packages/front/office/pdf/src/prepress/pageBoundary.js` | **Deps** `pdfErrors`, `pdfParser` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
Computes a page's effective boundary boxes following the §14.11.2 Table 31 inheritance rules:
|
|
17
|
+
- `/MediaBox` — paper size, mandatory.
|
|
18
|
+
- `/CropBox` — visible area, defaults to `MediaBox`.
|
|
19
|
+
- `/TrimBox` — finished trim area, defaults to `CropBox`.
|
|
20
|
+
- `/BleedBox` — bleed area, defaults to `CropBox`.
|
|
21
|
+
- `/ArtBox` — meaningful content area, defaults to `CropBox`.
|
|
22
|
+
|
|
23
|
+
Each box is `[llx, lly, urx, ury]`. The module accepts either an already-typed page record (with `mediaBox`/`cropBox`/… own fields) or a raw dict-shape object (`{ entries: { MediaBox, … } }` or `{ raw: { entries: {...} } }`), and validates the box shape (4 numeric elements) before returning it.
|
|
24
|
+
|
|
25
|
+
## Resolve
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
const pb = runtime.resolve('pdfPageBoundary');
|
|
29
|
+
// Returns: { effectiveMediaBox, effectiveCropBox, effectiveTrimBox, effectiveBleedBox, effectiveArtBox }
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## API
|
|
33
|
+
|
|
34
|
+
| Method | Signature | Returns |
|
|
35
|
+
|---------|-----------|----------|
|
|
36
|
+
| `effectiveMediaBox` | `(page) => [number,number,number,number]` | Throws if absent. |
|
|
37
|
+
| `effectiveCropBox` | `(page) => Box` | Falls back to MediaBox. |
|
|
38
|
+
| `effectiveTrimBox` | `(page) => Box` | Falls back to CropBox. |
|
|
39
|
+
| `effectiveBleedBox` | `(page) => Box` | Falls back to CropBox. |
|
|
40
|
+
| `effectiveArtBox` | `(page) => Box` | Falls back to CropBox. |
|
|
41
|
+
|
|
42
|
+
`page` is the output of [`pdfPage.typePage`](../document/page.md).
|
|
43
|
+
|
|
44
|
+
## Examples
|
|
45
|
+
|
|
46
|
+
### Imposition
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
const pb = runtime.resolve('pdfPageBoundary');
|
|
50
|
+
for (const page of doc.pages) {
|
|
51
|
+
const trim = pb.effectiveTrimBox(page);
|
|
52
|
+
const bleed = pb.effectiveBleedBox(page);
|
|
53
|
+
const margin = trim[0] - bleed[0]; // left bleed margin
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Screen rendering
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
const view = pb.effectiveCropBox(page);
|
|
61
|
+
canvas.width = view[2] - view[0];
|
|
62
|
+
canvas.height = view[3] - view[1];
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Errors
|
|
66
|
+
|
|
67
|
+
| Code | Class | When |
|
|
68
|
+
|------|--------|------|
|
|
69
|
+
| `pdf/page-boundary/bad-box` | `ParseError` | Box is not a 4-element array. |
|
|
70
|
+
| `pdf/page-boundary/bad-box-element` | `ParseError` | A box element is non-numeric. |
|
|
71
|
+
| `pdf/page-boundary/no-mediabox` | `ParseError` | `/MediaBox` absent along the inheritance chain. |
|
|
72
|
+
|
|
73
|
+
## See also
|
|
74
|
+
|
|
75
|
+
- [`pdfPage`](../document/page.md) · [`pdfOutputIntent`](./outputIntent.md)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Digital Signatures — ISO 32000-2 §12.8
|
|
2
|
+
|
|
3
|
+
PKCS#7 detached + CAdES + RFC 3161 timestamps, generation (`pdfSign`) and verification (`pdfSignature`/`pdfTimestamp`/`pdfCertChain`), plus the PAdES-LT Document Security Store builder (`pdfDssBuilder`). Most modules are `fwModules` (fw-bound: `asn1`, `rsa`, `ecc`, `ed25519`, `sha256`, `sha384`, `sha512`, `bitArray`, `pem`); `pdfSigOids` and `pdfSha1` are lighter dispatch/legacy-hash helpers shared by the rest of the family.
|
|
4
|
+
|
|
5
|
+
| Module | Returns | Deps | Description |
|
|
6
|
+
|--------|----------|------|-------------|
|
|
7
|
+
| [`pdfSignature`](./signature.md) | `{ typeSignature, verifySignature, verifyAllSignatures, verifyPk, locatePkcs7, DIGEST_OIDS, SIG_OIDS }` | `pdfErrors`, `pdfParser`, `pdfSigOids`, fw crypto | §12.8 + ISO TS 32001/32002 — verify. |
|
|
8
|
+
| [`pdfSign`](./sign.md) | `{ sign, HASH_TABLE, … }` (plus `_`-prefixed test helpers) | `pdfErrors`, `pdfSigOids`, `pdfByteRange`, `pdfDssBuilder`, `pdfIncrementalWriter`, `pdfParser`, `pdfDocument`, fw crypto | PAdES generation, levels B/T/LT/LTA. |
|
|
9
|
+
| [`pdfByteRange`](./byteRange.md) | `{ computeByteRange, extractSignedBytes, findContentsField, auditByteRange }` | `pdfErrors` | `/ByteRange` §12.8.1 + hardened audit. |
|
|
10
|
+
| [`pdfTimestamp`](./timestamp.md) | `{ parseTimestampToken, verifyTimestamp, extractTimestampFromUnsignedAttrs, OID_TST_INFO, OID_AA_TIMESTAMP }` | `pdfErrors`, `pdfSigOids`, fw crypto | RFC 3161 §12.8.5. |
|
|
11
|
+
| [`pdfCertChain`](./certChain.md) | `{ parseCertificate, extractCertsFromCms, extractCertFromPem, findIssuer, validateChainOrder }` | `pdfErrors`, `pdfSigOids`, fw `asn1`, `pem` | X.509 chain §12.8.3. |
|
|
12
|
+
| [`pdfDssBuilder`](./dss.md) | `{ buildDss }` | `pdfErrors`, `pdfSha1`, `bitArray` | PAdES-LT Document Security Store, §12.8.4.3. |
|
|
13
|
+
| [`pdfSigOids`](./oids.md) | `{ DIGEST_OIDS, SIG_DISPATCH_OIDS, KEY_ALG_OIDS, SIG_ALG_OIDS_VERBOSE, OID_TST_INFO, OID_AA_TIMESTAMP, lookupDigest, lookupSigAlg, lookupKeyAlg, lookupSigVerbose, shortOid }` | `asn1Oid` | Shared OID dispatch tables. |
|
|
14
|
+
| [`pdfSha1`](./sha1.md) | `{ fn, hash }` | `bitArray`, `utf8` | Legacy SHA-1 — DSS `/VRI` keys only. |
|
|
15
|
+
|
|
16
|
+
## Verification pattern
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
const sig = runtime.resolve('pdfSignature');
|
|
20
|
+
const typed = sig.typeSignature(sigField.v);
|
|
21
|
+
const result = sig.verifySignature(typed, documentBytes, fwBundle);
|
|
22
|
+
// `result.verified` / `result.pkVerified` reflect the ACTUAL outcome of the
|
|
23
|
+
// public-key check (RSA-PSS / ECDSA / Ed25519) — the check is wired and
|
|
24
|
+
// executed by construction. There is no `pdf/sig/pk-verify-not-wired` code;
|
|
25
|
+
// a failed check surfaces a specific `errors[]` record instead (see
|
|
26
|
+
// `pdfSignature`'s Errors table).
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## See also
|
|
30
|
+
|
|
31
|
+
- [`pdfSignatureField`](../form/signature.md) — carrier in the AcroForm.
|
|
32
|
+
- [Crypto](../crypto/README.md) — encryption (orthogonal).
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfByteRange
|
|
3
|
+
category: pdf/sig
|
|
4
|
+
dependencies: [pdfErrors]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfByteRange
|
|
11
|
+
|
|
12
|
+
> `/ByteRange` computation and extraction — ISO 32000-2 §12.8.1.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfByteRange` | **Source** `packages/front/office/pdf/src/sig/byteRange.js` | **Deps** `pdfErrors` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
A signature's `/ByteRange` is an array `[start1 len1 start2 len2]` covering the whole document *except* the gap `[start1+len1, start2)` that holds the `/Contents` value. This module provides the mechanics: locating `/Contents` in the file bytes, computing the matching ByteRange, auditing a ByteRange against the file, and extracting the signed bytes (concatenation of the two ranges). Two gap forms exist in the field; see [Notes § Gap forms](#gap-forms).
|
|
17
|
+
|
|
18
|
+
## Resolve
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const br = runtime.resolve('pdfByteRange');
|
|
22
|
+
// Returns: { computeByteRange, extractSignedBytes, findContentsField, auditByteRange }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
| Method | Signature | Returns |
|
|
28
|
+
|--------|-----------|---------|
|
|
29
|
+
| `computeByteRange` | `(docBytes, contentsOffset, contentsLength, opts?) => [s1, l1, s2, l2]` | Direct computation. Without `opts` the gap is the span given; `opts.token` makes it the `<…>` token (form b). |
|
|
30
|
+
| `findContentsField` | `(docBytes, sigObjectOffset) => { offset, length }` | Hex-digit span of the `/Contents <…>` literal in the file (`offset` is the byte after `<`). |
|
|
31
|
+
| `extractSignedBytes` | `(docBytes, byteRange) => Uint8Array` | Concatenation of the two intervals. |
|
|
32
|
+
| `auditByteRange` | `(docBytes, byteRange, opts?) => { ok, issues, gapForm }` | Hardened audit (overlap, gap form, coverage). |
|
|
33
|
+
|
|
34
|
+
### `computeByteRange(documentBytes, contentsOffset, contentsLength, opts?)`
|
|
35
|
+
|
|
36
|
+
Returns `[0, gapStart, gapEnd, total - gapEnd]`. Without `opts` the gap is
|
|
37
|
+
`[contentsOffset, contentsOffset + contentsLength)` — the historical
|
|
38
|
+
call, unchanged. `opts.token` — `{ offset, length }`, the span of the whole
|
|
39
|
+
`<…>` token — makes that span the gap (form b); it must enclose the digit
|
|
40
|
+
span by exactly one byte on each side, and those bytes must be `<` and `>`,
|
|
41
|
+
otherwise `pdf/sig/byterange/bad-token` is thrown. `pdfSign` calls it with
|
|
42
|
+
`{ token: { offset: contentsOffset - 1, length: contentsLength + 2 } }`.
|
|
43
|
+
|
|
44
|
+
### `auditByteRange(documentBytes, byteRange, opts?)`
|
|
45
|
+
|
|
46
|
+
Non-throwing audit: returns `{ ok, issues, gapForm }` where each issue
|
|
47
|
+
is a record `{ code, message, context }`. The caller decides whether to
|
|
48
|
+
escalate to an error or a warning. `gapForm` is `'token'` (form b),
|
|
49
|
+
`'digits'` (form a) or `null` — `null` when `opts.contents` is absent or
|
|
50
|
+
the gap matches neither form. An accepted gap form does not mask the other
|
|
51
|
+
checks: `ok` is `false` whenever any issue is recorded. `opts`:
|
|
52
|
+
|
|
53
|
+
- `opts.contents` — `{ offset, length }` from `findContentsField` (the
|
|
54
|
+
hex-digit span); the gap must be exactly the `<…>` token or exactly the
|
|
55
|
+
digits. Any other gap records `gap-start-mismatch` and/or
|
|
56
|
+
`gap-end-mismatch`, measured against the token bounds.
|
|
57
|
+
- `opts.others` — array of other `/ByteRange`s to cross-check, to
|
|
58
|
+
detect overlaps between concurrent signatures.
|
|
59
|
+
- `opts.requireFullCoverage: true` — requires the second range to
|
|
60
|
+
reach `documentBytes.length`.
|
|
61
|
+
|
|
62
|
+
## Examples
|
|
63
|
+
|
|
64
|
+
### Hash the signature
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
const br = runtime.resolve('pdfByteRange');
|
|
68
|
+
const sig = runtime.resolve('pdfSignature').typeSignature(dict);
|
|
69
|
+
const signed = br.extractSignedBytes(docBytes, sig.byteRange);
|
|
70
|
+
const hash = await crypto.subtle.digest('SHA-256', signed);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Locate `/Contents` to re-sign (form b)
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
const pos = br.findContentsField(docBytes, sigObjOffset); // hex digits
|
|
77
|
+
const byteRange = br.computeByteRange(docBytes, pos.offset, pos.length, {
|
|
78
|
+
token: { offset: pos.offset - 1, length: pos.length + 2 }
|
|
79
|
+
});
|
|
80
|
+
br.auditByteRange(docBytes, byteRange, { contents: pos }).gapForm; // 'token'
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Errors
|
|
84
|
+
|
|
85
|
+
| Code | Class | When |
|
|
86
|
+
|------|--------|------|
|
|
87
|
+
| `pdf/sig/byterange/bad-input` | `ParseError` | Bytes argument is not a Uint8Array. |
|
|
88
|
+
| `pdf/sig/byterange/bad-offset` | `ParseError` | Offset < 0 or out of bounds. |
|
|
89
|
+
| `pdf/sig/byterange/bad-length` | `ParseError` | Length < 0 or out of bounds. |
|
|
90
|
+
| `pdf/sig/byterange/overflow` | `ParseError` | `offset + length` > file size. |
|
|
91
|
+
| `pdf/sig/byterange/bad-token` | `ParseError` | `computeByteRange` `opts.token` is not the `<…>` token enclosing the digit span. |
|
|
92
|
+
| `pdf/sig/byterange/bad-shape` | `ParseError` | ByteRange is not a 4-integer array. |
|
|
93
|
+
| `pdf/sig/byterange/inconsistent` | `ParseError` | A range entry is negative, a range extends past the document, or range 2 starts before range 1 ends. |
|
|
94
|
+
| `pdf/sig/byterange/non-zero-start` | record `issues[]` | Range 1 does not start at 0. |
|
|
95
|
+
| `pdf/sig/byterange/self-overlap` | record `issues[]` | Range 2 starts before range 1 ends. |
|
|
96
|
+
| `pdf/sig/byterange/out-of-bounds` | record `issues[]` | A range extends past the end of the document. |
|
|
97
|
+
| `pdf/sig/byterange/gap-start-mismatch` | record `issues[]` | The gap is neither form and range 1 does not end at the `/Contents` literal's `<` (`context.expected` = the token start). |
|
|
98
|
+
| `pdf/sig/byterange/gap-end-mismatch` | record `issues[]` | The gap is neither form and range 2 does not start right after the `/Contents` literal's `>` (`context.expected` = the token end). |
|
|
99
|
+
| `pdf/sig/byterange/cross-overlap` | record `issues[]` | Overlap with another `/ByteRange` (`opts.others`). |
|
|
100
|
+
| `pdf/sig/byterange/incomplete-coverage` | record `issues[]` | Range 2 does not cover the document up to its end (`opts.requireFullCoverage`). |
|
|
101
|
+
| `pdf/sig/byterange/no-contents` | `ParseError` | `/Contents` marker not found. |
|
|
102
|
+
| `pdf/sig/byterange/contents-not-hex` | `ParseError` | `/Contents` is not a hex string (`<…>`). |
|
|
103
|
+
| `pdf/sig/byterange/contents-unterminated` | `ParseError` | `<` opened without a matching `>`. |
|
|
104
|
+
|
|
105
|
+
## Notes
|
|
106
|
+
|
|
107
|
+
### Gap forms
|
|
108
|
+
|
|
109
|
+
| Form | `gapForm` | The gap is | Who emits it |
|
|
110
|
+
|---|---|---|---|
|
|
111
|
+
| (b) token | `'token'` | the whole `<…>` hex string, both delimiters included | `pdfSign` today; PDFBox (`COSWriter`) and pyHanko (`DERPlaceholder`) |
|
|
112
|
+
| (a) digits | `'digits'` | the hex digits only; `<` and `>` are signed | `pdfSign` in earlier versions |
|
|
113
|
+
|
|
114
|
+
ISO 32000-2:2020 §12.8.3.3.1 (CMS signatures, the clause governing `adbe.pkcs7.detached`, `pdfSign`'s default `/SubFilter`; unchanged since ISO 32000-1 §12.8.3.3) states that `/Contents` "shall be a hexadecimal string with "<" and ">" delimiters" and that "it shall fit precisely in the space between the ranges specified by ByteRange" — form (b). For `ETSI.CAdES.detached` and `ETSI.RFC3161` the text only says "excluding the Contents value", and ETSI EN 319 142-1 §6.3 i) disapplies the explicit clause; both reference implementations use form (b) there too. No clause describes form (a). Hence the signer moved to form (b), and the verifier accepts both.
|
|
115
|
+
|
|
116
|
+
`pdfSign` emits form (b) for the `/Sig` and the LTA `/DocTimeStamp`. `auditByteRange` accepts **exactly** form (a) or form (b), so a signature written by an earlier version still audits clean; any other gap (off by one at either end, a delimiter only, part of the digits) is refused. `pdfSignature.verifySignature` / `verifyAllSignatures` apply the same rule to every `/Sig`, and `verifyAllSignatures` to every `/DocTimeStamp` too: any other gap sets `verified: false` and adds the `gap-start-mismatch` / `gap-end-mismatch` records to `errors`; a `timestamps[]` entry also names the accepted form in `gapForm`, with this module's vocabulary (see [`pdfSignature`](./signature.md)). The digest is always taken over the ranges the file declares; neither form is special-cased there.
|
|
117
|
+
|
|
118
|
+
## See also
|
|
119
|
+
|
|
120
|
+
- [`pdfSignature`](./signature.md) · [`pdfTimestamp`](./timestamp.md)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfCertChain
|
|
3
|
+
category: pdf/sig
|
|
4
|
+
dependencies: [pdfErrors, pdfSigOids, asn1, pem]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfCertChain
|
|
11
|
+
|
|
12
|
+
> X.509 chain extraction and ordering — ISO 32000-2 §12.8.3.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfCertChain` | **Source** `packages/front/office/pdf/src/sig/certChain.js` | **Deps** `pdfErrors`, `pdfSigOids`, `asn1`, `pem` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
Parses the DER certificates embedded in a CMS blob (signature or timestamp), extracts `tbsCertificate` (issuer, subject, validity, subjectPublicKeyInfo), finds the issuer within a set of candidates, and validates chain ordering (leaf → CA → root). Performs **no** trust validation (no trust-anchor evaluation, no CRL/OCSP) — that is left to the caller.
|
|
17
|
+
|
|
18
|
+
## Resolve
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const cc = runtime.resolve('pdfCertChain');
|
|
22
|
+
// Returns: { parseCertificate, extractCertsFromCms, extractCertFromPem,
|
|
23
|
+
// findIssuer, validateChainOrder }
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## API
|
|
27
|
+
|
|
28
|
+
| Method | Signature | Returns |
|
|
29
|
+
|--------|-----------|---------|
|
|
30
|
+
| `parseCertificate` | `(der: Uint8Array, asn1Mod?) => Cert` | Decodes tbsCertificate. |
|
|
31
|
+
| `extractCertsFromCms` | `(blob, asn1Mod?, opts?) => Cert[]` | Looks up the SignedData's `certificates [0]` field; malformed certs are skipped and reported via `opts.warnings` if supplied. |
|
|
32
|
+
| `extractCertFromPem` | `(pemString, pemMod?, asn1Mod?) => Cert` | Decodes a single PEM certificate. |
|
|
33
|
+
| `findIssuer` | `(cert, candidates) => Cert \| null` | Matches by `candidate.subject === cert.issuer`. |
|
|
34
|
+
| `validateChainOrder` | `(chain: Cert[]) => { valid: boolean, errors: object[] }` | Checks ordering (each cert's `issuer` must equal the next cert's `subject`). |
|
|
35
|
+
|
|
36
|
+
### Shape `Cert`
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
{
|
|
40
|
+
version, serialNumber: Uint8Array,
|
|
41
|
+
issuer: string, subject: string, // rendered RDN sequences
|
|
42
|
+
notBefore: Date | null, notAfter: Date | null,
|
|
43
|
+
publicKey: Uint8Array, // raw SPKI BIT STRING value
|
|
44
|
+
keyAlgorithm: string, sigAlgorithm: string,
|
|
45
|
+
raw: Uint8Array // full certificate DER
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
### Extraction and sort
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
const cc = runtime.resolve('pdfCertChain');
|
|
55
|
+
const certs = cc.extractCertsFromCms(sig.contents);
|
|
56
|
+
const leaf = certs.find((c) => c.subject === pkcs7SignerSubject);
|
|
57
|
+
const issuer = cc.findIssuer(leaf, certs);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Order validation
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
const ok = cc.validateChainOrder([leaf, issuer, root]);
|
|
64
|
+
if (!ok.valid) console.warn(ok.errors);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Errors
|
|
68
|
+
|
|
69
|
+
| Code | Class | When |
|
|
70
|
+
|------|--------|------|
|
|
71
|
+
| `pdf/cert/malformed` | `ParseError` | Invalid ASN.1. |
|
|
72
|
+
| `pdf/cert/short` | `ParseError` | DER too short. |
|
|
73
|
+
| `pdf/cert/bad-tbs` | `ParseError` | Malformed tbsCertificate. |
|
|
74
|
+
| `pdf/cert/bad-input` | `ParseError` | `extractCertsFromCms` received a non-Uint8Array. |
|
|
75
|
+
| `pdf/cert/missing-fw` | `EncryptionError` | `asn1` bundle missing. |
|
|
76
|
+
| `pdf/cert/bad-pem-input` | `ParseError` | PEM argument is not a string. |
|
|
77
|
+
| `pdf/cert/missing-pem` | `EncryptionError` | `pem` provider not supplied. |
|
|
78
|
+
| `pdf/cert/pem-decode-failed` | `ParseError` | Malformed PEM. |
|
|
79
|
+
| `pdf/cert/empty-chain` | record `errors[]` | `validateChainOrder` received a non-array or empty chain. |
|
|
80
|
+
| `pdf/cert/chain-break` | record `errors[]` | A cert's `issuer` does not equal the next cert's `subject`. |
|
|
81
|
+
|
|
82
|
+
## See also
|
|
83
|
+
|
|
84
|
+
- [`pdfSignature`](./signature.md) · [`pdfTimestamp`](./timestamp.md)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfDssBuilder
|
|
3
|
+
category: pdf/sig
|
|
4
|
+
dependencies: [pdfErrors, pdfSha1, bitArray]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfDssBuilder
|
|
11
|
+
|
|
12
|
+
> PAdES-LT Document Security Store builder — ETSI EN 319 142-1 §5.4 / ISO 32000-2:2020 §12.8.4.3.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfDssBuilder` | **Source** `packages/front/office/pdf/src/sig/dss.js` | **Deps** `pdfErrors`, `pdfSha1`, `bitArray` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
Produces the indirect objects (cert/OCSP/CRL streams, the `/DSS` dict, and
|
|
17
|
+
optionally a `/VRI` dict) that a level-LT/LTA signer appends to an
|
|
18
|
+
already-signed PDF via [`pdfIncrementalWriter`](../document/incrementalWriter.md).
|
|
19
|
+
The factory **does not touch the byte buffer** — it returns a plan of
|
|
20
|
+
`{ num, gen, value }` updates plus the allocated DSS object number, so the
|
|
21
|
+
caller can also append an updated Catalog carrying `/DSS dssNum 0 R`.
|
|
22
|
+
`pdfSha1` is used solely for VRI key derivation (ISO 32000-2 §12.8.4.3
|
|
23
|
+
mandates SHA-1 of the signature value as the `/VRI` dict key — legacy
|
|
24
|
+
requirement, unrelated to signature strength).
|
|
25
|
+
|
|
26
|
+
## Resolve
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
const dss = runtime.resolve('pdfDssBuilder');
|
|
30
|
+
// Returns: { buildDss }
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## API
|
|
34
|
+
|
|
35
|
+
| Method | Signature | Returns |
|
|
36
|
+
|--------|-----------|---------|
|
|
37
|
+
| `buildDss` | `(args: BuildDssArgs) => BuildDssResult` | The update plan for an incremental append. It returns plaintext typed objects; when signing an encrypted document `pdfSign` encrypts the streams and strings before writing them. |
|
|
38
|
+
| `_refObj` / `_intObj` / `_nameObj` / `_strHexObj` / `_arrayObj` / `_dictObj` / `_streamObj` / `_sha1` / `_toHexUpper` / `_scanSignatureContentsHex` / `_pdfDate` | internal helpers | Returned for white-box tests only; not a stable contract — use `buildDss`. |
|
|
39
|
+
|
|
40
|
+
### `BuildDssArgs`
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
{
|
|
44
|
+
startNum: number, // required, >= 2 — first free object number
|
|
45
|
+
certs?: Uint8Array[], // DER-encoded certificates
|
|
46
|
+
ocsps?: Uint8Array[], // DER-encoded OCSP responses
|
|
47
|
+
crls?: Uint8Array[], // DER-encoded CRLs
|
|
48
|
+
vri?: { [sigHashHex: string]: {
|
|
49
|
+
certs?: number[] | Uint8Array[], // indices into certs[], or raw DER to promote
|
|
50
|
+
ocsps?: number[] | Uint8Array[],
|
|
51
|
+
crls?: number[] | Uint8Array[],
|
|
52
|
+
tu?: string, // PDF date string — validation-data-obtained time
|
|
53
|
+
ts?: Uint8Array // TimeStampToken DER, promoted to a /TS stream
|
|
54
|
+
} },
|
|
55
|
+
autoVri?: boolean, // scan parentBytes for every signature and synthesise VRI entries
|
|
56
|
+
parentBytes?: Uint8Array, // required when autoVri is true
|
|
57
|
+
vriTime?: Date // overrides `new Date()` for autoVri's /TU (tests: deterministic value)
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### `BuildDssResult`
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
{
|
|
65
|
+
updates: Array<{ num, gen, value }>, // ready for pdfIncrementalWriter.appendIncremental
|
|
66
|
+
dssNum: number,
|
|
67
|
+
lastNum: number,
|
|
68
|
+
certNums: number[], ocspNums: number[], crlNums: number[]
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Examples
|
|
73
|
+
|
|
74
|
+
### Explicit VRI keyed by signature-value SHA-1
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
const dss = runtime.resolve('pdfDssBuilder');
|
|
78
|
+
const built = dss.buildDss({
|
|
79
|
+
startNum: 10,
|
|
80
|
+
certs: [leafDer, caDer],
|
|
81
|
+
vri: { 'A1B2C3...': { certs: [0, 1], tu: '(D:20260803120000+00\'00\')' } }
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Auto-populated VRI over every signature in the parent bytes
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
const built = dss.buildDss({
|
|
89
|
+
startNum: 10,
|
|
90
|
+
certs: [leafDer, caDer], ocsps: [ocspDer],
|
|
91
|
+
autoVri: true, parentBytes: signedBytes
|
|
92
|
+
});
|
|
93
|
+
built.dssNum; // object number to reference from the updated Catalog
|
|
94
|
+
built.updates; // feed straight into pdfIncrementalWriter.appendIncremental
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Errors
|
|
98
|
+
|
|
99
|
+
All thrown as `ContractError`.
|
|
100
|
+
|
|
101
|
+
| Code | When |
|
|
102
|
+
|------|------|
|
|
103
|
+
| `pdf/dss/bad-startNum` | `startNum` missing or `< 2`. |
|
|
104
|
+
| `pdf/dss/bad-cert` / `bad-ocsp` / `bad-crl` | An entry in `certs`/`ocsps`/`crls` is not a `Uint8Array`. |
|
|
105
|
+
| `pdf/dss/vri-bad-index` | A `vri.<hex>.certs/ocsps/crls` numeric index is out of bounds of the corresponding parent list. |
|
|
106
|
+
|
|
107
|
+
## See also
|
|
108
|
+
|
|
109
|
+
- [`pdfSign`](./sign.md) — the only caller, for PAdES levels LT/LTA.
|
|
110
|
+
- [`pdfIncrementalWriter`](../document/incrementalWriter.md) — consumes `buildDss`'s `updates`.
|
|
111
|
+
- [`pdfSha1`](./sha1.md) — VRI key hash.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfSigOids
|
|
3
|
+
category: pdf/sig
|
|
4
|
+
dependencies: [asn1Oid]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfSigOids
|
|
11
|
+
|
|
12
|
+
> Shared OID dispatch tables for the `pdf/sig/*` family.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfSigOids` | **Source** `packages/front/office/pdf/src/sig/oids.js` | **Deps** `asn1Oid` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
A thin adapter over fw's `asn1Oid` (`@awacloud/fw/crypto/utils/asn1-oid.js`) — the
|
|
17
|
+
canonical OID database (~150 entries: PKCS, X.509, CMS, JOSE, PAdES, ECC,
|
|
18
|
+
AES). This module does **not** duplicate that data; it filters and
|
|
19
|
+
normalises a subset into the dispatch semantics `signature.js`, `sign.js`,
|
|
20
|
+
`timestamp.js` and `certChain.js` need — mapping OIDs to fw module names or
|
|
21
|
+
PDF-domain dispatch labels. Adding or renaming an OID happens in fw's
|
|
22
|
+
`asn1Oid` database; this module only decides how to surface an entry to PDF
|
|
23
|
+
callers. Every table is rebuilt by filtering fw's database, so an OID fw
|
|
24
|
+
doesn't recognise is silently dropped rather than fabricated.
|
|
25
|
+
|
|
26
|
+
## Resolve
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
const oids = runtime.resolve('pdfSigOids');
|
|
30
|
+
// Returns: { DIGEST_OIDS, SIG_DISPATCH_OIDS, KEY_ALG_OIDS, SIG_ALG_OIDS_VERBOSE,
|
|
31
|
+
// OID_TST_INFO, OID_AA_TIMESTAMP,
|
|
32
|
+
// lookupDigest, lookupSigAlg, lookupKeyAlg, lookupSigVerbose, shortOid }
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## API
|
|
36
|
+
|
|
37
|
+
| Member | Shape | Description |
|
|
38
|
+
|--------|-------|--------------|
|
|
39
|
+
| `DIGEST_OIDS` | `Object.freeze({ [oid]: 'sha256'\|'sha384'\|'sha512'\|'sha1' })` | Digest OID → fw hash module name. |
|
|
40
|
+
| `SIG_DISPATCH_OIDS` | `Object.freeze({ [oid]: 'rsa'\|'rsa-pss'\|'ecc'\|'ed25519' })` | Signature-algorithm OID → fw verifier dispatch name (all PKCS#1 v1.5 RSA OIDs map to `'rsa'`). |
|
|
41
|
+
| `KEY_ALG_OIDS` | `Object.freeze({ [oid]: 'rsa'\|'ecc'\|'ed25519'\|'ed448' })` | SPKI base-algorithm OID (no hash suffix) → short algorithm name. |
|
|
42
|
+
| `SIG_ALG_OIDS_VERBOSE` | `Object.freeze({ [oid]: string })` | Certificate `sigAlgorithm` verbose name (e.g. `'sha256WithRSAEncryption'`, `'ecdsa-with-SHA256'`, `'rsassa-pss'`). |
|
|
43
|
+
| `OID_TST_INFO` | `string` | `id-ct-TSTInfo` (`1.2.840.113549.1.9.16.1.4`), RFC 3161. |
|
|
44
|
+
| `OID_AA_TIMESTAMP` | `string` | `id-aa-timeStampToken` (`1.2.840.113549.1.9.16.2.14`), RFC 3161. |
|
|
45
|
+
| `lookupDigest(oid)` | `(oid: string) => string \| null` | `DIGEST_OIDS[oid]` or `null`. |
|
|
46
|
+
| `lookupSigAlg(oid)` | `(oid: string) => string \| null` | `SIG_DISPATCH_OIDS[oid]` or `null`. |
|
|
47
|
+
| `lookupKeyAlg(oid)` | `(oid: string) => string \| null` | `KEY_ALG_OIDS[oid]` or `null`. |
|
|
48
|
+
| `lookupSigVerbose(oid)` | `(oid: string) => string \| null` | `SIG_ALG_OIDS_VERBOSE[oid]` or `null`. |
|
|
49
|
+
| `shortOid(oid)` | `(oid: string) => string` | DN attribute OID → short form (`'CN'`, `'O'`, `'OU'`, `'C'`, `'E'`…); falls back to the OID string itself when unrecognised. |
|
|
50
|
+
|
|
51
|
+
## Examples
|
|
52
|
+
|
|
53
|
+
### Resolving a certificate's signature algorithm
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
const oids = runtime.resolve('pdfSigOids');
|
|
57
|
+
const dispatch = oids.lookupSigAlg('1.2.840.113549.1.1.11'); // 'rsa'
|
|
58
|
+
const verbose = oids.lookupSigVerbose('1.2.840.113549.1.1.11'); // 'sha256WithRSAEncryption'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Rendering a Distinguished Name
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
const oids = runtime.resolve('pdfSigOids');
|
|
65
|
+
const parts = rdnAttributes.map(({ oid, value }) => `${oids.shortOid(oid)}=${value}`);
|
|
66
|
+
const dn = parts.join(', '); // e.g. 'CN=Example, O=Acme, C=FR'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Errors
|
|
70
|
+
|
|
71
|
+
None — every lookup returns `null` (or falls back to the OID string, for
|
|
72
|
+
`shortOid`) rather than throwing on an unrecognised OID.
|
|
73
|
+
|
|
74
|
+
## See also
|
|
75
|
+
|
|
76
|
+
- [`pdfSignature`](./signature.md) · [`pdfSign`](./sign.md) · [`pdfTimestamp`](./timestamp.md) · [`pdfCertChain`](./certChain.md) — all consumers.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfSha1
|
|
3
|
+
category: pdf/sig
|
|
4
|
+
dependencies: [bitArray, utf8]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfSha1
|
|
11
|
+
|
|
12
|
+
> SHA-1 (FIPS 180-4 §6.1) — PDF-local legacy hash, DSS `/VRI` keys only.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfSha1` | **Source** `packages/front/office/pdf/src/sig/sha1.js` | **Deps** `bitArray`, `utf8` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
SHA-1 is cryptographically broken for collision resistance and **must not**
|
|
17
|
+
be used for new signatures, MACs, or password hashing. This module exists
|
|
18
|
+
solely because ISO 32000-2 §12.8.4.3 mandates SHA-1 of the signature value
|
|
19
|
+
as the DSS `/VRI` dict key — kept in `@awacloud/pdf` rather than `@awacloud/fw` so the
|
|
20
|
+
legacy-only nature stays obvious to anyone reading fw's hash family
|
|
21
|
+
(`sha256`/`sha384`/`sha512` only, no `sha1`). Exposes the same shape as fw's
|
|
22
|
+
hash modules (`hash(data)` one-shot, `fn()` constructor) so dispatch code
|
|
23
|
+
can treat it uniformly.
|
|
24
|
+
|
|
25
|
+
## Resolve
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
const sha1 = runtime.resolve('pdfSha1');
|
|
29
|
+
// Returns: { fn, hash }
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## API
|
|
33
|
+
|
|
34
|
+
| Method | Signature | Returns |
|
|
35
|
+
|--------|-----------|---------|
|
|
36
|
+
| `hash` | `(data: Uint8Array \| bitArray \| string) => bitArray` | One-shot digest (20 bytes as a fw `bitArray`). |
|
|
37
|
+
| `fn` | `(other?: HashState) => HashState` | Streaming constructor — `{ reset, update, finalize, blockSize: 512 }`. Passing an existing instance clones its internal state. |
|
|
38
|
+
|
|
39
|
+
`update(data)` accepts a `string` (UTF-8 encoded via `utf8.toBytes` then
|
|
40
|
+
converted to a `bitArray`) or an already-encoded `bitArray`.
|
|
41
|
+
|
|
42
|
+
## Examples
|
|
43
|
+
|
|
44
|
+
### One-shot digest
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
const sha1 = runtime.resolve('pdfSha1');
|
|
48
|
+
const bitArrayMod = runtime.resolve('bitArray');
|
|
49
|
+
const digest = sha1.hash(bitArrayMod.ui8_to_ba(signatureValueBytes));
|
|
50
|
+
const bytes = bitArrayMod.ba_to_ui8(digest); // 20 bytes
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Streaming
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
const sha1 = runtime.resolve('pdfSha1');
|
|
57
|
+
const ctx = sha1.fn();
|
|
58
|
+
ctx.update(chunk1).update(chunk2);
|
|
59
|
+
const digest = ctx.finalize();
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Errors
|
|
63
|
+
|
|
64
|
+
None thrown. `update()` guards against hashing more than 2^53 − 1 bits by
|
|
65
|
+
`console.warn`-ing and returning `false` instead of throwing — a limit that
|
|
66
|
+
is unreachable for the DSS VRI-key use case (hashing a single signature
|
|
67
|
+
value, at most a few KB).
|
|
68
|
+
|
|
69
|
+
## See also
|
|
70
|
+
|
|
71
|
+
- [`pdfDssBuilder`](./dss.md) — the only consumer, for `/VRI` key derivation.
|
|
72
|
+
- [`pdfSignature`](./signature.md) — uses fw's `sha256`/`sha384`/`sha512` for the actual signature digest.
|