pdf-lite 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/.commitlintrc.cjs +25 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
- package/.github/workflows/docs.yaml +93 -0
- package/.github/workflows/prepare-release.yaml +79 -0
- package/.github/workflows/release.yaml +80 -0
- package/.github/workflows/test.yaml +35 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +1 -0
- package/.prettierignore +4 -0
- package/.prettierrc +4 -0
- package/CONTRIBUTING.md +109 -0
- package/EXAMPLES.md +1515 -0
- package/LICENSE +21 -0
- package/README.md +285 -0
- package/examples/001-create-pdf.ts +112 -0
- package/examples/002-create-encrypted-pdf.ts +121 -0
- package/examples/003-sign-pdf.ts +347 -0
- package/examples/004-incremental-update.ts +206 -0
- package/examples/005-modify-acroform.ts +374 -0
- package/examples/006-tokeniser-example.ts +131 -0
- package/examples/007-decoder-example.ts +197 -0
- package/package.json +72 -0
- package/packages/pdf-lite/README.md +3 -0
- package/packages/pdf-lite/package.json +68 -0
- package/packages/pdf-lite/scripts/create-encryption-tests.sh +41 -0
- package/packages/pdf-lite/scripts/gen-signing-keys.sh +290 -0
- package/packages/pdf-lite/scripts/generate-all-signing-keys.sh +70 -0
- package/packages/pdf-lite/src/core/decoder.ts +454 -0
- package/packages/pdf-lite/src/core/generators.ts +128 -0
- package/packages/pdf-lite/src/core/incremental-parser.ts +221 -0
- package/packages/pdf-lite/src/core/index.ts +2 -0
- package/packages/pdf-lite/src/core/objects/pdf-array.ts +54 -0
- package/packages/pdf-lite/src/core/objects/pdf-boolean.ts +19 -0
- package/packages/pdf-lite/src/core/objects/pdf-comment.ts +50 -0
- package/packages/pdf-lite/src/core/objects/pdf-date.ts +74 -0
- package/packages/pdf-lite/src/core/objects/pdf-dictionary.ts +171 -0
- package/packages/pdf-lite/src/core/objects/pdf-hexadecimal.ts +54 -0
- package/packages/pdf-lite/src/core/objects/pdf-indirect-object.ts +137 -0
- package/packages/pdf-lite/src/core/objects/pdf-name.ts +19 -0
- package/packages/pdf-lite/src/core/objects/pdf-null.ts +15 -0
- package/packages/pdf-lite/src/core/objects/pdf-number.ts +98 -0
- package/packages/pdf-lite/src/core/objects/pdf-object-reference.ts +30 -0
- package/packages/pdf-lite/src/core/objects/pdf-object.ts +107 -0
- package/packages/pdf-lite/src/core/objects/pdf-start-xref.ts +39 -0
- package/packages/pdf-lite/src/core/objects/pdf-stream.ts +687 -0
- package/packages/pdf-lite/src/core/objects/pdf-string.ts +38 -0
- package/packages/pdf-lite/src/core/objects/pdf-trailer.ts +57 -0
- package/packages/pdf-lite/src/core/objects/pdf-xref-table.ts +264 -0
- package/packages/pdf-lite/src/core/parser.ts +22 -0
- package/packages/pdf-lite/src/core/ref.ts +102 -0
- package/packages/pdf-lite/src/core/serializer.ts +68 -0
- package/packages/pdf-lite/src/core/streams/object-stream.ts +20 -0
- package/packages/pdf-lite/src/core/tokeniser.ts +687 -0
- package/packages/pdf-lite/src/core/tokens/boolean-token.ts +20 -0
- package/packages/pdf-lite/src/core/tokens/byte-offset-token.ts +20 -0
- package/packages/pdf-lite/src/core/tokens/comment-token.ts +32 -0
- package/packages/pdf-lite/src/core/tokens/end-array-token.ts +10 -0
- package/packages/pdf-lite/src/core/tokens/end-dictionary-token.ts +10 -0
- package/packages/pdf-lite/src/core/tokens/end-object-token.ts +10 -0
- package/packages/pdf-lite/src/core/tokens/end-stream-token.ts +11 -0
- package/packages/pdf-lite/src/core/tokens/hexadecimal-token.ts +22 -0
- package/packages/pdf-lite/src/core/tokens/name-token.ts +19 -0
- package/packages/pdf-lite/src/core/tokens/null-token.ts +9 -0
- package/packages/pdf-lite/src/core/tokens/number-token.ts +164 -0
- package/packages/pdf-lite/src/core/tokens/object-reference-token.ts +24 -0
- package/packages/pdf-lite/src/core/tokens/start-array-token.ts +10 -0
- package/packages/pdf-lite/src/core/tokens/start-dictionary-token.ts +10 -0
- package/packages/pdf-lite/src/core/tokens/start-object-token.ts +28 -0
- package/packages/pdf-lite/src/core/tokens/start-stream-token.ts +52 -0
- package/packages/pdf-lite/src/core/tokens/start-xref-token.ts +10 -0
- package/packages/pdf-lite/src/core/tokens/stream-chunk-token.ts +8 -0
- package/packages/pdf-lite/src/core/tokens/string-token.ts +17 -0
- package/packages/pdf-lite/src/core/tokens/token.ts +43 -0
- package/packages/pdf-lite/src/core/tokens/trailer-token.ts +12 -0
- package/packages/pdf-lite/src/core/tokens/whitespace-token.ts +43 -0
- package/packages/pdf-lite/src/core/tokens/xref-table-entry-token.ts +65 -0
- package/packages/pdf-lite/src/core/tokens/xref-table-section-start-token.ts +31 -0
- package/packages/pdf-lite/src/core/tokens/xref-table-start-token.ts +13 -0
- package/packages/pdf-lite/src/crypto/ciphers/aes128.ts +63 -0
- package/packages/pdf-lite/src/crypto/ciphers/aes256.ts +50 -0
- package/packages/pdf-lite/src/crypto/ciphers/rc4.ts +82 -0
- package/packages/pdf-lite/src/crypto/constants.ts +10 -0
- package/packages/pdf-lite/src/crypto/key-derivation/key-derivation-aes256.ts +213 -0
- package/packages/pdf-lite/src/crypto/key-derivation/key-derivation.ts +122 -0
- package/packages/pdf-lite/src/crypto/key-gen/key-gen-aes256.ts +79 -0
- package/packages/pdf-lite/src/crypto/key-gen/key-gen-rc4-128.ts +190 -0
- package/packages/pdf-lite/src/crypto/key-gen/key-gen-rc4-40.ts +129 -0
- package/packages/pdf-lite/src/crypto/types.ts +6 -0
- package/packages/pdf-lite/src/crypto/utils.ts +81 -0
- package/packages/pdf-lite/src/filters/ascii85.ts +128 -0
- package/packages/pdf-lite/src/filters/asciihex.ts +55 -0
- package/packages/pdf-lite/src/filters/flate.ts +39 -0
- package/packages/pdf-lite/src/filters/lzw.ts +144 -0
- package/packages/pdf-lite/src/filters/pass-through.ts +37 -0
- package/packages/pdf-lite/src/filters/runlength.ts +92 -0
- package/packages/pdf-lite/src/filters/types.ts +21 -0
- package/packages/pdf-lite/src/index.ts +4 -0
- package/packages/pdf-lite/src/pdf/errors.ts +5 -0
- package/packages/pdf-lite/src/pdf/index.ts +4 -0
- package/packages/pdf-lite/src/pdf/pdf-document.ts +924 -0
- package/packages/pdf-lite/src/pdf/pdf-reader.ts +57 -0
- package/packages/pdf-lite/src/pdf/pdf-revision.ts +234 -0
- package/packages/pdf-lite/src/pdf/pdf-xref-lookup.ts +527 -0
- package/packages/pdf-lite/src/security/crypt-filters/aesv2.ts +58 -0
- package/packages/pdf-lite/src/security/crypt-filters/aesv3.ts +56 -0
- package/packages/pdf-lite/src/security/crypt-filters/base.ts +140 -0
- package/packages/pdf-lite/src/security/crypt-filters/identity.ts +40 -0
- package/packages/pdf-lite/src/security/crypt-filters/v2.ts +59 -0
- package/packages/pdf-lite/src/security/handlers/base.ts +625 -0
- package/packages/pdf-lite/src/security/handlers/pubSec.ts +413 -0
- package/packages/pdf-lite/src/security/handlers/utils.ts +304 -0
- package/packages/pdf-lite/src/security/handlers/v1.ts +225 -0
- package/packages/pdf-lite/src/security/handlers/v2.ts +128 -0
- package/packages/pdf-lite/src/security/handlers/v4.ts +379 -0
- package/packages/pdf-lite/src/security/handlers/v5.ts +298 -0
- package/packages/pdf-lite/src/security/types.ts +158 -0
- package/packages/pdf-lite/src/signing/document-security-store.ts +224 -0
- package/packages/pdf-lite/src/signing/index.ts +3 -0
- package/packages/pdf-lite/src/signing/signatures/adbe-pkcs7-detached.ts +154 -0
- package/packages/pdf-lite/src/signing/signatures/adbe-pkcs7-sha1.ts +161 -0
- package/packages/pdf-lite/src/signing/signatures/adbe-x509-rsa-sha1.ts +106 -0
- package/packages/pdf-lite/src/signing/signatures/base.ts +229 -0
- package/packages/pdf-lite/src/signing/signatures/etsi-cades-detached.ts +229 -0
- package/packages/pdf-lite/src/signing/signatures/etsi-rfc3161.ts +92 -0
- package/packages/pdf-lite/src/signing/signatures/index.ts +6 -0
- package/packages/pdf-lite/src/signing/signer.ts +120 -0
- package/packages/pdf-lite/src/signing/types.ts +86 -0
- package/packages/pdf-lite/src/signing/utils.ts +71 -0
- package/packages/pdf-lite/src/types.ts +44 -0
- package/packages/pdf-lite/src/utils/IterableReadableStream.ts +30 -0
- package/packages/pdf-lite/src/utils/algos.ts +446 -0
- package/packages/pdf-lite/src/utils/assert.ts +42 -0
- package/packages/pdf-lite/src/utils/bytesToHex.ts +18 -0
- package/packages/pdf-lite/src/utils/bytesToHexBytes.ts +27 -0
- package/packages/pdf-lite/src/utils/bytesToString.ts +17 -0
- package/packages/pdf-lite/src/utils/concatUint8Arrays.ts +26 -0
- package/packages/pdf-lite/src/utils/escapeString.ts +49 -0
- package/packages/pdf-lite/src/utils/hexBytesToBytes.ts +22 -0
- package/packages/pdf-lite/src/utils/hexBytesToString.ts +21 -0
- package/packages/pdf-lite/src/utils/hexToBytes.ts +18 -0
- package/packages/pdf-lite/src/utils/padBytes.ts +25 -0
- package/packages/pdf-lite/src/utils/predictors.ts +332 -0
- package/packages/pdf-lite/src/utils/replaceInBuffer.ts +56 -0
- package/packages/pdf-lite/src/utils/stringToBytes.ts +22 -0
- package/packages/pdf-lite/src/utils/stringToHexBytes.ts +23 -0
- package/packages/pdf-lite/src/utils/unescapeString.ts +123 -0
- package/packages/pdf-lite/test/acceptance/__snapshots__/versions.node.test.ts.snap +60766 -0
- package/packages/pdf-lite/test/acceptance/fixtures/1.3/basic.pdf +0 -0
- package/packages/pdf-lite/test/acceptance/fixtures/1.4/basic-aes-128.pdf +0 -0
- package/packages/pdf-lite/test/acceptance/fixtures/1.4/basic-aes-256.pdf +0 -0
- package/packages/pdf-lite/test/acceptance/fixtures/1.4/basic-rc4-128.pdf +0 -0
- package/packages/pdf-lite/test/acceptance/fixtures/1.4/basic-rc4-40.pdf +0 -0
- package/packages/pdf-lite/test/acceptance/fixtures/1.4/basic.pdf +0 -0
- package/packages/pdf-lite/test/acceptance/fixtures/1.5/basic.pdf +0 -0
- package/packages/pdf-lite/test/acceptance/fixtures/1.6/basic.pdf +0 -0
- package/packages/pdf-lite/test/acceptance/fixtures/1.7/basic.pdf +0 -0
- package/packages/pdf-lite/test/acceptance/fixtures/2.0/basic-aes-128.pdf +43 -0
- package/packages/pdf-lite/test/acceptance/fixtures/2.0/basic-aes-256.pdf +43 -0
- package/packages/pdf-lite/test/acceptance/fixtures/2.0/basic-rc4-128.pdf +43 -0
- package/packages/pdf-lite/test/acceptance/fixtures/2.0/basic-rc4-40.pdf +44 -0
- package/packages/pdf-lite/test/acceptance/fixtures/2.0/basic.pdf +79 -0
- package/packages/pdf-lite/test/acceptance/versions.node.test.ts +41 -0
- package/packages/pdf-lite/test/unit/__snapshots__/decoder.node.test.ts.snap +86947 -0
- package/packages/pdf-lite/test/unit/__snapshots__/tokeniser.node.test.ts.snap +131829 -0
- package/packages/pdf-lite/test/unit/ciphers.test.ts +61 -0
- package/packages/pdf-lite/test/unit/decoder.node.test.ts +21 -0
- package/packages/pdf-lite/test/unit/decoder.test.ts +567 -0
- package/packages/pdf-lite/test/unit/filters.test.ts +67 -0
- package/packages/pdf-lite/test/unit/fixtures/basic.pdf +0 -0
- package/packages/pdf-lite/test/unit/fixtures/encrypted_v1/basic-aes-128.pdf +0 -0
- package/packages/pdf-lite/test/unit/fixtures/encrypted_v1/basic-aes-256.pdf +0 -0
- package/packages/pdf-lite/test/unit/fixtures/encrypted_v1/basic-rc4-128.pdf +0 -0
- package/packages/pdf-lite/test/unit/fixtures/encrypted_v1/basic-rc4-40.pdf +43 -0
- package/packages/pdf-lite/test/unit/fixtures/protectedAdobeLivecycle.pdf +0 -0
- package/packages/pdf-lite/test/unit/fixtures/rsa-2048/index.ts +187 -0
- package/packages/pdf-lite/test/unit/fixtures/template.pdf +0 -0
- package/packages/pdf-lite/test/unit/incremental-update.test.ts +0 -0
- package/packages/pdf-lite/test/unit/objects.test.ts +0 -0
- package/packages/pdf-lite/test/unit/pdf-document-signing.test.ts +0 -0
- package/packages/pdf-lite/test/unit/pdf-revision.test.ts +195 -0
- package/packages/pdf-lite/test/unit/pdf.browser.test.ts +0 -0
- package/packages/pdf-lite/test/unit/predictors.test.ts +226 -0
- package/packages/pdf-lite/test/unit/ref.test.ts +158 -0
- package/packages/pdf-lite/test/unit/security-handlers.test.ts +645 -0
- package/packages/pdf-lite/test/unit/serializer.test.ts +81 -0
- package/packages/pdf-lite/test/unit/signature-objects.test.ts +814 -0
- package/packages/pdf-lite/test/unit/string-escaping.test.ts +84 -0
- package/packages/pdf-lite/test/unit/tokeniser.node.test.ts +38 -0
- package/packages/pdf-lite/test/unit/tokeniser.test.ts +1213 -0
- package/packages/pdf-lite/test/unit/utils.test.ts +248 -0
- package/packages/pdf-lite/test/unit/xref-lookup.test.ts +72 -0
- package/packages/pdf-lite/tsconfig.json +4 -0
- package/packages/pdf-lite/tsconfig.prod.json +8 -0
- package/packages/pdf-lite/typedoc.json +14 -0
- package/packages/pdf-lite/vitest.config.ts +43 -0
- package/pnpm-workspace.yaml +2 -0
- package/renovate.json +34 -0
- package/scripts/build-examples.ts +30 -0
- package/scripts/bump-version.sh +56 -0
- package/scripts/gen-html-docs.sh +21 -0
- package/scripts/gen-md-docs.sh +15 -0
- package/scripts/prepare-release.sh +33 -0
- package/tsconfig.json +22 -0
- package/tsconfig.prod.json +12 -0
- package/typedoc.json +34 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { PdfArray } from '../core/objects/pdf-array'
|
|
2
|
+
import { PdfBoolean } from '../core/objects/pdf-boolean'
|
|
3
|
+
import { PdfDictionary } from '../core/objects/pdf-dictionary'
|
|
4
|
+
import { PdfHexadecimal } from '../core/objects/pdf-hexadecimal'
|
|
5
|
+
import { PdfIndirectObject } from '../core/objects/pdf-indirect-object'
|
|
6
|
+
import { PdfName } from '../core/objects/pdf-name'
|
|
7
|
+
import { PdfNumber } from '../core/objects/pdf-number'
|
|
8
|
+
import { PdfString } from '../core/objects/pdf-string'
|
|
9
|
+
import { ByteArray } from '../types'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Represents the PDF document ID array containing two hexadecimal identifiers.
|
|
13
|
+
* The first element is the permanent ID assigned when the document is created,
|
|
14
|
+
* and the second is updated when the document is modified.
|
|
15
|
+
*/
|
|
16
|
+
export type PdfId = PdfArray<PdfHexadecimal>
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Dictionary defining a crypt filter for PDF encryption.
|
|
20
|
+
* Specifies the encryption method and authentication event trigger.
|
|
21
|
+
*/
|
|
22
|
+
export type PdfCryptFilterDictionary = PdfDictionary<{
|
|
23
|
+
AuthEvent: PdfName<'DocOpen' | 'EFOpen'>
|
|
24
|
+
CFM: PdfName<'None' | 'V2' | 'AESV2' | 'AESV3'>
|
|
25
|
+
Length?: PdfNumber
|
|
26
|
+
}>
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The encryption dictionary stored in the PDF trailer.
|
|
30
|
+
* Contains all encryption parameters including filter type, version, revision,
|
|
31
|
+
* owner/user keys, permissions, and crypt filter configurations.
|
|
32
|
+
*/
|
|
33
|
+
export type PdfEncryptionDictionary = PdfDictionary<{
|
|
34
|
+
Filter: PdfName<'Standard' | 'Adobe.PubSec'>
|
|
35
|
+
SubFilter?: PdfName<'adbe.pkcs7.s3' | 'adbe.pkcs7.s4' | 'adbe.pkcs7.s5'>
|
|
36
|
+
V: PdfNumber
|
|
37
|
+
R: PdfNumber
|
|
38
|
+
O: PdfString | PdfHexadecimal
|
|
39
|
+
OE?: PdfString | PdfHexadecimal
|
|
40
|
+
U: PdfString | PdfHexadecimal
|
|
41
|
+
UE?: PdfString | PdfHexadecimal
|
|
42
|
+
P: PdfNumber
|
|
43
|
+
Perms?: PdfString | PdfHexadecimal
|
|
44
|
+
Length: PdfNumber
|
|
45
|
+
CF?: PdfDictionary<{
|
|
46
|
+
[key: string]: PdfCryptFilterDictionary
|
|
47
|
+
}>
|
|
48
|
+
StmF?: PdfName
|
|
49
|
+
StrF?: PdfName
|
|
50
|
+
EFF?: PdfName
|
|
51
|
+
EncryptMetadata?: PdfBoolean
|
|
52
|
+
ID?: PdfArray<PdfHexadecimal>
|
|
53
|
+
Recipients?: PdfArray<PdfHexadecimal>
|
|
54
|
+
}>
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* An indirect object containing the encryption dictionary.
|
|
58
|
+
*/
|
|
59
|
+
export type PdfEncryptionDictionaryObject =
|
|
60
|
+
PdfIndirectObject<PdfEncryptionDictionary>
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Specifies the type of content being encrypted.
|
|
64
|
+
* - 'string': PDF string objects
|
|
65
|
+
* - 'stream': PDF stream objects
|
|
66
|
+
* - 'file': Embedded file streams
|
|
67
|
+
*/
|
|
68
|
+
export type CryptFilterType = 'string' | 'stream' | 'file'
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Recipient information for public key encryption.
|
|
72
|
+
* Contains the certificate for encryption and optional private key for decryption.
|
|
73
|
+
*/
|
|
74
|
+
export type PdfEncryptionRecipient = {
|
|
75
|
+
certificate?: ByteArray
|
|
76
|
+
privateKey?: ByteArray
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Supported encryption algorithm types.
|
|
81
|
+
* - 'RC4-40': 40-bit RC4 encryption (weak, legacy)
|
|
82
|
+
* - 'RC4-128': 128-bit RC4 encryption (legacy)
|
|
83
|
+
* - 'AES-128-CBC': 128-bit AES in CBC mode
|
|
84
|
+
* - 'AES-256-CBC': 256-bit AES in CBC mode (recommended)
|
|
85
|
+
* - 'none': No encryption (identity filter)
|
|
86
|
+
*/
|
|
87
|
+
export type PdfEncryptionAlgorithmType =
|
|
88
|
+
| 'RC4-40'
|
|
89
|
+
| 'RC4-128'
|
|
90
|
+
| 'AES-128-CBC'
|
|
91
|
+
| 'AES-256-CBC'
|
|
92
|
+
| 'none'
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* RC4-40 encryption configuration.
|
|
96
|
+
*/
|
|
97
|
+
type Rc40 = {
|
|
98
|
+
default: 'RC4-40'
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* RC4-128 encryption configuration.
|
|
103
|
+
*/
|
|
104
|
+
type Rc128 = {
|
|
105
|
+
default: 'RC4-128'
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* AES-128 encryption configuration with optional per-type crypt filters.
|
|
110
|
+
*/
|
|
111
|
+
type Aes128WithCryptFilters = {
|
|
112
|
+
default: 'AES-128-CBC'
|
|
113
|
+
streams?: 'AES-128-CBC' | 'RC4-128' | 'RC4-40' | 'none'
|
|
114
|
+
strings?: 'AES-128-CBC' | 'RC4-128' | 'RC4-40' | 'none'
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* AES-256 encryption configuration with optional per-type crypt filters.
|
|
119
|
+
*/
|
|
120
|
+
type Aes256 = {
|
|
121
|
+
default: 'AES-256-CBC' | 'none'
|
|
122
|
+
streams?: 'AES-256-CBC' | 'AES-128-CBC' | 'RC4-128' | 'none'
|
|
123
|
+
files?: 'AES-256-CBC' | 'AES-128-CBC' | 'RC4-128' | 'none'
|
|
124
|
+
strings?: 'AES-256-CBC' | 'AES-128-CBC' | 'RC4-128' | 'none'
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Union of all encryption algorithm configuration options.
|
|
129
|
+
*/
|
|
130
|
+
export type PdfEncryptionAlgorithmOptions =
|
|
131
|
+
| Rc40
|
|
132
|
+
| Rc128
|
|
133
|
+
| Aes128WithCryptFilters
|
|
134
|
+
| Aes256
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Options for configuring PDF encryption.
|
|
138
|
+
* Includes encryption method, passwords, document ID, and permission settings.
|
|
139
|
+
*/
|
|
140
|
+
export type PdfEncryptionOptions = {
|
|
141
|
+
method?: PdfEncryptionAlgorithmOptions
|
|
142
|
+
password?: ByteArray | string
|
|
143
|
+
ownerPassword?: ByteArray | string
|
|
144
|
+
documentId?: PdfId | ByteArray | string
|
|
145
|
+
encryptMetadata?: boolean
|
|
146
|
+
recipients?: PdfEncryptionRecipient[]
|
|
147
|
+
permissions?: {
|
|
148
|
+
print?: boolean
|
|
149
|
+
modify?: boolean
|
|
150
|
+
copy?: boolean
|
|
151
|
+
annotate?: boolean
|
|
152
|
+
fill?: boolean
|
|
153
|
+
extract?: boolean
|
|
154
|
+
assemble?: boolean
|
|
155
|
+
printHighQuality?: boolean
|
|
156
|
+
all?: boolean
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { PdfArray } from '../core/objects/pdf-array'
|
|
2
|
+
import { PdfDate } from '../core/objects/pdf-date'
|
|
3
|
+
import { PdfDictionary } from '../core/objects/pdf-dictionary'
|
|
4
|
+
import { PdfIndirectObject } from '../core/objects/pdf-indirect-object'
|
|
5
|
+
import { PdfName } from '../core/objects/pdf-name'
|
|
6
|
+
import { PdfObjectReference } from '../core/objects/pdf-object-reference'
|
|
7
|
+
import { PdfStream } from '../core/objects/pdf-stream'
|
|
8
|
+
import { PdfString } from '../core/objects/pdf-string'
|
|
9
|
+
import { PdfDocument } from '../pdf/pdf-document'
|
|
10
|
+
import { ByteArray } from '../types'
|
|
11
|
+
import { RevocationInfo } from './types'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Indirect object containing a certificate stream.
|
|
15
|
+
*/
|
|
16
|
+
export class PdfCertObject extends PdfIndirectObject<PdfStream> {}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Indirect object containing a CRL stream.
|
|
20
|
+
*/
|
|
21
|
+
export class PdfCrlObject extends PdfIndirectObject<PdfStream> {}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Indirect object containing an OCSP response stream.
|
|
25
|
+
*/
|
|
26
|
+
export class PdfOcspObject extends PdfIndirectObject<PdfStream> {}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Validation Related Information (VRI) dictionary.
|
|
30
|
+
* Associates revocation data with specific certificate hashes.
|
|
31
|
+
*/
|
|
32
|
+
export type PdfVriObject = PdfIndirectObject<
|
|
33
|
+
PdfDictionary<{
|
|
34
|
+
[CertHash: string]: PdfDictionary<{
|
|
35
|
+
Type?: PdfName<'VRI'>
|
|
36
|
+
Cert?: PdfObjectReference
|
|
37
|
+
OCSP?: PdfObjectReference
|
|
38
|
+
CRL?: PdfObjectReference
|
|
39
|
+
TU?: PdfDate
|
|
40
|
+
TS?: PdfString
|
|
41
|
+
}>
|
|
42
|
+
}>
|
|
43
|
+
>
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Dictionary for the Document Security Store (DSS).
|
|
47
|
+
* Contains arrays of certificates, CRLs, OCSPs, and VRI entries.
|
|
48
|
+
*/
|
|
49
|
+
export class PdfDocumentSecurityStoreDictionary extends PdfDictionary<{
|
|
50
|
+
Type?: PdfName<'DSS'>
|
|
51
|
+
VRI?: PdfObjectReference
|
|
52
|
+
OCSPs?: PdfArray<PdfObjectReference>
|
|
53
|
+
CRLs?: PdfArray<PdfObjectReference>
|
|
54
|
+
Certs?: PdfArray<PdfObjectReference>
|
|
55
|
+
}> {}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Document Security Store (DSS) object for PAdES LTV signatures.
|
|
59
|
+
* Stores validation data (certificates, CRLs, OCSPs) for long-term validation.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const dss = new PdfDocumentSecurityStoreObject(document)
|
|
64
|
+
* await dss.addCert(certificateBytes)
|
|
65
|
+
* await dss.addCrl(crlBytes)
|
|
66
|
+
* await dss.addOcsp(ocspBytes)
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export class PdfDocumentSecurityStoreObject extends PdfIndirectObject<PdfDocumentSecurityStoreDictionary> {
|
|
70
|
+
/** Reference to the parent document. */
|
|
71
|
+
private document: PdfDocument
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Creates a new DSS object.
|
|
75
|
+
*
|
|
76
|
+
* @param document - The parent PDF document.
|
|
77
|
+
* @param content - Optional pre-existing DSS dictionary.
|
|
78
|
+
*/
|
|
79
|
+
constructor(
|
|
80
|
+
document: PdfDocument,
|
|
81
|
+
content?: PdfDocumentSecurityStoreDictionary,
|
|
82
|
+
) {
|
|
83
|
+
super(content ?? new PdfDocumentSecurityStoreDictionary())
|
|
84
|
+
this.document = document
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Adds an OCSP response to the DSS, avoiding duplicates.
|
|
89
|
+
*
|
|
90
|
+
* @param ocsp - The DER-encoded OCSP response.
|
|
91
|
+
* @returns The created or existing OCSP object.
|
|
92
|
+
*/
|
|
93
|
+
async addOcsp(ocsp: ByteArray): Promise<PdfOcspObject> {
|
|
94
|
+
const newOcsp = new PdfStream(ocsp)
|
|
95
|
+
let ocspArray = this.content.get('OCSPs')
|
|
96
|
+
|
|
97
|
+
const currentOcsps = (await Promise.all(
|
|
98
|
+
(ocspArray?.items ?? []).map(async (ref) => {
|
|
99
|
+
const obj = await this.document.readObject(ref)
|
|
100
|
+
return obj
|
|
101
|
+
}),
|
|
102
|
+
)) as PdfIndirectObject<PdfStream>[]
|
|
103
|
+
|
|
104
|
+
for (const existingOcsp of currentOcsps) {
|
|
105
|
+
if (existingOcsp.content.equals(newOcsp)) {
|
|
106
|
+
return existingOcsp as PdfOcspObject
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const ocspObject = new PdfOcspObject(newOcsp)
|
|
111
|
+
this.document.add(ocspObject)
|
|
112
|
+
|
|
113
|
+
if (!ocspArray) {
|
|
114
|
+
ocspArray = new PdfArray<PdfObjectReference>([])
|
|
115
|
+
this.content.set('OCSPs', ocspArray)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
ocspArray.items.push(ocspObject.reference)
|
|
119
|
+
|
|
120
|
+
return ocspObject
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Adds a CRL to the DSS, avoiding duplicates.
|
|
125
|
+
*
|
|
126
|
+
* @param crl - The DER-encoded CRL.
|
|
127
|
+
* @returns The created or existing CRL object.
|
|
128
|
+
*/
|
|
129
|
+
async addCrl(crl: ByteArray): Promise<PdfCrlObject> {
|
|
130
|
+
let crlArray = this.content.get('CRLs')
|
|
131
|
+
|
|
132
|
+
const currentCrls = (await Promise.all(
|
|
133
|
+
(crlArray?.items ?? []).map(async (ref) => {
|
|
134
|
+
const obj = await this.document.readObject(ref)
|
|
135
|
+
return obj
|
|
136
|
+
}),
|
|
137
|
+
)) as PdfIndirectObject<PdfStream>[]
|
|
138
|
+
|
|
139
|
+
for (const existingCrl of currentCrls) {
|
|
140
|
+
if (existingCrl.content.equals(new PdfStream(crl))) {
|
|
141
|
+
return existingCrl as PdfCrlObject
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const crlObject = new PdfCrlObject(new PdfStream(crl))
|
|
146
|
+
this.document.add(crlObject)
|
|
147
|
+
|
|
148
|
+
if (!crlArray) {
|
|
149
|
+
crlArray = new PdfArray<PdfObjectReference>([])
|
|
150
|
+
this.content.set('CRLs', crlArray)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
crlArray.items.push(crlObject.reference)
|
|
154
|
+
|
|
155
|
+
return crlObject
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Adds a certificate to the DSS, avoiding duplicates.
|
|
160
|
+
*
|
|
161
|
+
* @param cert - The DER-encoded certificate.
|
|
162
|
+
* @returns The created or existing certificate object.
|
|
163
|
+
*/
|
|
164
|
+
async addCert(cert: ByteArray): Promise<PdfCertObject> {
|
|
165
|
+
let certArray = this.content.get('Certs')
|
|
166
|
+
|
|
167
|
+
const currentCerts = (await Promise.all(
|
|
168
|
+
(certArray?.items ?? []).map(async (ref) => {
|
|
169
|
+
const obj = await this.document.readObject(ref)
|
|
170
|
+
return obj
|
|
171
|
+
}),
|
|
172
|
+
)) as PdfIndirectObject<PdfStream>[]
|
|
173
|
+
|
|
174
|
+
for (const existingCert of currentCerts) {
|
|
175
|
+
if (existingCert.content.equals(new PdfStream(cert))) {
|
|
176
|
+
return existingCert as PdfCertObject
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const certObject = new PdfCertObject(new PdfStream(cert))
|
|
181
|
+
this.document.add(certObject)
|
|
182
|
+
|
|
183
|
+
if (!certArray) {
|
|
184
|
+
certArray = new PdfArray<PdfObjectReference>([])
|
|
185
|
+
this.content.set('Certs', certArray)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
certArray.items.push(certObject.reference)
|
|
189
|
+
|
|
190
|
+
return certObject
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Adds revocation information (CRLs and OCSPs) to the DSS.
|
|
195
|
+
*
|
|
196
|
+
* @param revocationInfo - The revocation information to add.
|
|
197
|
+
*/
|
|
198
|
+
async addRevocationInfo(revocationInfo: RevocationInfo): Promise<void> {
|
|
199
|
+
for (const ocsp of revocationInfo.ocsps ?? []) {
|
|
200
|
+
await this.addOcsp(ocsp)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
for (const crl of revocationInfo.crls ?? []) {
|
|
204
|
+
await this.addCrl(crl)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Checks if the DSS is empty (contains no certificates, CRLs, or OCSPs).
|
|
210
|
+
*
|
|
211
|
+
* @returns True if the DSS has no stored data.
|
|
212
|
+
*/
|
|
213
|
+
isEmpty(): boolean {
|
|
214
|
+
const certs = this.content.get('Certs')
|
|
215
|
+
const crls = this.content.get('CRLs')
|
|
216
|
+
const ocsps = this.content.get('OCSPs')
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
(!certs || certs.items.length === 0) &&
|
|
220
|
+
(!crls || crls.items.length === 0) &&
|
|
221
|
+
(!ocsps || ocsps.items.length === 0)
|
|
222
|
+
)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { RevocationInfo, TimeStampAuthority } from '../types'
|
|
2
|
+
import { SignedData } from 'pki-lite/pkcs7/SignedData'
|
|
3
|
+
import { Certificate } from 'pki-lite/x509/Certificate'
|
|
4
|
+
import { SignerInfo } from 'pki-lite/pkcs7/SignerInfo'
|
|
5
|
+
import { Attribute } from 'pki-lite/x509/Attribute'
|
|
6
|
+
import { RevocationInfoArchival } from 'pki-lite/adobe/RevocationInfoArchival'
|
|
7
|
+
import { CertificateList } from 'pki-lite/x509/CertificateList'
|
|
8
|
+
import { OCSPResponse } from 'pki-lite/ocsp/OCSPResponse'
|
|
9
|
+
import { PrivateKeyInfo } from 'pki-lite/keys/PrivateKeyInfo'
|
|
10
|
+
import { OtherRevInfo } from 'pki-lite/adobe/OtherRevInfo'
|
|
11
|
+
import { AsymmetricEncryptionAlgorithmParams } from 'pki-lite/core/index'
|
|
12
|
+
import { fetchRevocationInfo } from '../utils'
|
|
13
|
+
import { PdfSignatureObject, PdfSignatureSignOptions } from './base'
|
|
14
|
+
import { ByteArray } from '../../types'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* PKCS#7 detached signature object (adbe.pkcs7.detached).
|
|
18
|
+
* Creates CMS SignedData with the document hash as external data.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const signature = new PdfAdbePkcs7DetachedSignatureObject({
|
|
23
|
+
* privateKey: keyBytes,
|
|
24
|
+
* certificate: certBytes,
|
|
25
|
+
* reason: 'Document approval',
|
|
26
|
+
* timeStampAuthority: true
|
|
27
|
+
* })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export class PdfAdbePkcs7DetachedSignatureObject extends PdfSignatureObject {
|
|
31
|
+
/** Private key for signing. */
|
|
32
|
+
privateKey: ByteArray
|
|
33
|
+
/** Signer certificate. */
|
|
34
|
+
certificate: ByteArray
|
|
35
|
+
/** Additional certificates for chain building. */
|
|
36
|
+
additionalCertificates: ByteArray[]
|
|
37
|
+
/** Issuer certificate for OCSP requests. */
|
|
38
|
+
issuerCertificate?: ByteArray
|
|
39
|
+
/** Signing date. */
|
|
40
|
+
date?: Date
|
|
41
|
+
/** Signature algorithm parameters. */
|
|
42
|
+
algorithm?: AsymmetricEncryptionAlgorithmParams
|
|
43
|
+
/** Revocation information or 'fetch' to retrieve automatically. */
|
|
44
|
+
revocationInfo?: RevocationInfo | 'fetch'
|
|
45
|
+
/** Timestamp authority configuration. */
|
|
46
|
+
timeStampAuthority?: TimeStampAuthority
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Creates a new PKCS#7 detached signature object.
|
|
50
|
+
*
|
|
51
|
+
* @param options - Signature configuration options.
|
|
52
|
+
*/
|
|
53
|
+
constructor(
|
|
54
|
+
options: PdfSignatureSignOptions & {
|
|
55
|
+
privateKey: ByteArray
|
|
56
|
+
certificate: ByteArray
|
|
57
|
+
issuerCertificate?: ByteArray
|
|
58
|
+
additionalCertificates?: ByteArray[]
|
|
59
|
+
algorithm?: AsymmetricEncryptionAlgorithmParams
|
|
60
|
+
revocationInfo?: RevocationInfo | 'fetch'
|
|
61
|
+
timeStampAuthority?: TimeStampAuthority | true
|
|
62
|
+
},
|
|
63
|
+
) {
|
|
64
|
+
super({
|
|
65
|
+
...options,
|
|
66
|
+
subfilter: 'adbe.pkcs7.detached',
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
this.privateKey = options.privateKey
|
|
70
|
+
this.certificate = options.certificate
|
|
71
|
+
this.issuerCertificate = options.issuerCertificate
|
|
72
|
+
this.additionalCertificates = options.additionalCertificates || []
|
|
73
|
+
this.date = options.date
|
|
74
|
+
this.algorithm = options.algorithm
|
|
75
|
+
this.revocationInfo = options.revocationInfo
|
|
76
|
+
this.timeStampAuthority =
|
|
77
|
+
options.timeStampAuthority === true
|
|
78
|
+
? {
|
|
79
|
+
url: 'http://timestamp.digicert.com',
|
|
80
|
+
}
|
|
81
|
+
: options.timeStampAuthority
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Signs the document bytes using PKCS#7 detached format.
|
|
86
|
+
*
|
|
87
|
+
* @param options - Signing options with bytes and revocation embedding flag.
|
|
88
|
+
* @returns The CMS SignedData and revocation information.
|
|
89
|
+
*/
|
|
90
|
+
sign: PdfSignatureObject['sign'] = async (options) => {
|
|
91
|
+
const { bytes } = options
|
|
92
|
+
|
|
93
|
+
const certificate: Certificate = Certificate.fromDer(this.certificate)
|
|
94
|
+
const additionalCertificates: Certificate[] =
|
|
95
|
+
this.additionalCertificates.map(Certificate.fromDer)
|
|
96
|
+
|
|
97
|
+
const signedAttributes = new SignerInfo.SignedAttributes()
|
|
98
|
+
const unsignedAttributes = new SignerInfo.UnsignedAttributes()
|
|
99
|
+
|
|
100
|
+
signedAttributes.push(Attribute.signingTime(this.date ?? new Date()))
|
|
101
|
+
|
|
102
|
+
const revocationInfo =
|
|
103
|
+
this.revocationInfo === 'fetch'
|
|
104
|
+
? await fetchRevocationInfo({
|
|
105
|
+
certificates: [
|
|
106
|
+
this.certificate,
|
|
107
|
+
...(this.additionalCertificates ?? []),
|
|
108
|
+
],
|
|
109
|
+
issuerCertificate: this.issuerCertificate,
|
|
110
|
+
})
|
|
111
|
+
: this.revocationInfo
|
|
112
|
+
|
|
113
|
+
if (options.embedRevocationInfo && revocationInfo) {
|
|
114
|
+
signedAttributes.push(
|
|
115
|
+
Attribute.adobeRevocationInfoArchival(
|
|
116
|
+
new RevocationInfoArchival({
|
|
117
|
+
crls: revocationInfo.crls?.map((x) =>
|
|
118
|
+
CertificateList.fromDer(x),
|
|
119
|
+
),
|
|
120
|
+
ocsps: revocationInfo.ocsps?.map((x) =>
|
|
121
|
+
OCSPResponse.fromDer(x),
|
|
122
|
+
),
|
|
123
|
+
otherRevInfo: revocationInfo.otherRevInfo?.map(
|
|
124
|
+
(x) =>
|
|
125
|
+
new OtherRevInfo({
|
|
126
|
+
type: x.type,
|
|
127
|
+
value: x.value,
|
|
128
|
+
}),
|
|
129
|
+
),
|
|
130
|
+
}),
|
|
131
|
+
),
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const signedData = await SignedData.builder()
|
|
136
|
+
.addCertificate(...additionalCertificates)
|
|
137
|
+
.setData(bytes)
|
|
138
|
+
.setDetached(true)
|
|
139
|
+
.addSigner({
|
|
140
|
+
certificate,
|
|
141
|
+
privateKeyInfo: PrivateKeyInfo.fromDer(this.privateKey),
|
|
142
|
+
encryptionAlgorithm: this.algorithm,
|
|
143
|
+
signedAttrs: signedAttributes,
|
|
144
|
+
unsignedAttrs: unsignedAttributes,
|
|
145
|
+
tsa: this.timeStampAuthority,
|
|
146
|
+
})
|
|
147
|
+
.build()
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
signedBytes: signedData.toCms().toDer(),
|
|
151
|
+
revocationInfo,
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { RevocationInfo, TimeStampAuthority } from '../types'
|
|
2
|
+
import { SignedData } from 'pki-lite/pkcs7/SignedData'
|
|
3
|
+
import { Certificate } from 'pki-lite/x509/Certificate'
|
|
4
|
+
import { SignerInfo } from 'pki-lite/pkcs7/SignerInfo'
|
|
5
|
+
import { Attribute } from 'pki-lite/x509/Attribute'
|
|
6
|
+
import { RevocationInfoArchival } from 'pki-lite/adobe/RevocationInfoArchival'
|
|
7
|
+
import { CertificateList } from 'pki-lite/x509/CertificateList'
|
|
8
|
+
import { OCSPResponse } from 'pki-lite/ocsp/OCSPResponse'
|
|
9
|
+
import { PrivateKeyInfo } from 'pki-lite/keys/PrivateKeyInfo'
|
|
10
|
+
import { OtherRevInfo } from 'pki-lite/adobe/OtherRevInfo'
|
|
11
|
+
import { AsymmetricEncryptionAlgorithmParams } from 'pki-lite/core/index'
|
|
12
|
+
import { fetchRevocationInfo } from '../utils'
|
|
13
|
+
import { PdfSignatureObject, PdfSignatureSignOptions } from './base'
|
|
14
|
+
import { DigestAlgorithmIdentifier } from 'pki-lite/algorithms/AlgorithmIdentifier'
|
|
15
|
+
import { ByteArray } from '../../types'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* PKCS#7 SHA-1 signature object (adbe.pkcs7.sha1).
|
|
19
|
+
* Creates CMS SignedData with SHA-1 hash embedded as signed content.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const signature = new PdfAdbePkcs7Sha1SignatureObject({
|
|
24
|
+
* privateKey: keyBytes,
|
|
25
|
+
* certificate: certBytes
|
|
26
|
+
* })
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export class PdfAdbePkcs7Sha1SignatureObject extends PdfSignatureObject {
|
|
30
|
+
/** Fixed algorithm for SHA-1 signatures. */
|
|
31
|
+
static readonly ALGORITHM: AsymmetricEncryptionAlgorithmParams = {
|
|
32
|
+
type: 'RSASSA_PKCS1_v1_5',
|
|
33
|
+
params: {
|
|
34
|
+
hash: 'SHA-1',
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Private key for signing. */
|
|
39
|
+
privateKey: ByteArray
|
|
40
|
+
/** Signer certificate. */
|
|
41
|
+
certificate: ByteArray
|
|
42
|
+
/** Additional certificates for chain building. */
|
|
43
|
+
additionalCertificates: ByteArray[]
|
|
44
|
+
/** Issuer certificate for OCSP requests. */
|
|
45
|
+
issuerCertificate?: ByteArray
|
|
46
|
+
/** Signing date. */
|
|
47
|
+
date?: Date
|
|
48
|
+
/** Revocation information or 'fetch' to retrieve automatically. */
|
|
49
|
+
revocationInfo?: RevocationInfo | 'fetch'
|
|
50
|
+
/** Timestamp authority configuration. */
|
|
51
|
+
timeStampAuthority?: TimeStampAuthority
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Creates a new PKCS#7 SHA-1 signature object.
|
|
55
|
+
*
|
|
56
|
+
* @param options - Signature configuration options.
|
|
57
|
+
*/
|
|
58
|
+
constructor(
|
|
59
|
+
options: PdfSignatureSignOptions & {
|
|
60
|
+
privateKey: ByteArray
|
|
61
|
+
certificate: ByteArray
|
|
62
|
+
issuerCertificate?: ByteArray
|
|
63
|
+
additionalCertificates?: ByteArray[]
|
|
64
|
+
algorithm?: AsymmetricEncryptionAlgorithmParams
|
|
65
|
+
revocationInfo?: RevocationInfo | 'fetch'
|
|
66
|
+
timeStampAuthority?: TimeStampAuthority | true
|
|
67
|
+
},
|
|
68
|
+
) {
|
|
69
|
+
super({
|
|
70
|
+
...options,
|
|
71
|
+
subfilter: 'adbe.pkcs7.sha1',
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
this.privateKey = options.privateKey
|
|
75
|
+
this.certificate = options.certificate
|
|
76
|
+
this.issuerCertificate = options.issuerCertificate
|
|
77
|
+
this.additionalCertificates = options.additionalCertificates || []
|
|
78
|
+
this.date = options.date
|
|
79
|
+
this.revocationInfo = options.revocationInfo
|
|
80
|
+
this.timeStampAuthority =
|
|
81
|
+
options.timeStampAuthority === true
|
|
82
|
+
? {
|
|
83
|
+
url: 'http://timestamp.digicert.com',
|
|
84
|
+
}
|
|
85
|
+
: options.timeStampAuthority
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Signs the document bytes using PKCS#7 SHA-1 format.
|
|
90
|
+
*
|
|
91
|
+
* @param options - Signing options with bytes and revocation embedding flag.
|
|
92
|
+
* @returns The CMS SignedData and revocation information.
|
|
93
|
+
*/
|
|
94
|
+
sign: PdfSignatureObject['sign'] = async (options) => {
|
|
95
|
+
const { bytes } = options
|
|
96
|
+
|
|
97
|
+
const certificate: Certificate = Certificate.fromDer(this.certificate)
|
|
98
|
+
const additionalCertificates: Certificate[] =
|
|
99
|
+
this.additionalCertificates.map(Certificate.fromDer)
|
|
100
|
+
|
|
101
|
+
const signedAttributes = new SignerInfo.SignedAttributes()
|
|
102
|
+
const unsignedAttributes = new SignerInfo.UnsignedAttributes()
|
|
103
|
+
|
|
104
|
+
signedAttributes.push(Attribute.signingTime(this.date ?? new Date()))
|
|
105
|
+
const revocationInfo =
|
|
106
|
+
this.revocationInfo === 'fetch'
|
|
107
|
+
? await fetchRevocationInfo({
|
|
108
|
+
certificates: [
|
|
109
|
+
this.certificate,
|
|
110
|
+
...(this.additionalCertificates ?? []),
|
|
111
|
+
],
|
|
112
|
+
issuerCertificate: this.issuerCertificate,
|
|
113
|
+
})
|
|
114
|
+
: this.revocationInfo
|
|
115
|
+
|
|
116
|
+
if (options.embedRevocationInfo && revocationInfo) {
|
|
117
|
+
signedAttributes.push(
|
|
118
|
+
Attribute.adobeRevocationInfoArchival(
|
|
119
|
+
new RevocationInfoArchival({
|
|
120
|
+
crls: revocationInfo.crls?.map((x) =>
|
|
121
|
+
CertificateList.fromDer(x),
|
|
122
|
+
),
|
|
123
|
+
ocsps: revocationInfo.ocsps?.map((x) =>
|
|
124
|
+
OCSPResponse.fromDer(x),
|
|
125
|
+
),
|
|
126
|
+
otherRevInfo: revocationInfo.otherRevInfo?.map(
|
|
127
|
+
(x) =>
|
|
128
|
+
new OtherRevInfo({
|
|
129
|
+
type: x.type,
|
|
130
|
+
value: x.value,
|
|
131
|
+
}),
|
|
132
|
+
),
|
|
133
|
+
}),
|
|
134
|
+
),
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const digest =
|
|
139
|
+
await DigestAlgorithmIdentifier.digestAlgorithm('SHA-1').digest(
|
|
140
|
+
bytes,
|
|
141
|
+
)
|
|
142
|
+
const signedData = await SignedData.builder()
|
|
143
|
+
.addCertificate(...additionalCertificates)
|
|
144
|
+
.setData(digest)
|
|
145
|
+
.setDetached(false)
|
|
146
|
+
.addSigner({
|
|
147
|
+
certificate,
|
|
148
|
+
privateKeyInfo: PrivateKeyInfo.fromDer(this.privateKey),
|
|
149
|
+
encryptionAlgorithm: PdfAdbePkcs7Sha1SignatureObject.ALGORITHM,
|
|
150
|
+
signedAttrs: signedAttributes,
|
|
151
|
+
unsignedAttrs: unsignedAttributes,
|
|
152
|
+
tsa: this.timeStampAuthority,
|
|
153
|
+
})
|
|
154
|
+
.build()
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
signedBytes: signedData.toCms().toDer(),
|
|
158
|
+
revocationInfo,
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|