datekeys-ts 0.5.0 implements spec v0.16 (tag spec-v0.16 of datekeys-go):
a seal without accuracy proves nothing before the opening date, and
drand's JSON is read strictly; it also draws the random words of a key of
words, from a computer or from dice, and says what the official SDK says
when it seals, besides everything 0.4.0 does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The author approved specification v0.16 on 7 October 2026, tagged
spec-v0.16 at b6ff17a. Only the annex changes, with the SHA-256 of the
approved text, and the README of testdata; the README and the CHANGELOG
name the approved version.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3fd0e93 restores the escapes of release.json that 4f78854 had lost: the
cases "round escaped as round" and "round twice, once escaped as
round", and the surrogate pair of "a surrogate pair in a value". The
annex changes with the SHA-256 of the draft. The comment of the strict
reader had lost the same escape.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec §38.1: the hint of the person's own words says that they are not
enough for something valuable and that a password used elsewhere must not
be one, since once the date has come the capsule lets anyone test it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As aefc8f6 of datekeys-go. sync-testdata.mjs also vendors annex/ of Go,
the recovery annex (§79 under a title with the version and the SHA-256 of
the specification), and testdata, wordlists and annex are at aefc8f6.
/create recommends the key to a time_only capsule more than a year ahead
(§7.6), and once the capsule is made it says what opening it later will
take: the capsule, one of its keys if it has them, and the signature of
drand for its round, which an archive or a cache service must keep if
drand no longer serves it (§62.1, rule 26); and it offers the annex for
download as <capsule>.recuperacion.txt (rule 27, annex.ts). check-build.mjs
wants the annex shipped byte for byte.
profile.ts gains ProfileStatus, PROFILE_STATUS and profileStatusOf, as
StatusOf of Go: Quicknet is active. planCapsule writes no capsule with a
profile that is not, and /inspect warns when the profile of a capsule is
compromised (buildReport takes profileStatus).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For whoever does not trust the random numbers of a computer, as dice.go of
datekeys-go at 92e7154, with its texts: five dice for each word give a
number from 11111 to 66666, the position of the word in a list of 7776.
wordlist.ts gains DICE_LIST_SIZE, diceNumber, diceWord, diceWords and
diceList, the list numbered as the EFF publishes its own, and wordkey.ts
goFields, which splits at white space as strings.Fields of Go.
/create offers "Con dados" between the random words and the person's own:
it turns the numbers into words as they are typed, tells a number that is
not five dice or that gives a word again, and offers the list numbered for
dice, to print it, with its SHA-256. planCapsule takes dice and diceList,
and readDice reads the numbers one by one. The list loads once for random
words and dice, and an effect that finds it loaded writes no state, so it
does not run again without end.
testdata and wordlists at 92e7154, whose README of the lists records the
SHA-256 of each list numbered for dice.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
testdata and wordlists at datekeys-go e671032, with the same testdata:
wordlists/en.txt is the large wordlist of the EFF, 7776 words, CC BY 4.0,
in its order and without the dice numbers. WORD_LIST_SHA256 pins it, and
the alphabet of en is a to z and the hyphen of its four compound words.
/create still offers the Spanish list, and check-build.mjs wants the site
to ship that one alone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The effect that checks the paths wrote pathCheck and read it back, so
Svelte ran it again without end once the rules had loaded, with the first
file, comment or author: effect_update_depth_exceeded in the console, and
checkPaths over the whole list each time. It reads the check from a local
now. Since 7dc88ef (1 October), and in 0.4.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the policy with a key, a check box opens the capsule with words too,
random by default: the page fetches the Spanish list of datekeys-go from
its own site (create-words.ts, the hashed file that Vite ships), takes it
only with its pinned SHA-256, and draws 7 words that never leave the
browser. It shows them numbered, since they are typed in that order, with
their strength computed from the list loaded and a button to draw others.
"Las elijo yo" lets the person type their own, with the warning that they
are weaker. Either way they are written again; case and accents do not
matter. planCapsule takes wordsKind (none, random or own) and asks for the
words that are missing.
licenses.txt carries the README of wordlists/, with the source, the method
and the license of the list (CC BY-SA 4.0), and check-build.mjs wants it,
and the list shipped byte for byte.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
wordlist.ts does what wordkey.Generate, CheckList and Bits of Go do at
27a75ee, with their texts: generateWords draws different words, 7 by
default, with crypto.getRandomValues; wordBits is their strength;
checkWordList refuses a list of fewer than 2048 words, with two words that
are one once normalized or with a character outside the alphabet of its
language, which the code gives and not the list. readWordList takes a list
only with the SHA-256 pinned for its language, in UTF-8 and accepted by
checkWordList: no list is trusted, not even those of DateKeys.
wordkey.ts gains wordRules, which loads the Unicode tables once for a
caller that reads many words; normalizeWords and checkWords use it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/sync-testdata.mjs copies wordkey/lists of the same commit of
datekeys-go into wordlists/, with its own SOURCE.json, and check verifies
both copies; the testdata test wants both from one commit. .gitattributes
keeps the bytes of wordlists/ as they are, like those of testdata/.
testdata and wordlists at datekeys-go 27a75ee, branch v0.15 after the tag
spec-v0.15: the files of testdata are those of the tag; wordlists brings the
Spanish list, 7776 words, CC BY-SA 4.0, with its README.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
datekeys-ts 0.4.0 implements spec v0.15 (tag spec-v0.15 of datekeys-go):
the release object, release archives and a release in hand that the clock
does not stop, besides everything 0.3.0 does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The versions table and the current version, releaseobject.ts and the
changes of release.ts and open.ts, the page with the release from a file
and a clock behind, the tests of release.json, releases/ and the source of
the mutation corpus, and the testdata at 3c3e737; a CHANGELOG section
"0.4.0 — sin publicar".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The release field takes a file too: a release object, drand's JSON or a
local release archive (spec v0.15, §47.1, §50). opener.ts gives it to
open as OpenOptions.release, a release in hand, never compared with the
clock: an archive is read only for its header and one signature, and a
file too large to be a release, and not an archive, is not read.
- What is pasted goes to open as drand's JSON, which names no chain.
- With a clock before the round time the form stays, without the request to
drand, and a release in hand opens the capsule; the result says the clock
seems to be behind (OpenReport.clockBehind).
- The glosses of steps 9 and 10 say what v0.15 checks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
datekeys-ts 0.3.0 implements spec v0.14 (tag spec-v0.14 of datekeys-go):
one drand scheme and the root of trust byte for byte, with the vectors of
tlock_steps.json, besides everything 0.2.0 does. It is the version frozen
for the external review.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- SPEC_VERSION 0.14; testdata synced from datekeys-go at 39b2033
(spec-v0.14), which adds vectors/tlock_steps.json;
testing/mutation-texts.json regenerated with Go: only its spec field
changes.
- Decision 8: validateProfile admits only bls-unchained-g1-rfc9380, with
its public key in G2, in the order and with the texts of Go's
validateDrand at c041fa3; any other drand scheme fails with
ERR_UNKNOWN_PROFILE before the key and the chain hash.
- vectors.test.ts walks tlock_steps.json value by value with the code of
ibe.ts, release.ts and bls12381.ts, with its negative checks, and the
testdata guard requires it. ibe.ts exports h3Base, h3Try and hashToG1,
which h3, the encryption and release.ts now use.
- The comment of h3 said the top bit is cleared: the first byte is
shifted one bit to the right, as kyber does.
- README and CHANGELOG.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
datekeys-ts 0.2.0 implements spec v0.13 (tag spec-v0.13 of datekeys-go): it
reads capsule formats 1 to 3 and writes format 3, with the author signature
of alg 1 and alg 2, the seal, the key of words, the public note and the
locator of datekeys.capsule, and the /inspect and /create pages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The vectors of Go are regenerated on datekeys-go 69dbb0c: only the cases
of those checks change. The writer of the extension refuses a DateKey of a
profile that is not pinned.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec v0.12, section 44.1, already asked for both. The vectors of Go are
regenerated on datekeys-go e801e03: only the ten addresses of those two
forms, and the locators that carry them, change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/inspect shows the public note under the verdict, as text of the creator
that nobody checked, with the warning of Go's showNote. The pages no longer
show the message of an unexpected exception: unexpectedProblem says in
Spanish what to do, and logs the exception. vite.config.ts pre-bundles the
dependencies the pages load on demand, so that the dev server does not
reload the page on the first opening and break the import in flight.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
encryptFiles gains authorKey (alg 1, an AuthorSigner such as AuthorKey),
cmsSigner (alg 2, a CMS signature with certificates), sealer (seal_type 2,
an RFC 3161 token) and largeArea, as EncryptOptions of Go at spec-v0.12:
the same checks in the same order with the same texts, the signature and
the seal made with the final control and head and before anything is
written, and the security area evaluated by the reader of this library in
the context of the capsule before it is written, as Go's security does.
The hooks may be asynchronous. The area grows to 64 KiB only when what was
signed does not fit and largeArea allows it, and the larger capsule counts
in the limit of memory. security.ts encodes the area with its signature and
seal, and securitycms.ts encodes SIGNERS.
scripts/signing-go-vectors_test.go, run as a test in an export of
datekeys-go at spec-v0.12, writes testing/signing-vectors.json: with the
draws of crypto/rand of Go and the signatures and tokens of its hooks,
encryptFiles writes the eight signed and sealed capsules of Go byte for
byte, asks the hooks over the same messages, and fails with the text of Go
in the other 15 recipes; and Go opens the five capsules that
scripts/signing-ts-samples.mjs writes with this library, its own random
values and certificates, with the same verdicts and lines.
check-build.mjs fails when a page loads the author keys with the page, or
when /inspect can load them at all.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
authorkey.ts ports the package authorkey of datekeys-go at spec-v0.12:
generate with an injectable random source, fromSeed, publicKey, sign,
clear, secret, a toString that hides the secret, publicString, parsePublic
(canonical, on the curve, not of small order), parseSecret, marshal, and
the key file encrypted with age and scrypt of work factor 16, read with a
maximum of 16, 64 KiB and the lines of bufio.Scanner, with the error texts
of Go and of Go's age byte for byte. Key strings are read as Go strings,
with the case and space tables of Go's package unicode (gounicode.ts,
generated by scripts/go-unicode-tables.go).
ed25519sign.ts is crypto_sign of TweetNaCl, as the Dart port, with the
SHA-512 of @noble/hashes: exact arithmetic in Float64Array, secrets never
in BigInt. No new package or module: age-encryption writes the scrypt
stanza, and the STREAM of a key file uses the ChaCha20-Poly1305 and HKDF
already imported.
scripts/authorkey-go-vectors.go, the generator of the Dart port with this
library's output, writes testing/authorkey-vectors.json in an export of
datekeys-go at spec-v0.12: 234 signatures, scalars, keys, Generate and
Encrypt with Go's draws (reproduced byte for byte), 1288 key strings,
3240 runes at the edges of the tables and 130 key files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ageio.ts reads and writes age files as filippo.io/age v1.3.2, with its
texts and its order of random draws, which Go's locator copies; it uses
only the noble modules that x25519.ts already uses. envelope.ts is Open,
Info.OpenLocator, OpenEnvelope, Seal and NewEnvelope of package locator
at spec-v0.12, with an injectable random source read in the order of Go.
- locator-seal.json (scripts/locator-seal-go-vectors.go): with the same
seed, seal and newEnvelope write the bytes of Go;
- locator-interop.json (scripts/locator-ts-samples.mjs and
locator-go-verdicts.go): Go opens what this library writes, up to a
.dkc of 16 MiB and one byte;
- vectors.test.ts runs all of testdata/vectors/locator.json with the
texts of Go, instead of its spec field only.
Shared files: dependencies.test.ts lets ageio.ts import noble and keeps
the four locator modules out of index.ts; check-build.mjs fails when a
page loads the locator with its first load; vitest.config.ts holds them
at 100 % coverage; ibe.ts updates the comment of encryptOnG2WithSigma;
README and CHANGELOG describe the port.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Port of package locator of datekeys-go at spec-v0.12 (spec §43 to §44.1),
with the checks, the order, the codes and the texts of Go: the data of the
extension (parseInfo, infoExtension), the registry of locator.Standard,
the addresses with every rule of §44.1 (checkURI, addressHost,
usableAddresses), the IP addresses as netip reads them, compared byte by
byte with the IANA blocks, checkResolvedIp as datekeys-dart has it, the
plaintext with its padding, and the rest in its host.
scripts/locator-go-vectors.go, the generator of datekeys-dart stage 7a
with the seeds of this repository, writes testing/locator-uris.json and
locator-vectors.json from an export of datekeys-go at spec-v0.12.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README: the module rows of der.ts, cms.ts, securitycms.ts, security.ts,
extension.ts (checkWrite), note.ts (checkNoteData, unusableNote) and
inspect.ts (the public note of the view); testdata at 601e6d2 while
SPEC_VERSION stays 0.11; the 218 cases of mutations.json; security.json,
security_cms.json, note.json and locator.json among the vectors that the
tests read. CHANGELOG: the two entries of 5 October.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
testdata is synced with the head of the branch v0.12 of datekeys-go
(601e6d2); SPEC_VERSION stays 0.11 until the author approves the draft.
- CMS as Go reads it at the draft v0.12 (review of 2 October, T2, T6 to T8
and the TypeScript side of E7 to E9):
- the certificate field by field with the profile of section 29.10, its
errors in CertificateError with the texts of Go; one that breaks it
decides nothing unless a SignerInfo names it, and two copies are one;
- the text of a name only from UTF8String, PrintableString, IA5String,
TeletexString in ASCII and BMPString without surrogates, never from an
attribute that appears twice; the holder by givenName and surname
before the commonName, the issuer by its commonName or its
organizationName;
- object identifiers by the bytes of their DER; a SET OF may repeat an
element; RSA with NULL parameters and an odd modulus; a key of another
scheme than its algorithm is invalid; a messageImprint of another
length is S3; the crls of a token decide nothing;
- DER: UTCTime and GeneralizedTime in their X.690 forms with a date that
exists, the restricted string types as primitive, the accuracy as
minimal INTEGERs. The test of cms.test.ts that compared a function
with itself has an expected value of its own.
- The verdicts in the texts of the draft: names between « and », shown
with at most 64 code points and no two spaces in a row, or their SHA-256;
in F6 the authority of each seal and the warning that nobody checks who
issued it; foreign signers in Spanish; times with their fraction.
- security.json in its context with lines, and the 135 cases of
security_cms.json, compared field by field, lines included.
- The 218 cases of mutations.json, with the texts of capsule.Open
regenerated by scripts/mutation-go-texts.go, and ibe-vectors.json with
the fixtures format3_note, format3_unsigned and the new
format3_seal_unsupported; its frozen values do not change.
- note.json, run with checkNoteData, publicNote and unusableNote.
- inspect reads the public note on demand, only for a header with one, so
that the Unicode tables never load with /inspect; the view of inspect
-json gives public_note and public_note_unusable, as Go.
A Go/TypeScript differential of 63,623 security areas, made from the
vectors, edited element by element and signed afresh with varied
certificates, tokens and authorities, gave no difference in verdicts,
results or lines; the code before this change differed in 13,296 of the
first 42,986.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As extension.CheckWrite of the Go reference on the branch v0.12:
- extension.ts holds NOTE_ID and CAPSULE_ID, and checkWrite: datekeys.note
goes only in the noncritical array of PUBLIC_HEADER and datekeys.capsule
only in that of a .dkk, version 1, with data that is checked; any other
extension is the application's own.
- The writer of capsules applies it in newSealer, after the public note
and before the profile, to the arrays of PUBLIC_HEADER, CONTROL_CBOR and
the head, with the rules of the note; the writer of a .dkk applies it
after checkDisjoint. The texts are those of Go, taken from a probe.
- note.ts: checkNoteData checks the bytes of a note in the order of Go's
CheckNote, length, then UTF-8, then the rules of text; unusableNote is
Go's Header.UnusableNote. lengths.ts no longer keeps its own NOTE_ID.
Green on the test data of spec-v0.11: it changes no output of a valid
writer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes T14 of the review of the session of 1 and 2 October:
- README: the table of modules gains author.ts, ed25519strict.ts, der.ts,
cms.ts, securitycms.ts and note.ts, and names Go at spec-v0.11; the row
of the format 3 gives the verdicts of v0.11, X, F0 to F6 and S0 to S5,
where it said X to S2, and says that evaluateSecurity never throws; the
rows of the writers, lengths.ts, index.ts and testing/ say where the test
vectors come from now, the area of 32 KiB and the public note.
- README: the table of runtime dependencies says what noble does for the
signatures and the seals, and the guards list the importers of noble of
v0.11 and the new guards of testing/; the counts of the corpus of
mutations (210 cases, four that open) and of capsule-vectors.json are
those of today.
- security.test.ts no longer says that the library does not reach the
verdicts of v0.11, nor that its texts are those of spec-v0.10.
- CHANGELOG: an entry for the fixes of the review, and what waits for
v0.12: the reader of certificates (T2, T6, T7, T8), the text of an
issuer without a commonName and the test of cms.test.ts that compares it
with itself.
npm run verify passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes T10 of the review of the session of 1 and 2 October: no test checked
that Go opens what encryptFiles writes today, since capsule-vectors.json
came from c3c124a, with an area of 512 bytes and no note.
- capsule-ts-samples.mjs writes format 2 with encryptVectors of
testing/encrypt.ts, as a generator of test vectors, and format 3 with
encryptFiles, as any caller writes it: the six samples of before, now
with the area of 32 KiB, and two more with a public note, one out of
ASCII, and one of 1024 bytes in time_and_key beside another noncritical
extension of the header.
- capsule-go-verdicts.go records the size of the area that capsule.Open
gives, the note that Header.PublicNote reads, the text of capsule.Encrypt
for a public note in format 2, and the text of capsule.EncryptFiles for
nine public notes that break their rules.
- interop.test.ts requires Go to open each of the 21 samples with each
credential, to find the area of 32 KiB in format 3 and to read the note
written, and this library to read the same note; and the texts of the 22
options and of the 9 notes to be those of Go.
Go at spec-v0.11 (ae33434) opens the 21 samples with each credential and
with all of them, encodes their objects again byte for byte, and gives the
texts of this library for the 22 options and the 9 notes; the four mixes,
the 500 inputs of the encoder differential and the 22 recipients give what
they gave. npm run verify passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes T9, T11 and T12 of the review of the session of 1 and 2 October:
- T9: EncryptOptions no longer has testVectors nor areaLen, with which any
caller could write format 2, or an area of 512 bytes, which rule 13
forbids and which tells that the capsule has no signature (§55.2). What
only a generator of test vectors asks, as Go's TestVectors, is the
TestVectors argument of the core of writer.ts, which only the helpers of
testing/encrypt.ts pass: encryptVectors and encryptWith write format 2,
and encryptFilesWith another area, with which the tests still reproduce
byte for byte the fixtures of 512 bytes. encrypt keeps the shape of
capsule.Encrypt: without a generator it fails with the text of Go,
whatever the caller adds. dependencies.test.ts refuses an import of
testing/ from anything but the tests and testing/ itself, check-build.mjs
refuses a test or a module of testing/ in the bundle of the pages, and
note.ts joins the modules that index.ts must not re-export.
- T12: encrypt as a generator refuses a public note and an area with the
text of Go, "capsule: format 2 has no security area or public note: ...",
after the head and the length, as capsule.Encrypt. The errors of the note
carry "capsule: ", and newSealer checks the note, then the profile and the
clock, in the order of Go. The tests compare the texts byte for byte, also
for two faults at once.
- T11: capsuleLength takes the public note and predicts exactly the size of
the .dkc with it: eight notes of 1 to 1024 bytes, across the boundaries of
the heads of CBOR, with both policies and with other extensions.
The 40 texts that capsule.EncryptFiles and extension.CheckNote give at
spec-v0.11 on the same notes and options, taken with an oracle, are those
of this library; HEAD gave another one in 23 of them. npm run verify
passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes T4 and the rest of T5 of the review of the session of 1 and 2
October:
- note.ts: checkNote refuses a string with a lone surrogate, which UTF-8
cannot hold, after its length and with the text that extension.CheckNote
gives for invalid UTF-8. newNote wrote U+FFFD in its place, and the note
is public and permanent (spec §62.1 rules 15 and 23).
- note.ts: publicNote reads the data with decodeUtf8, which keeps a leading
U+FEFF: such a note is unusable, as in Go, where it showed without it.
- author.ts: authorCode takes the eight bytes of the code as Go's
AuthorCode takes them, a leading U+FEFF kept.
- inspector/drand.ts: an answer of a relay that starts with a BOM is
refused, as json.Unmarshal refuses it in the client of the reference.
- The texts of the head and the paths of format 3 already kept it, since
cbor.ts decodes them with decodeUtf8: head.test.ts now pins it with the
texts of Go. The other TextDecoder of src/lib, in age.ts, reads tokens of
ASCII that are checked byte by byte before.
The texts are those of extension.CheckNote, extension.Note,
capsule.DecodeHead and capsule.AuthorCode at spec-v0.11, taken with an
oracle on the same bytes; the drand client of the reference refuses the
answer with json.Unmarshal. npm run verify passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes T1, T3, T13 and the CMS part of T5 of the review of the session of
1 and 2 October (docs, spec_v0.11/revision_sesion_1_2_octubre.md):
- securitycms.ts: an issuer that breaks the rules of the declared author
shows the SHA-256 of the DER of its Name, Go's sha256.Sum256(RawIssuer),
and no longer that of the certificate (cms.certIssuerHash).
- cms.ts: an ECDSA key counts only with its point uncompressed, 0x04 and
the two coordinates, the only form that Go's x509.ParsePKIXPublicKey
reads: a compressed one makes a signer not verifiable (F5) and a seal S1.
- cms.ts: a UTF8String and the times of a certificate and of a token keep a
leading U+FEFF, as Go reads the bytes: such a name shows the hash, and
such a time breaks the profile (F1, S2).
- cms.ts: oidOf and intOf take time linear in the length of the element.
An arc of up to seven digits accumulates in a number, a longer one and
every INTEGER are read whole from hexadecimal, never by a shift per byte,
which took some 700 ms for 60 KB; attributes of one type are appended,
not copied.
- security.ts: evaluateSecurity never throws. A fault while it evaluates
the signature gives F1, one while it evaluates the seal S2, each apart,
and one while it decodes the area X, as the Go reference will from v0.12.
- Tests: securitycms.test.ts and security.failure.test.ts are new.
cms.test.ts now refuses a second content-type and two signature-time-
stamps for the rule of the count, with every SET OF in DER order, and
der.test.ts tests the depth at its boundary. cmsbuild.ts makes names,
validities and compressed points of its own.
capsule.EvaluateSecurityIn of the Go reference at spec-v0.11 gives the same
verdicts, signer lines and Spanish lines on 25 areas made with cmsbuild.ts:
issuers with ESC, U+202E, empty, of 300 bytes or with a leading U+FEFF;
names and times with a leading U+FEFF; and compressed keys on P-256, P-384
and P-521, as signers and as authorities of a seal. HEAD gave other ones in
19 of them. npm run verify passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
encryptFiles writes the security area of 32 KiB, as rule 13 of 62.1 asks of
a writer of v0.11, and accepts publicNote, the extension datekeys.note of
PUBLIC_HEADER, with the rules of text of 24.1 (note.ts). Another area is for
a generator of test vectors, with testVectors and areaLen, so that the tests
still reproduce byte for byte the fixtures that a writer of v0.10 wrote with
512 bytes. lengths.ts and the page plan L with the new area. A note changed
after writing fails at step 15. npm run verify passes.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
der.ts checks DER byte by byte. cms.ts reads the CMS signature and the RFC
3161 token of spec v0.11 29.10 and 29.11 with the closed table of
algorithms: RSA PKCS 1 and PSS with BigInt, ECDSA with the arithmetic of
@noble/curves, no new package. securitycms.ts gives F1, F2, F5 and F6 with
the signers named, and S1 to S5 with the authority of a valid seal.
evaluateSecurity returns them with their detail, and verdictLines writes the
lines of F6 and S4. The 22 cases of security_cms.json and the fixtures
format3_signed_cms and format3_sealed give the verdicts, the signers and the
seal of the Go reference. testing/cmsbuild.ts builds signatures and tokens
with WebCrypto for the hostile cases ported from the Go tests, and the
pending mechanism of the first sync is gone. npm run verify passes.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
ed25519strict.ts checks the four conditions of spec v0.11 29.9 on top of the
arithmetic of @noble/curves and gives the answer of Go on the 18 vectors of
ed25519_strict.json. author.ts computes payload_commit, control_commit,
head_digest, signers_digest, AUTHOR_MESSAGE and its code, as the record of
format3_signed says. evaluateSecurity takes the context of the capsule and
gives F2, F3 or F4; open passes it, and OpenOptions.authorKeys are the keys
the person saved. No new package: both modules use @noble/curves and
@noble/hashes, which were already in the bundle.
Alg 2 and the time seal are still read as v0.10 reads them, and the tests say
so with testing/pending.ts. npm run verify passes.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
SPEC_VERSION is 0.11. testdata brings format3_signed, format3_signed_cms and
format3_sealed, and the vectors ed25519_strict.json, security_cms.json and
locator.json; the mutation corpus has 210 cases. ibe-vectors.json adds the
three fixtures and remakes the two that Go regenerated, and
mutation-texts.json is made again with that reference.
This library still reads the security area as a reader of v0.10, so a
signature or a seal that the reference checks gives F1 or S1 here. The
Verdict type and the texts know F2 to F6 and S3 to S5, and the tests state
the gap with testing/pending.ts instead of hiding it; porting the
verification makes that file the identity. npm run verify and
testdata:check pass.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
As the spec v0.11 draft decides after its review (38.1), and as the Go
reference does from 2213b8c:
- dkc/wordkey.ts replaces inspector/wordkey.ts. The salt carries the
capsule_id too, so the same words give another key in each capsule;
the words are lowered with the new LOWERCASE table of pathrule.ts,
loaded on demand; checkWords refuses controls, invisible and
unassigned code points and counts only different words of three
letters or more, with the errors of Go. New vector of 38.1.
- encryptFiles takes the words and derives their key once it has drawn
capsule_id; the creator passes them, and the opener salts them with
the capsule_id of the capsule.
- /create asks for the words twice and shows how they are kept; the form
checks them with the tables of the platform, and the writer again with
those of Unicode 18.0.0.
- The tables, regenerated with the lower case, and testdata synced from
2213b8c; the frozen texts of Go for the invalid options, updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
normalizeWords lowers each code point on its own, as Go's simple
mapping does (no final sigma), and splits at the white space of Go's
unicode.IsSpace, so that the page and wordkey.Normalize of datekeys-go
give the same words; both test the same PBKDF2 vector.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The author wanted a key that people can keep without files. A capsule
"solo con una llave" can now take words the person chooses, at least
six, on /create, and /inspect opens it with them. wordkey.ts derives
the X25519 identity with PBKDF2-SHA256 of Web Crypto, 600 000 rounds,
salted with the chain and the round of the capsule, after making case,
accents and extra spaces not matter; its public key is one more
recipient, so the format does not change. The writer wipes the private
half at once; the opener adds it to the identities it tries.
Checked in Chromium: a capsule created with "Perro luna casa verde
trén mar" and no .dkk opened with "perro LUNA casa verde tren mar",
with the release fetched from drand by the page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The author found copying the release of the round tedious. A button,
"Pedir la firma a drand", fetches it from the three public relays of
the CLI of the reference, as its client does: raced, 6 s, at most
8 KiB an answer, no redirects, and the randomness checked against the
signature; step 10 still verifies the signature with the pinned key,
so a relay cannot make the page accept a false one. It is the only
connection the page makes to another site, and only on that click: the
CSP allows those three origins in connect-src, check-build.mjs
requires exactly them, and the footer says so. Pasting by hand still
works. Checked in Chromium: api2.drand.sh gave the release of round
32668196 and the capsule opened.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>