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

@val-protocol/qes-validator

v0.1.1

Published

Caller-side, no-DSS, pure-JS eIDAS QES (Qualified Electronic Signature) validator for VAL Profile C. Validates a detached/enveloped CAdES (.p7m) or JAdES delegator signature (parse + x5c signature-value + cert-path + QcStatements + Trusted-List CA/QC-for-

Readme

@val-protocol/qes-validator

Not published. Caller-side, no-DSS, pure-JS eIDAS QES (Qualified Electronic Signature) validator for VAL Profile C. See spec §7.1(f) and §5.2 Profile C.

anchoring proves time; Profile C proves identity. This package validates the qualified signature at the root of a VAL lineage — proving the human delegator is a legally identified natural person (eIDAS Art-25), not merely a device-key holder (Profile B).

Why a separate package

The reference verifier @val-protocol/chain-verifier is zero-dependency (Charter §II — "verify without trusting RIGA"). QES validation (X.509 path-building, QcStatements, Trusted-List resolution) is not zero-dep, so it lives here. The core consumes its verdict — exactly as Pass 4 consumes a resolved anchorTrust. The relying party runs this validator themselves, so verification stays trustless.

No DSS, no server (the trustless point)

A relying party verifies a VAL grant's qualified signature without standing up a Java DSS — this is pure JS (Node 18+ / browser-friendly via Web Crypto + node:crypto X509). It reuses @val-protocol/anchor-lotl-resolver for the LOTL→member-state pointer, and adds a CA/QC-for-eSignatures Trusted-List matcher beside the resolver's TSA/QTST one (a TSA hit is never counted as a qualified-eSignature hit).

Documented ETSI subset (honest scope)

  1. JWS/JAdES parse — ETSI TS 119 182-1
  2. signature-value verification over the JWS signing input via the embedded x5c — ETSI TS 119 102-1
  3. certificate-path build + verification leaf → issuer → trust anchor — ETSI TS 119 102-1
  4. qualification-status determination — ETSI TS 119 615: QcCompliance (0.4.0.1862.1.1) and QcType-eSign (0.4.0.1862.1.6.1) in the signing cert and the issuer is a granted CA/QC-for-eSignatures Trusted-List service at signing time.

Out of scope (DSS's job, not reimplemented): per-certificate OCSP/CRL revocation, full AdES-LTA / archive-timestamp LTV. Revocation here is at Trusted-List service-status granularity (granted / withdrawn at signing time), not per-cert OCSP.

Precondition: complete certificate chain (no AIA chasing)

The validator anchors a signature ONLY if the full path leaf → … → TL-listed granted CA/QC service is present in the JAdES x5c header or in trust.intermediateHintsDer. It does not fetch missing issuer certificates (no AIA / caIssuers chasing) — that would require a network call and break the offline/trustless model. DSS-emitted JAdES carries the full chain in x5c; a leaner non-DSS QTSP that emits a partial x5c (leaf only) will return status: 'not_qualified', subIndication: 'CHAIN_INCOMPLETE' (supply the full chain, or pass the intermediates via intermediateHintsDer) — never a false qualified. This is distinct from ANCHOR_NOT_ON_TRUSTED_LIST (the chain WAS complete and reached a self-issued top that simply isn't a granted CA/QC service — e.g. an attacker's self-signed root).

Verdict — conclusive vs indeterminate, and per-signature keying

validateQes(input) → QesValidationReport. qualified: boolean is the only field the core treats as the gate, and is true only on a conclusive positive. Everything else is status: 'not_qualified' (conclusive negative) or status: 'indeterminate' (could not conclude — e.g. LOTL unreachable, no trust anchor, CAdES input) — never a silent qualified:true. signatureRef (sha256-hex of the delegation signature bytes) lets the core match this report to this signature (per-signature matching), so distinct qualified delegations never borrow each other's verdict.

import { verifyValChain } from '@val-protocol/chain-verifier';
import { validateQes } from '@val-protocol/qes-validator';

const report = await validateQes({
  signedCanonical,                 // the root ASSIGNMENT canonical bytes the QES was computed over
  signature,                       // ValQesSignature { alg, signature } (detached JAdES)
  validationTime: anchorGenTime,   // §8.4 anchor genTime anchor time for at-signing-time determination
  trust: { tslXml, trustAnchorsDer }, // or { fetchLive: true } to pull the EU LOTL live
});
const result = await verifyValChain(rows, { qesValidation: { reports: [report] } });
// result.conformanceProfile === 'C' and result.signature === 'green' when report.qualified === true

Tests

npm test — deterministic openssl fixtures (test/fixtures/gen.sh), no DSS, no network: the positive (real ES256 signature verified + cert-path + QcStatements + CA/QC TSL), and negatives (mangled sig, TSA-only issuer, withdrawn / granted-late service, no-ForeSignatures, wrong canonical, no anchor, CAdES → indeterminate). Not proven here: byte-compatibility with a real DSS-emitted JAdES (needs the infra-gated SSL.com artifact) — the fixtures are spec-shaped (sigD ObjectIdByURIHash) but synthetic.