Skip to content

noqtis-seal(1)

noqtis-seal — seal a folder of files into a signed capsule

noqtis seal -k key [-p key.pub] [-m json-file] [--format 1 | 2] [--input [name=]dir ...] [--tsa url ...] [--anchor der-file ...] dir

noqtis seal turns the folder dir into a capsule (noqtis-capsule(5)). It lists every regular file under dir, computes each file's size, SHA-256 and SHA3-256, writes the manifest noqtis.json (canonical JSON, RFC 8785), signs its exact bytes with the secret key in key under the context string ‘noqtis-capsule-1’, and writes the seal noqtis.sig. An existing noqtis.json and noqtis.sig at the top of dir are left out of the listing and replaced. On success it prints

sealed dir with alg

With --tsa, it then asks a time-stamping authority (TSA) for an RFC 3161 timestamp over the seal's signature and stores the token in noqtis.sig (nqtsput(3)). The request (nqtsreq(3)) holds only the SHA-256 of the signature, a random nonce and a request for the TSA's certificate; it is sent by an HTTP/1.1 POST (‘application/timestamp-query’), and the reply must be a granted token over that signature with that nonce, signed by a TSA certificate valid at its genTime. It prints

timestamp from url: genTime time
and the summary line ends in ‘and a timestamp’. A seal holds one timestamp: give --tsa again for fallbacks, tried in order until one gives a token that checks. When none does, the new noqtis.json and noqtis.sig are removed, so the folder is never left sealed without the timestamp that was asked for, and the exit status is 2. An interrupt while it waits (Ctrl-C, SIGTERM, SIGHUP) removes them too; only SIGKILL or a power cut can leave the folder sealed without one. A TSA has 120 seconds in all for one request, the name lookup included (30 seconds at most for any one step).

The folder must not hold a noqtis secret key (a file that starts with ‘noqtis-key-1 <alg> sec’), which would ship with the capsule: the seal is refused, with exit status 2.

The folder must hold only regular files and folders with portable names. Nothing is written, and the exit status is 2, when it holds a symbolic link, a Windows reparse point, a device, pipe or socket, a name that is empty, holds a control character, ‘/’, ‘\’ or ‘:’, is not valid UTF-8, or two paths that differ only in ASCII case; or when it exceeds a limit: more than 2,000,000 files, a path over 4096 bytes, folders more than 64 levels deep, a manifest over 512 MiB, or a file over 2^53-1 bytes.

The creation time in the manifest is SOURCE_DATE_EPOCH when it is set (a decimal number of seconds), otherwise the clock.

The secret key and the public key must be one pair: the new seal is verified before it is written, and a key pair that does not match is refused.

key, --key=key
A secret signature key file (ML-DSA or SLH-DSA).
key.pub, --pub=key.pub
The matching public key, stored in the seal. Default: key.pub.
json-file, --meta=json-file
A JSON object (at most 1 MiB) stored, in canonical form, as the manifest's ‘meta’ field and covered by the signature. noqtis does not interpret it.
1 |
The capsule format (noqtis-capsule(5)). Format 1 (the default) signs the whole manifest. Format 2 adds a Merkle tree over the file entries and signs the manifest's head, which holds the tree's root but not the list of files, so that noqtis-prove(1) can show some files to a reader without the names or digests of the others.
[name=]dir
A sealed capsule this one was made from, up to 32 times; it implies --format 2. The input must check (noqtis-check(1)), and its id (the SHA-256 of the bytes its seal signs) is recorded under name, by default the folder's last component (1 to 255 bytes, no control characters). noqtis-check(1) --lineage follows these records back.
url
An RFC 3161 time-stamping authority, as ‘http://host[:port][/path]’, up to 32 times. Plain HTTP is enough: the token is signed by the TSA, so TLS adds no integrity. ‘https://’ works when noqtis was built with its own TLS 1.3 client (the CMake option NQTLS), the server's certificate checked against the PEM bundle SSL_CERT_FILE names, else the system's, and its Certificate Transparency SCTs against the log list NOQTIS_CT_LOGS names, when set (see noqtis-check(1)); otherwise it is refused with that said. Most public TSAs answer on ‘http://’. There is no proxy support. Each connection, read and write waits at most 30 seconds.
der-file
The TSA's root or issuing certificate (DER), up to 32: the token must then also have a certificate path to one of them, checked as noqtis-check(1) --anchor checks it. Without it the reply is checked, but not whether the TSA is one to trust, and a note on standard error says so.

Seconds since 1970-01-01T00:00:00Z to record as the creation time, for reproducible capsules. A value that is not a plain decimal number is refused.

dir/noqtis.json
the manifest
dir/noqtis.sig
the seal

0 when the capsule was written (with its timestamp, when --tsa was given); 2 on a usage error, keys that are not a signature key pair, an unsealable folder, a limit, a file that cannot be read or written, or no TSA that gave a timestamp.

$ noqtis keygen -a ML-DSA-65 -o me
ML-DSA-65 key pair: me (secret), me.pub (public)
$ echo '{"project":"demo"}' > meta.json
$ noqtis seal -k me -m meta.json results
sealed results with ML-DSA-65
$ ls results
data  noqtis.json  noqtis.sig  report.txt

A reproducible capsule:

$ SOURCE_DATE_EPOCH=1767225600 noqtis seal -k me results
sealed results with ML-DSA-65

With a timestamp from one of two authorities, checked at seal time:

$ noqtis seal -k me --tsa http://timestamp.digicert.com \
    --tsa http://timestamp.sectigo.com \
    --anchor digicert.der --anchor sectigo.der results
timestamp from http://timestamp.digicert.com: genTime 2026-10-29T09:34:03Z, verified under a TSA anchor
sealed results with ML-DSA-65 and a timestamp

noqtis(1), noqtis-check(1), noqtis-keygen(1), noqtis-prove(1), nqseal(3), nqtsput(3), noqtis-capsule(5)

Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP), RFC 3161, August 2001.