edockit 0.1.1-beta.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Edgars Jēkabsons, ZenomyTech SIA
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # edockit
2
+
3
+ A JavaScript/TypeScript library for viewing and verifying EU standard ASiC-E containers (including Latvian eDoc files, which use the same format with a different extension). Works in both browser and Node.js environments.
4
+
5
+ > **Note: Work in Progress** - This library is under active development and requires more real-world testing with various ASiC-E implementations from different European countries. If you have sample files or encounter issues, please contribute!
6
+
7
+ > **Important:** Certificate validation currently lacks OCSP checks (Online Certificate Status Protocol). Adding OCSP support is on the roadmap and will be implemented in a future release.
8
+
9
+ ## About
10
+
11
+ This library supports standard European ASiC-E (.asice) containers as defined by the ETSI standards. Latvian eDoc (.edoc) files are effectively ASiC-E containers with a different file extension, so they are also supported. While the core functionality exists, extensive testing with real-world documents from various EU countries is still needed to ensure complete compatibility across different implementations.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ # Install the core library
17
+ npm install edockit
18
+
19
+ # If using in Node.js environment, also install xmldom
20
+ npm install @xmldom/xmldom
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ### Basic Usage
26
+
27
+ ```typescript
28
+ import { parseEdoc, verifySignature } from 'edockit';
29
+
30
+ // Parse an ASiC-E/eDoc file
31
+ const fileBuffer = /* your file buffer */;
32
+ const container = parseEdoc(fileBuffer);
33
+ // container = {
34
+ // files: Map<string, Uint8Array>, // All files in the container
35
+ // documentFileList: string[], // Document files (.pdf, .docx, etc.)
36
+ // metadataFileList: string[], // Metadata files
37
+ // signedFileList: string[], // Files covered by signatures
38
+ // signatures: SignatureInfo[] // Signature objects
39
+ // }
40
+
41
+ // List files in container
42
+ console.log(Array.from(container.files.keys()));
43
+
44
+ // Verify a signature
45
+ const result = await verifySignature(container.signatures[0], container.files);
46
+ // result = {
47
+ // isValid: boolean, // Overall validity
48
+ // certificate: {isValid: boolean}, // Certificate validation result
49
+ // checksums: {isValid: boolean}, // File checksums validation result
50
+ // signature: {isValid: boolean}, // XML signature validation result
51
+ // errors: string[] // Any validation errors (if present)
52
+ // }
53
+ console.log(`Signature valid: ${result.isValid}`);
54
+ ```
55
+
56
+ ### Node.js Example
57
+
58
+ ```typescript
59
+ import { readFileSync } from 'fs';
60
+ import { parseEdoc, verifySignature } from 'edockit';
61
+
62
+ // Read file
63
+ const fileBuffer = readFileSync('document.asice');
64
+ const container = parseEdoc(fileBuffer);
65
+
66
+ // Check signatures
67
+ for (const signature of container.signatures) {
68
+ const result = await verifySignature(signature, container.files);
69
+ console.log(`Signature valid: ${result.isValid}`);
70
+
71
+ if (!result.isValid && result.errors) {
72
+ console.log(`Errors: ${result.errors.join(', ')}`);
73
+ }
74
+ }
75
+ ```
76
+
77
+ ### Browser Example
78
+
79
+ ```javascript
80
+ // Fetch and verify a document
81
+ async function verifyDocument(url) {
82
+ const response = await fetch(url);
83
+ const fileBuffer = await response.arrayBuffer();
84
+
85
+ const container = parseEdoc(new Uint8Array(fileBuffer));
86
+
87
+ // List document files
88
+ console.log("Documents:", container.documentFileList);
89
+
90
+ for (const signature of container.signatures) {
91
+ const result = await verifySignature(signature, container.files);
92
+ console.log(`Valid: ${result.isValid}`);
93
+ }
94
+ }
95
+ ```
96
+
97
+ ## Features
98
+
99
+ - Support for EU standard ASiC-E containers and Latvian eDoc files/containers (same format, different extension)
100
+ - List files contained in ASiC-E/eDoc container
101
+ - Extract and display signature information
102
+ - Verify XML signatures against file checksums
103
+ - Validate certificate validity (Note: OCSP validation planned for future releases)
104
+
105
+ ## Testing Status
106
+
107
+ The library has been tested with a limited set of real Latvian eDoc files (which are ASiC-E containers with a .edoc extension). More testing is needed with:
108
+ - ASiC-E containers from different EU countries
109
+ - Files created with different software implementations
110
+ - Various signature algorithms and certificate types
111
+ - Edge cases and non-standard implementations
112
+
113
+ ## Browser Usage with UMD Build
114
+
115
+ If you're not using a module bundler, you can use the UMD build:
116
+
117
+ ```html
118
+ <script src="path/to/edockit/dist/index.umd.js"></script>
119
+ <script>
120
+ // Access the library from the global 'edockit' object
121
+ const { parseEdoc, verifySignature } = edockit;
122
+
123
+ // Your code here
124
+ </script>
125
+ ```
126
+
127
+ ## Contributing
128
+
129
+ Contributions are highly encouraged! The library needs more real-world testing to improve compatibility and robustness. In particular:
130
+
131
+ 1. Testing with ASiC-E containers from different European countries
132
+ 2. Bug reports with sample files (when possible)
133
+ 3. Feature requests for specific EU country implementations
134
+ 4. Documentation improvements
135
+
136
+ If you encounter any issues, please open an issue on GitHub. Including sample files with your issue report (if possible) will help tremendously with debugging and improving compatibility.
137
+
138
+ ## License
139
+
140
+ MIT - See LICENSE file for details.
@@ -0,0 +1,51 @@
1
+ interface CanonMethod {
2
+ beforeChildren: (hasElementChildren?: boolean, hasMixedContent?: boolean) => string;
3
+ afterChildren: (hasElementChildren?: boolean, hasMixedContent?: boolean) => string;
4
+ betweenChildren: (prevIsElement?: boolean, nextIsElement?: boolean, hasMixedContent?: boolean) => string;
5
+ afterElement: () => string;
6
+ isCanonicalizationMethod?: string;
7
+ }
8
+ declare const CANONICALIZATION_METHODS: {
9
+ default: string;
10
+ "http://www.w3.org/TR/2001/REC-xml-c14n-20010315": string;
11
+ "http://www.w3.org/2006/12/xml-c14n11": string;
12
+ "http://www.w3.org/2001/10/xml-exc-c14n#": string;
13
+ };
14
+ declare const NODE_TYPES: {
15
+ ELEMENT_NODE: number;
16
+ TEXT_NODE: number;
17
+ };
18
+ interface ExcC14NOptions {
19
+ inclusiveNamespacePrefixList?: string[];
20
+ isStartingNode?: boolean;
21
+ }
22
+ interface WhitespaceInfo {
23
+ hasMixedContent?: boolean;
24
+ hasExistingLinebreaks?: boolean;
25
+ originalContent?: Record<string, any>;
26
+ }
27
+ interface NodeWithWhitespace extends Node {
28
+ _whitespace?: WhitespaceInfo;
29
+ _originalText?: string;
30
+ }
31
+ declare class XMLCanonicalizer {
32
+ private method;
33
+ constructor(method?: CanonMethod);
34
+ static fromMethod(methodUri: string): XMLCanonicalizer;
35
+ static base64Elements: Set<string>;
36
+ setMethod(method: CanonMethod): void;
37
+ static escapeXml(text: string): string;
38
+ static collectNamespaces(node: Node, visibleNamespaces?: Map<string, string>): Map<string, string>;
39
+ static collectUsedNamespaces(node: Node, allVisibleNamespaces?: Map<string, string>, inclusivePrefixList?: string[]): Map<string, string>;
40
+ static isBase64Element(node: Node): boolean;
41
+ static analyzeWhitespace(node: Node): void;
42
+ canonicalize(node: NodeWithWhitespace, visibleNamespaces?: Map<string, string>, options?: {
43
+ isStartingNode: boolean;
44
+ }): string;
45
+ canonicalizeExclusive(node: NodeWithWhitespace, visibleNamespaces?: Map<string, string>, options?: ExcC14NOptions): string;
46
+ static c14n(node: Node): string;
47
+ static c14n11(node: Node): string;
48
+ static c14n_exc(node: Node, inclusiveNamespacePrefixList?: string[]): string;
49
+ static canonicalize(node: Node, methodUri: string, options?: any): string;
50
+ }
51
+ export { XMLCanonicalizer, CANONICALIZATION_METHODS, NODE_TYPES };
@@ -0,0 +1,98 @@
1
+ import { X509Certificate } from "@peculiar/x509";
2
+ /**
3
+ * Certificate subject information
4
+ */
5
+ export interface CertificateSubject {
6
+ country?: string;
7
+ commonName?: string;
8
+ surname?: string;
9
+ givenName?: string;
10
+ serialNumber?: string;
11
+ organization?: string;
12
+ }
13
+ /**
14
+ * Certificate issuer information
15
+ */
16
+ export interface CertificateIssuer {
17
+ country?: string;
18
+ commonName?: string;
19
+ organization?: string;
20
+ }
21
+ /**
22
+ * Full certificate information
23
+ */
24
+ export interface CertificateInfo {
25
+ subject: CertificateSubject;
26
+ validFrom: Date;
27
+ validTo: Date;
28
+ issuer: CertificateIssuer;
29
+ serialNumber?: string;
30
+ }
31
+ /**
32
+ * Certificate validity check result
33
+ */
34
+ export interface CertificateValidityResult {
35
+ isValid: boolean;
36
+ reason?: string;
37
+ }
38
+ /**
39
+ * Format a certificate string as a proper PEM certificate
40
+ * @param certBase64 Base64-encoded certificate
41
+ * @returns Formatted PEM certificate
42
+ */
43
+ export declare function formatPEM(certBase64?: string): string;
44
+ /**
45
+ * Extract subject information from an X.509 certificate
46
+ * @param certificate X509Certificate instance
47
+ * @returns Signer information object
48
+ */
49
+ export declare function extractSignerInfo(certificate: X509Certificate): {
50
+ commonName?: string;
51
+ organization?: string;
52
+ country?: string;
53
+ surname?: string;
54
+ givenName?: string;
55
+ serialNumber?: string;
56
+ validFrom: Date;
57
+ validTo: Date;
58
+ issuer: {
59
+ commonName?: string;
60
+ organization?: string;
61
+ country?: string;
62
+ };
63
+ };
64
+ /**
65
+ * Parse a certificate from base64 data
66
+ * @param certData Base64-encoded certificate data
67
+ * @returns Parsed certificate information
68
+ */
69
+ export declare function parseCertificate(certData: string): Promise<CertificateInfo>;
70
+ /**
71
+ * Check if a certificate was valid at a specific time
72
+ * @param cert Certificate object or info
73
+ * @param checkTime The time to check validity against (defaults to current time)
74
+ * @returns Validity check result
75
+ */
76
+ export declare function checkCertificateValidity(cert: X509Certificate | CertificateInfo, checkTime?: Date): CertificateValidityResult;
77
+ /**
78
+ * Extract the public key information from a certificate
79
+ * @param cert The X.509 certificate
80
+ * @returns Public key information
81
+ */
82
+ export declare function getPublicKeyInfo(cert: X509Certificate): {
83
+ algorithm: string;
84
+ namedCurve?: string;
85
+ rawData: ArrayBuffer;
86
+ };
87
+ /**
88
+ * Helper function to get signer display name from certificate
89
+ * @param certInfo Certificate information
90
+ * @returns Formatted display name
91
+ */
92
+ export declare function getSignerDisplayName(certInfo: CertificateInfo): string;
93
+ /**
94
+ * Helper function to format certificate validity period in a human-readable format
95
+ * @param certInfo Certificate information
96
+ * @returns Formatted validity period
97
+ */
98
+ export declare function formatValidityPeriod(certInfo: CertificateInfo): string;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Format a certificate string as a proper PEM certificate
3
+ * @param certBase64 Base64-encoded certificate
4
+ * @returns Formatted PEM certificate
5
+ */
6
+ export declare function formatPEM(certBase64?: string): string;
@@ -0,0 +1,33 @@
1
+ import { SignatureInfo } from "./types";
2
+ import { formatPEM } from "./certificateUtils";
3
+ /**
4
+ * Find signature files in the eDoc container
5
+ * @param files Map of filenames to file contents
6
+ * @returns Array of signature filenames
7
+ */
8
+ export declare function findSignatureFiles(files: Map<string, Uint8Array>): string[];
9
+ /**
10
+ * Parse a signature file that contains a single signature
11
+ * @param xmlContent The XML file content
12
+ * @param filename The filename (for reference)
13
+ * @returns The parsed signature with raw XML content
14
+ */
15
+ export declare function parseSignatureFile(xmlContent: Uint8Array, filename: string): SignatureInfo | null;
16
+ /**
17
+ * Parse a single signature element using a browser-like approach
18
+ * @param signatureElement The signature element to parse
19
+ * @param xmlDoc The parent XML document
20
+ * @returns Parsed signature information
21
+ */
22
+ export declare function parseSignatureElement(signatureElement: Element, xmlDoc: Document): SignatureInfo;
23
+ /**
24
+ * Fallback for creating a basic signature from text when DOM parsing fails
25
+ * @param xmlText The full XML text
26
+ * @returns A basic signature or null if parsing fails
27
+ */
28
+ export declare function parseBasicSignatureFromText(xmlText: string): SignatureInfo | null;
29
+ export declare const __test__: {
30
+ parseSignatureElement: typeof parseSignatureElement;
31
+ parseBasicSignatureFromText: typeof parseBasicSignatureFromText;
32
+ formatPEM: typeof formatPEM;
33
+ };
@@ -0,0 +1,38 @@
1
+ export interface EdocContainer {
2
+ files: Map<string, Uint8Array>;
3
+ documentFileList: string[];
4
+ metadataFileList: string[];
5
+ signedFileList: string[];
6
+ signatures: SignatureInfo[];
7
+ }
8
+ export interface SignatureInfo {
9
+ id: string;
10
+ signingTime: Date;
11
+ certificate: string;
12
+ certificatePEM: string;
13
+ publicKey?: {
14
+ algorithm: string;
15
+ namedCurve?: string;
16
+ rawData: ArrayBuffer;
17
+ };
18
+ signedChecksums: Record<string, string>;
19
+ signerInfo?: {
20
+ commonName?: string;
21
+ organization?: string;
22
+ country?: string;
23
+ serialNumber?: string;
24
+ validFrom: Date;
25
+ validTo: Date;
26
+ issuer: {
27
+ commonName?: string;
28
+ organization?: string;
29
+ country?: string;
30
+ };
31
+ };
32
+ references: string[];
33
+ algorithm?: string;
34
+ signatureValue?: string;
35
+ signedInfoXml?: string;
36
+ rawXml?: string;
37
+ canonicalizationMethod?: string;
38
+ }
@@ -0,0 +1,8 @@
1
+ import type { EdocContainer, SignatureInfo } from "./parser/types";
2
+ export { EdocContainer, SignatureInfo };
3
+ /**
4
+ * Parse an eDoc container from a buffer
5
+ * @param edocBuffer The raw eDoc file content
6
+ * @returns Parsed container with files, document file list, metadata file list, signed file list, and signatures
7
+ */
8
+ export declare function parseEdoc(edocBuffer: Uint8Array): EdocContainer;
@@ -0,0 +1,94 @@
1
+ import { CertificateInfo } from "./certificate";
2
+ import { SignatureInfo } from "./parser";
3
+ /**
4
+ * Options for verification process
5
+ */
6
+ export interface VerificationOptions {
7
+ checkCertificateValidity?: boolean;
8
+ verifySignatures?: boolean;
9
+ verifyChecksums?: boolean;
10
+ verifyTime?: Date;
11
+ }
12
+ /**
13
+ * Result of a checksum verification
14
+ */
15
+ export interface ChecksumVerificationResult {
16
+ isValid: boolean;
17
+ details: Record<string, {
18
+ expected: string;
19
+ actual: string;
20
+ matches: boolean;
21
+ fileFound: boolean;
22
+ }>;
23
+ }
24
+ /**
25
+ * Result of a signature verification
26
+ */
27
+ export interface SignatureVerificationResult {
28
+ isValid: boolean;
29
+ reason?: string;
30
+ }
31
+ /**
32
+ * Result of a certificate verification
33
+ */
34
+ export interface CertificateVerificationResult {
35
+ isValid: boolean;
36
+ reason?: string;
37
+ info?: CertificateInfo;
38
+ }
39
+ /**
40
+ * Complete verification result
41
+ */
42
+ export interface VerificationResult {
43
+ isValid: boolean;
44
+ certificate: CertificateVerificationResult;
45
+ checksums: ChecksumVerificationResult;
46
+ signature?: SignatureVerificationResult;
47
+ errors?: string[];
48
+ }
49
+ /**
50
+ * Compute a digest (hash) of file content with browser/node compatibility
51
+ * @param fileContent The file content as Uint8Array
52
+ * @param algorithm The digest algorithm to use (e.g., 'SHA-256')
53
+ * @returns Promise with Base64-encoded digest
54
+ */
55
+ export declare function computeDigest(fileContent: Uint8Array, algorithm: string): Promise<string>;
56
+ /**
57
+ * Verify checksums of files against signature
58
+ * @param signature The signature information
59
+ * @param files Map of filenames to file contents
60
+ * @returns Promise with verification results for each file
61
+ */
62
+ export declare function verifyChecksums(signature: {
63
+ signedChecksums: Record<string, string>;
64
+ algorithm?: string;
65
+ }, files: Map<string, Uint8Array>): Promise<ChecksumVerificationResult>;
66
+ /**
67
+ * Verify certificate validity
68
+ * @param certificatePEM PEM-formatted certificate
69
+ * @param verifyTime Time to check validity against
70
+ * @returns Certificate verification result
71
+ */
72
+ export declare function verifyCertificate(certificatePEM: string, verifyTime?: Date): Promise<CertificateVerificationResult>;
73
+ /**
74
+ * Verify the XML signature specifically using SignedInfo and SignatureValue
75
+ * @param signatureXml The XML string of the SignedInfo element
76
+ * @param signatureValue The base64-encoded signature value
77
+ * @param publicKeyData The public key raw data
78
+ * @param algorithm Key algorithm details
79
+ * @param canonicalizationMethod The canonicalization method used
80
+ * @returns Signature verification result
81
+ */
82
+ export declare function verifySignedInfo(signatureXml: string, signatureValue: string, publicKeyData: ArrayBuffer, algorithm: {
83
+ name: string;
84
+ hash: string;
85
+ namedCurve?: string;
86
+ }, canonicalizationMethod?: string): Promise<SignatureVerificationResult>;
87
+ /**
88
+ * Verify a complete signature (certificate, checksums, and signature)
89
+ * @param signatureInfo Signature information
90
+ * @param files File contents
91
+ * @param options Verification options
92
+ * @returns Complete verification result
93
+ */
94
+ export declare function verifySignature(signatureInfo: SignatureInfo, files: Map<string, Uint8Array>, options?: VerificationOptions): Promise<VerificationResult>;