npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

edockit

v0.3.0

Published

A JavaScript library for listing, parsing, and verifying the contents and signatures of electronic documents (eDoc) and Associated Signature Containers (ASiC-E), supporting EU eIDAS standards for digital signatures and electronic seals.

Readme

edockit

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.

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!

About

This library supports standard European ASiC-E (.asice, .sce) 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.

Installation

# Install the core library
npm install edockit

# If using in Node.js environment, also install xmldom
npm install @xmldom/xmldom

Usage

Basic Usage

import { parseEdoc, verifySignature } from 'edockit';

// Parse an ASiC-E/eDoc file
const fileBuffer = /* your file buffer */;
const container = parseEdoc(fileBuffer);
// container = {
//   files: Map<string, Uint8Array>,  // All files in the container
//   documentFileList: string[],      // Document files (.pdf, .docx, etc.)
//   metadataFileList: string[],      // Metadata files
//   signedFileList: string[],        // Files covered by signatures
//   signatures: SignatureInfo[]      // Signature objects
// }

// List files in container
console.log(Array.from(container.files.keys()));

// Verify a signature (with revocation and timestamp checking)
const result = await verifySignature(container.signatures[0], container.files, {
  checkRevocation: true,   // OCSP/CRL checking (default: true)
  revocationOptions: {     // Optional: configure revocation check behavior
    ocspTimeout: 5000,     // OCSP request timeout in ms (default: 5000)
    crlTimeout: 10000,     // CRL fetch timeout in ms (default: 10000)
    proxyUrl: 'https://cors-proxy.example.com/?url=',  // CORS proxy for browser (optional)
  },
  verifyTimestamps: true,  // RFC 3161 timestamp verification (default: true)
  verifyTime: new Date()   // Verify certificate at specific time (default: timestamp time if present, otherwise now)
});
// result = {
//   isValid: boolean,                // Overall validity (for backwards compatibility)
//   status: 'VALID' | 'INVALID' | 'INDETERMINATE' | 'UNSUPPORTED',  // Granular status
//   statusMessage?: string,          // Human-readable explanation
//   limitations?: [{                 // Platform/environment constraints (if any)
//     code: string,                  // e.g., 'RSA_KEY_SIZE_UNSUPPORTED'
//     description: string,
//     platform?: string              // e.g., 'Safari/WebKit'
//   }],
//   certificate: {
//     isValid: boolean,              // Certificate validity (time-based)
//     revocation: {                  // Revocation check result
//       status: 'good' | 'revoked' | 'unknown' | 'error',
//       method: 'ocsp' | 'crl' | 'none',
//       checkedAt: Date,
//       isValid: boolean
//     }
//   },
//   checksums: {isValid: boolean},   // File checksums validation result
//   signature: {isValid: boolean},   // XML signature validation result
//   timestamp: {                     // Timestamp verification (if present)
//     isValid: boolean,
//     info: { genTime: Date, policy: string, ... },
//     coversSignature: boolean,
//     tsaRevocation: { status, method, ... }
//   },
//   errors: string[]                 // Any validation errors (if present)
// }
console.log(`Signature valid: ${result.isValid}`);

Node.js Example

import { readFileSync } from "fs";
import { parseEdoc, verifySignature } from "edockit";

// Read file
const fileBuffer = readFileSync("document.asice");
const container = parseEdoc(fileBuffer);

// Check signatures with revocation and timestamp checking
for (const signature of container.signatures) {
  const result = await verifySignature(signature, container.files, {
    checkRevocation: true,
    verifyTimestamps: true
  });

  // Use granular status for detailed handling
  console.log(`Status: ${result.status}`);  // VALID, INVALID, INDETERMINATE, or UNSUPPORTED

  if (result.status === 'VALID') {
    console.log('Signature is valid');
  } else if (result.status === 'UNSUPPORTED') {
    // Platform limitation (e.g., RSA >4096 bits in Safari)
    console.log(`Cannot verify: ${result.statusMessage}`);
  } else if (result.status === 'INDETERMINATE') {
    // Can't conclude (e.g., revocation status unknown)
    console.log(`Inconclusive: ${result.statusMessage}`);
  } else {
    // INVALID - definitely wrong
    console.log(`Invalid: ${result.statusMessage}`);
  }

  if (result.timestamp?.info) {
    console.log(`Signed at (TSA): ${result.timestamp.info.genTime}`);
  }

  if (result.certificate.revocation) {
    console.log(`Revocation status: ${result.certificate.revocation.status}`);
  }
}

Browser Example

// Fetch and verify a document
async function verifyDocument(url) {
  const response = await fetch(url);
  const fileBuffer = await response.arrayBuffer();

  const container = parseEdoc(new Uint8Array(fileBuffer));

  // List document files
  console.log("Documents:", container.documentFileList);

  for (const signature of container.signatures) {
    const result = await verifySignature(signature, container.files, {
      checkRevocation: true,
      revocationOptions: {
        // Use a CORS proxy for OCSP/CRL requests in browser environments
        proxyUrl: 'https://your-cors-proxy.example.com/?url=',
      },
    });

    // Handle different validation states
    if (result.status === 'VALID') {
      console.log('Signature verified successfully');
    } else if (result.status === 'UNSUPPORTED') {
      // Some signatures can't be verified in certain browsers (e.g., RSA >4096 in Safari)
      console.log(`Browser limitation: ${result.statusMessage}`);
    } else {
      console.log(`${result.status}: ${result.statusMessage}`);
    }

    if (result.timestamp?.info) {
      console.log(`Timestamp: ${result.timestamp.info.genTime}`);
    }
  }
}

Note: OCSP and CRL endpoints typically don't support CORS, so browser environments need a proxy to perform revocation checks. The proxyUrl option routes all revocation requests through the specified proxy, which should accept the original URL as a query parameter.

Timestamp Utilities

For advanced timestamp handling, you can use the timestamp utilities directly:

import { parseTimestamp, verifyTimestamp, getTimestampTime } from 'edockit';

// Get timestamp time from a signature (quick utility)
const timestampTime = getTimestampTime(signature.signatureTimestamp);
console.log(`Signed at: ${timestampTime}`);

// Parse timestamp for detailed info
const info = parseTimestamp(signature.signatureTimestamp);
// info = {
//   genTime: Date,           // When TSA signed
//   policy: string,          // TSA policy OID
//   hashAlgorithm: string,   // e.g., 'SHA-256'
//   messageImprint: string,  // Hash of timestamped data
//   tsaName?: string,        // TSA name
//   tsaCertificate?: string, // TSA cert in PEM format
// }

// Verify timestamp with options
const result = await verifyTimestamp(signature.signatureTimestamp, {
  signatureValue: signature.signatureValue,  // Verify timestamp covers this signature
  verifyTsaCertificate: true,                // Check TSA cert validity
  checkTsaRevocation: true,                  // Check TSA cert revocation
});

Features

  • Support for EU standard ASiC-E containers and Latvian eDoc files/containers (same format, different extension)
  • List files contained in ASiC-E/eDoc container
  • Extract and display signature information
  • Verify XML signatures against file checksums
  • Validate certificate validity (time-based)
  • RFC 3161 timestamp verification (when present, certificate is validated at the trusted TSA timestamp time)
  • OCSP/CRL revocation checking for both signer and TSA certificates (soft-fail behavior - network errors don't invalidate signatures)

Testing Status

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:

  • ASiC-E containers from different EU countries
  • Files created with different software implementations
  • Various signature algorithms and certificate types
  • Edge cases and non-standard implementations

Browser Usage with UMD Build

If you're not using a module bundler, you can use the UMD build:

<script src="path/to/edockit/dist/index.umd.js"></script>
<script>
  // Access the library from the global 'edockit' object
  const { parseEdoc, verifySignature } = edockit;

  // Your code here
</script>

Contributing

Contributions are highly encouraged! The library needs more real-world testing to improve compatibility and robustness. In particular:

  1. Testing with ASiC-E containers from different European countries
  2. Bug reports with sample files (when possible)
  3. Feature requests for specific EU country implementations
  4. Documentation improvements

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.

License

MIT - See LICENSE file for details.