All notable changes to this project are documented here. The format follows Keep a Changelog, and the project uses Semantic Versioning.
0.1.0 - 2026-11-09
The first release.
Added
Tspex.request/2: builds aTimeStampReq(RFC 3161, 2.4.1) for a binary, a stream or a ready digest, with SHA-224 to SHA-512 (SHA-1 only withallow_sha1: true), a policy, a random nonce,certReqand extensions.Tspex.decode_request/2reads one back.Tspex.decode_response/2andTspex.decode_token/2: read aTimeStampRespand a token (TSTInfo, withaccuracy,ordering,tsaand extensions) without judging them.Tspex.verify/3: verifies a response or a token against the request that asked for it, or against stored data, and returns what it proves in aTspex.Verified. The certificate of the TSA is checked (signing certificate attribute, criticalextKeyUsagewith timeStamping, key usage), and its chain to the:trustroots is validated at thegenTime, so a token outlives the certificate that signed it. Nonce, policy,tsaname, critical extensions, clock skew and a:revocationfunction are checked. Status andfailInfoof a refusal are reported as errors. A token signed with SHA-1 (as the TSA of Apple and the LibreSSL of macOS do) is:weak_algorithmwithdetail: :sha1;allow_sha1: trueaccepts it.Tspex.stamp/2: request, transport, response and verification in one call, withTspex.HTTP, an HTTP/1.1 client with limits on the head, the body and the time, and a verified TLS connection; or your own:transport.- Time-stamps in CMS messages made with cmsex:
Tspex.signature_imprint/3,Tspex.add_signature_time_stamp/4,Tspex.signature_time_stamps/3andTspex.verify_signature_time_stamps/3(signature time-stamps, CAdES-T);Tspex.content_time_stamp_attribute/1andTspex.verify_content_time_stamp/3(content time-stamps);Tspex.verify_signature_at_time_stamp/2, which verifies a signature and its certificate path as of the time of its stamp. Tspex.path_validation_at/2, for validating a certificate path at a date.- Tested against
openssl ts(OpenSSL 1.1.1 and 3.x, LibreSSL) and the Javajarsigner, both ways, with a negative corpus and fuzzing of every reader, including inputs that are not text where text is expected. Tspex.TimeStampedData(RFC 5544, experimental):imprint/2,new/3,extension_imprint/2,extend/3,encode/1,decode/2,time_stamps/2andverify/2. A document with a chain of time-stamps, each covering the element before it, with theMetaDataunder the first token when it is hash protected. ThedataUriis never fetched;ersEvidenceand other evidence are read and written, not verified.TimeStampedData.verify/2says inorderedwhether thegenTimeof the tokens ever goes back along the chain, and:max_time_backrefuses it (:time_order) when it goes back by more than the seconds you give.- The error reasons
:content_missing,:unexpected_contentand:time_order. - A tested recipe in the guide for
:revocationfrom CRLs you hold, with the rules of RFC 3161, section 4 (key compromise voids every token; another reason only the tokens made at or after the revocation).