tool/locator_go_vectors.go runs package locator of datekeys-go at c531e93,
the draft v0.12, in its module, without changing it, and writes what Go
gives, with the texts of its errors:
- locator_uris.json: CheckURI and Address.Host on the 247 addresses of
testdata/vectors/locator.json and on 2 800 more, built at every edge of
spec 44.1 and drawn from a seed: IPv4 and IPv6 in every notation that
netip.ParseAddr accepts or rejects, zones, mapped, NAT64 and 6to4
addresses, the first and last address of every IANA block and their
neighbours, long and punycode labels, local names, ports, percent
signs, dot segments and CIDs; netip.ParseAddr and String on 1 700
strings; and publicIP, reached with go:linkname, on 868 byte strings.
- locator_vectors.json: the texts of the other cases of locator.json;
PlaintextLength from -4100 to 16484; Unmarshal on 482 plaintexts; Marshal
at every limit and boundary of the padding; Open on 118 sealed locators
of four rounds, edited or with other releases and profiles; Open past
1 MiB of plaintext, read through io.LimitReader; the envelope, its rest,
Hide and the split of NewEnvelope; Info.Extension, Info.OpenLocator and
ParseInfo; locator.Standard as a registry; and capsule.Open of a fixture
whose .dkk carries datekeys.capsule.
crypto/rand.Reader is a ChaCha8 of a fixed seed, so every run writes the
same bytes. The Dart constants hold the whole of the first file and a
part of the second, for the tests compiled to JavaScript.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/age_writer_bench.dart times the header of each age file of a
capsule, the file of an author key and a large PAYLOAD_AGE in streaming,
with the CSPRNG of the platform. On the VM, 64 MiB take 1.38 s, 46
MiB/s; compiled to JavaScript, 16 MiB take 0.33 s, 49 MiB/s. The header
of PAYLOAD_AGE costs 4 ms, INNER_ACCESS_AGE with 16 stanzas about 45 ms
on the VM and 35 ms in Node.js, OUTER_TIME_AGE 40 ms and 0.55 s, and an
author key file with scrypt of logN 16, 0.6 s and 0.85 s.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/age_interop_dart_samples.dart writes the files of the recipes of
test/age_interop_support.dart with SeededRandomSource, and
tool/age_interop_go_verdicts.go, in an export of datekeys-go, opens them
with age and the identities of agewrap and writes age_interop.json:
X25519 from 0 bytes to 3 MiB, one written in pieces, three and sixteen
recipients, tlock opened with the release of round 1000 of the fixtures,
tlock over sixteen X25519 as a SEALED_CONTROL, and scrypt with work
factors 10 and 16. Each sample keeps its recipe, the length and the
SHA-256 of its file, the file when small, its stanzas, the stanza rules
of agewrap on them and the verdict of Go with each opener.
The tests write each file again and must get the one that Go read; Go
opened it to the plaintext of the recipe, or refused it with an
identity that must not open it; and this library makes the same of it
as Go, with the same texts and the same stanza rules.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/age_writer_go_vectors.go runs in an export of datekeys-go at
c531e93 and makes crypto/rand read the keystream of the seeded source of
the writer: ChaCha20 under SHA-256(seed), with a zero nonce. age.Encrypt,
with the real X25519, scrypt and tlock recipients, then draws known
values, and age_writer.json records every draw, its size and its order,
with the files: one X25519 recipient over plaintexts of 0 bytes to 3 MiB
across the chunk boundaries; two, three and sixteen, and one with bit 255
set, which age accepts; scrypt with work factors 1 to 16; and the tlock
stanza of rounds of 1 to 11 digits.
The generator checks each file against testkit.SealAge, with the first
draw as the file key and the last as the nonce, checks each X25519
stanza against its ephemeral secret, and opens the file with Go. It also
records the errors of age.Encrypt with the draws before them, those of
the constructors, ParseX25519Recipient, CheckX25519Recipient,
GenerateX25519Identity, crypto/rand.Int and the permute of capsule over
the keystream, and the lengths of testkit and capsule. The output is the
same on every run. age_writer.g.dart holds the same JSON for the tests
compiled to JavaScript.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Injected faults showed two rules that only the tests on the VM checked:
SIGNERS of more than 16 entries, whose only case was in security_cms.json,
and the order of the foreign signers. securitycms_vectors.json gains
SIGNERS of 16 and of 17 entries with Ana among them, beside her signature
for those SIGNERS or for SIGNERS with her alone, and a required signer
beside two foreign ones, without seals so that the area stays small; the
part for Node.js holds them. 760 cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/open_bench.dart also opens format3_signed_cms, a signature of alg 2
by two signers each with a seal, and format3_sealed, a signature of alg 1
and a seal of seal_type 2, from securitycms_vectors.g.dart, and times
inside each opening the evaluation of its security area by the default
evaluator. On the VM an opening takes about 51 ms, of which the area
about 9 ms; compiled to JavaScript, about 1 s, of which the area 145 ms
and 49 ms.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/security_go_vectors.go also writes securitycms_vectors.json:
EvaluateSecurityIn of package capsule at the draft v0.12 on 755 areas
whose CMS signature or RFC 3161 seal it makes, as internal/cms/cmstest
makes them, with the verdicts, the lines, the detail of every signer and
of a valid seal, and SealedAt. Required and foreign signers of every
result; three required signers drawn from a seed; the validity of a
certificate at the time of its seal, at the nanosecond; t plus the
accuracy against the round time on both sides of it, Go's zero time and
the last second of 9999; a seal of each verdict beside a signature of
each verdict; and mutations of a SignedData, of SIGNERS and of tokens.
cmstest cannot be imported from outside the tree of datekeys-go, so the
part of it these cases need is restated. The keys come from labels, ECDSA
signs with the nonce of RFC 6979 and RSA with PKCS #1 v1.5: every run
writes the same bytes, and security_vectors.json and its part are the
same as before. Certificates, tokens and SignerInfo are written once, as
chunks. securitycms_vectors.g.dart holds a part of the cases, each verdict
pair of each group among them, and the fixtures format3_signed_cms and
format3_sealed, for the tests compiled to JavaScript.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/cms_bench.dart times, on the VM and compiled to JavaScript, one
verification of ECDSA on each curve and of RSA of each size and scheme,
the reading of a certificate, and a signature and a token read and
checked, on the cases of cms_vectors.g.dart.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/cms_go_vectors_test.go records what internal/cms of datekeys-go at
c531e93 (the draft v0.12) and the ECDSA and RSA of Go give: the curves,
points and signatures of ecdsa.VerifyASN1; RSA keys of 2048 to 4096 bits
and signatures of rsa.VerifyPKCS1v15 and VerifyPSS, with encodings built
by hand, each with one defect of its padding; ParseCert, ParseSignature,
SignerInfo.Check, ParseToken and Token.Check on the cases of the tests of
internal/cms and others (identifiers whose arcs wrap around in 32 or 64
bits, SET OF with an element repeated, the limits of the accuracy and of
the imprint, the ends of the validity); signatures, tokens and
certificates edited node by node and bit by bit; and every signature and
token of security_cms.json and of the two CMS fixtures, signer by signer.
It runs as a test in an export of datekeys-go, so that it can import
internal/cms and make keys and signatures deterministic with
testing/cryptotest: every run writes the same bytes. Each file stays
under 560 KB; repeated certificates are written once per file.
cms_vectors.g.dart holds a part of each file for the tests compiled to
JavaScript, and a test on the VM checks that it is that part.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OpenOptions.evaluator is now evaluateSecurityInput, so that opening a
capsule of format 3 gives the verdicts of Go at step 17: the signature of
alg 1 and every verdict of the form, with the author keys of the options,
and the signature of alg 2 and the seal of seal_type 2 not evaluated
until a reader of CMS is given. notEvaluated stays for a caller that
shows no verdict.
tool/open_go_vectors.go records the verdicts of each capsule of format 3
that opens, with their lines, the key and the label of alg 1 and the
earliest valid seal, and opens the fixtures signed with alg 1 also with
their author key saved, F3, and with another, F4. Every case of
open_cases.json and every case of the mutation corpus that opens gives
those verdicts and lines: format3_signed, format3_unsigned,
format3_signature_unsupported, format3_seal_unsupported,
format3_security_v2 and format3_note all of them, and format3_signed_cms
and format3_sealed the part that needs no reader of CMS.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/security_go_vectors.go writes test/vectors/security_vectors.json
with package capsule of datekeys-go at c531e93, the draft v0.12, run in
its module without changing it, and a part of it for Node.js in
security_vectors.g.dart:
- the commitments: PayloadCommit, ControlCommit of the control of every
fixture and of controls built with extensions, in each format, with
the text of the error where CONTROL_SIG cannot be encoded, HeadDigest,
SignersDigest, AuthorMessage, AuthorCode, also of messages that
AuthorMessage never writes, SigPart and SealSubject;
- the encoders of SECURITY_CBOR, author-signature and seal;
- 1730 evaluations of SECURITY_CBOR with EvaluateSecurityIn in 23
contexts, and EvaluateSecurity without one: the outer map,
author-signature and seal broken in every way of their schemas and
limits; signatures of alg 1 valid and invalid, saved or not, with the
cases of Taming the many EdDSAs made over AUTHOR_MESSAGE by searching
the context; and mutations of nine bases from a fixed seed. Each case
gives the verdicts, the key and the label of alg 1, the lines, alg and
seal_type as read, and the parts that only the reader of CMS evaluates;
- Lines and SealedAt of verdicts built with every pair of verdicts and
the details of signers and seals;
- holderText, reached with go:linkname, on names at the limit of 64 code
points and drawn from the seed.
The files are ASCII, and every run writes the same bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
testdata/ is synced with datekeys-go at c531e93, the head of the branch
v0.12, whose testdata is that of 601e6d2, the copy of datekeys-ts. Every
file keeps "spec": "0.11": the draft v0.12 is not approved yet. From the
tag spec-v0.11 it brings the fixtures format3_unsigned and format3_note,
format3_seal_unsupported with seal_type 4294967295, the records of
format3_sealed and format3_signed_cms, the mutation corpus of 218 cases,
note.json, security.json with a context and lines, security_cms.json of
135 cases and locator.json.
The vectors that the generators of tool/ make from the testdata are
written again by Go at c531e93: mutation_texts.json, open_cases.json,
formats_*.json with formats_vectors.g.dart, ibe_vectors.json and
age_fixtures.json; release_vectors.json, primitives.json and the views
of open_vectors.g.dart come out the same. age.json does not read the
testdata, and stays frozen: age draws its keys from crypto/rand. The
tests count 26 fixtures and 218 cases, and the inspection of
format3_note gives the note of its record. No difference with Go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/open_bench.dart times, on the VM or compiled to JavaScript, the
opening in memory of a fixture of each kind, time_only, time_and_key with
its .dkk in formats 1, 2 and 3, and format 3 with its file, each with the
verification of its release, and the throughput of a capsule opened from a
source in streaming, which test/large_capsule.dart makes from the
fixtures: 64 MiB on the VM, 16 MiB on Node.js. Medians of three runs on
the VM: 48 to 73 ms for a fixture, 1.50 s for 64 MiB in format 1 and
2.64 s for 64 MiB in one file of format 3, whose SHA-256 adds 17 ms per
MiB; on Node.js about 0.8 s for a fixture, 0.73 s for 16 MiB in format 1
and 0.92 s in format 3.
It never passes a sink as `c ? null : sink`: dart2js of Dart 3.13 loses
the writes to an object that reaches a field that way, and its counter of
bytes read 0 afterwards.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/mutation_go_texts.go ports scripts/mutation-go-texts.go of
datekeys-ts over the synced testdata of this repository, the tag
spec-v0.11: it replays every case of the mutation corpus as the testkit of
the reference does and writes the text of capsule.Open and its checks,
with the detail of each step, in mutation_texts.json. Where Go and the
corpus disagree on a code or a step it would say so in the case; Go at
c531e93 and at the tag spec-v0.11 agree with all 210 cases, and give the
same file, byte for byte.
tool/open_go_vectors.go runs in an export of datekeys-go, since it uses
internal/testkit, internal/cbortest and internal/inspectview, and writes:
- open_cases.json: capsule.Open on every fixture with each of its
credentials, and 117 openings of edited fixtures or with other options
at each step that the corpus does not reach: the frame, the fields, the
extensions and the bindings of a .dkk at step 9.a, the clock and the
failures of the release source, the age headers of steps 11 and 17, a
malformed X25519 stanza in INNER_ACCESS_AGE, CONTROL_CBOR and the BODY
of format 3 sealed again, the sinks and the output that fail, the
refusal of Accept and the unusable extensions of each object, with the
text, the step, the checks, the release requests, the state of the
sink and the content or the files;
- open_heads.json: capsule.DecodeHead and EncodeHead of heads of a fixed
seed, valid and broken in each layer of spec §69.1;
- open_notes.json: extension.CheckNote, Note, Header.UnusableNote and
extension.Standard with a note;
- open_inspect.json: the text of capsule.Inspect for each of the 5110
mutations of inspect_differential.json, where Go and the file also
agree, and the exact output of datekeys inspect -json with public notes;
- open_vectors.g.dart: seven small fixtures, their records and a part of
each file, for the tests that run compiled to JavaScript.
The edited capsules are sealed again with the file keys and the nonces of
the fixtures, as the testkit does, so the output is the same on every run.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/pathrule_bench.dart times, on the VM or compiled to JavaScript,
checkPath of a path of ASCII and of one that R6c projects with its 15
tables, checkComment of a comment of 16 351 bytes, checkTree of 1000
paths, the largest head (65 535 paths checked and their tree),
normalizeWords with checkWords, and wordKey with its 600 000 iterations
of PBKDF2. Medians of three runs on the VM: 9.5 and 28 microseconds for
the paths, 0.68 ms for the comment, 2.0 s for the largest head and
1.14 s for the key; on Node.js 11.8 and 38 microseconds, 0.63 ms, 2.3 s
and 0.73 s.
The header of tool/pathrule_go_vectors.go says now that its named cases
hold both sides of each limit of R2, R3 and R6b.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Faults injected one at a time found four that the vectors let through:
R2 at 32 segments, R3 counting code points instead of UTF-16 code units
in an astral NFD, U+036F kept by normalizeWords, and DEL let through by
checkWords. The generators now write both sides of each limit: 32 and 33
segments, 255 and 256 bytes in letters of two and four bytes, 255 and 256
UTF-16 code units of NFD and 252 and 258 from astral decompositions,
bases of 8 and 9 runes, extensions of 3 and 4 also astral, the first and
the last mark of U+0300 to U+036F and their neighbours, and U+001F,
U+007E, U+007F, U+0080 and U+00A0 in a word. All four faults are caught
now.
wordKeyPassword is the password P of spec §38.1, as wordKeySalt is S, and
wordKey uses both: the tests compiled to JavaScript check P against the
one of Go, so that a wrong separator of the words is caught there too,
not only by the keys of 600 000 iterations on the VM.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/src/wordkey.dart ports package wordkey of datekeys-go at c531e93:
normalizeWords is wordkey.Normalize (the NFD of pathrule.dart, without
U+0300 to U+036F, the simple lowercase of Unicode 18.0.0, split at the
white space of §38.1), checkWords is wordkey.Check with its texts,
wordKey is wordkey.Key (PBKDF2-HMAC-SHA256 of sha256.dart, 600 000
iterations, with the salt of §38.1) and wordIdentity is wordkey.Identity,
an X25519Identity of age.dart. As in pathrule.dart, the functions whose
name ends in Utf8 take the bytes of a Go string, and a String is taken as
utf8Bytes writes it.
tool/wordkey_go_vectors.go runs in the module context of datekeys-go and
writes test/vectors/wordkey_vectors.json and its Dart copy: 400 texts and
their words, 513 lists of words and the result of Check, and four keys
with their salt, the PBKDF2 of 1000 iterations for Node.js and the
recipient, the vector of §38.1 first. The keys of 600 000 iterations run
on the VM only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/src/pathrule.dart ports internal/pathrule of datekeys-go at c531e93
(spec §29.5, §29.5.1, §29.6): NFD with the canonical ordering and Hangul,
the case folding, the simple lowercase, Default_Ignorable with the
whitelist of R4, the best-fit projections of R6c, every rule of a path
(R2 to R6c and R10), the tree (R7 with its key and the two paths it names,
and R9), and the texts of the comment and the declared author, with the
texts of Go. canonicalTables is pathrule.Canonical, and a test recomputes
tablesDigest from the lists.
Go reads a string as bytes, and so does this port: the functions whose
name ends in Utf8 take the bytes of a Go string, where a byte that is not
valid UTF-8 is the rune U+FFFD, and the limits count bytes; the others
take a String as utf8Bytes writes it. Each rule returns its violation, as
in Go, and only the public functions throw.
tool/pathrule_go_vectors.go runs in an export of datekeys-go, since
internal/pathrule cannot be imported from outside its tree, and writes
test/vectors/pathrule_vectors.json and its Dart copy: the cases of the
tests of Go and of datekeys-ts, 1300 strings and 350 trees drawn from a
fixed seed (marks, Hangul, ignorables, emoji, best-fit look-alikes,
device names, 8.3 aliases, limits, texts and invalid UTF-8), the cases of
R9, code points, and for each plane the SHA-256 of one line per code
point of each function. Every code point of every plane gives the results
of Go: planes 0, 1 and 14 also on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A fault that ignored the top bit of FLAGS of a .dkc passed the tests: the
cases had FLAGS of 1, or random bytes with other bits set. The generator
now writes each bit of FLAGS and of RESERVED alone, in the PRELUDE of a
.dkc and in the frame of a .dkk, with the text of Go, and the tests on the
VM and on Node.js try every bit of both frames.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A fault injected in the order of the layers of PUBLIC_HEADER, parsing the
DateKey before the rule across the extension arrays, passed the tests: no
random case had a DateKey of layer 4 and a fault of layer 3 together. The
generator now builds, for PUBLIC_HEADER, CONTROL_CBOR of the three
formats, the Provider Profile and the .dkk, each fault of a list alone and
each pair of them on a valid object, with Go's code and text: 153, 360,
153 and 181 cases, the .dkk sometimes with FLAGS 1 too. The cases use no
random value, so the other sections are the same as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/formats_go_vectors.go runs in the module of datekeys-go at c531e93,
without changing anything there, and writes test/vectors/formats_*.json:
the result, the normative code and the text of Go on inputs of a fixed
seed, valid and broken in every layer of spec §69.1, and on the fixtures
of testdata/, edited:
- the PRELUDE (229 cases), the steps 1 to 3 of capsule.Inspect on cut and
edited fixtures (492) and whole .dkk files (268);
- PUBLIC_HEADER (660) and CONTROL_CBOR of the three formats (618);
- Provider Profiles decoded (163) and validated as values (60);
- extension arrays (260), Canonical (80), CheckDisjoint (50), the
registries with places (120) and CheckWrite with Standard (60);
- dk1_ strings (466);
- RFC 3339 parsed (434) and formatted (80), Resolve (320), RoundTime (64),
Validate (128) and MaxRound (8), on profiles of other genesis times and
periods;
- PaddedLength and PayloadAgeLength at the boundaries up to L_MAX (474),
and the check of the padding of capsule.Open at step 17 on fixtures whose
PAYLOAD_AGE is encrypted again with an edited plaintext (56);
- the encoders on values and the decoders at the limits of spec §57 (90);
- the frame of BODY (260) and the zeros of the area (60).
The output is the same on every run. formats_vectors.g.dart holds every
eighth case as Dart constants, so that the differential runs compiled to
JavaScript too, on Node.js; a test on the VM checks that they are those of
the files. Every file is under 310 KB.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Like those of stage 2, the four generators of stage 3 run in the module
of the datekeys-go next to this repository, which they import, without
changing anything there: cd ../datekeys-go && go run ../datekeys-dart/tool/
… The tag spec-v0.11 and the draft v0.12, whose packages provider, agewrap,
profile and capsule.ParsePrelude are the same, give the same output as the
committed vectors, byte for byte.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/bls12381_bench.dart times, on the VM or compiled to JavaScript, the
decoding of a point of G1 and of G2, a pairing, the verification of a
Quicknet round signature, the IBE decryption and encryption, and steps 10
and 11 of the opening together, as the plan asks in «Rendimiento». It
reads no file, so that a phone can run it too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ibe.dart is DecryptCCAonG2 and EncryptCCAonG2 of drand/kyber for Quicknet,
as ibe.ts of datekeys-ts: H2 over GT in the order of kilic, H3 with its
rejection of candidates, H4, the identity of a round, the gates of the
signature and of U, and fixed texts that carry no value of the
computation. Encryption takes an injectable sigma, so that the vectors of
Go reproduce byte for byte; sigma and r are secret and BigInt is not
constant time.
release.dart is provider.Verify, in its order and with its texts, for the
scheme of Quicknet only, as release.ts; the supplied release; and the rule
of step 9, under which whatever a source throws is
ERR_RELEASE_UNAVAILABLE. tlock.dart is NewTimeIdentity with its Unwrap and
NewTimeRecipient of agewrap on the arguments and the body of the stanza.
tool/ibe_go_vectors.go, tool/tlock_go_vectors.go and
tool/release_go_vectors.go, ports of the generators of datekeys-ts where
they exist, write the vectors from kyber, tlock, age, provider and agewrap
on the fixtures of testdata/. The ciphertexts with a random sigma are the
frozen ones of datekeys-ts at 289fe71, decrypted again by Go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The field layer, an extension type over BigInt that a later implementation
with fixed limbs can replace alone; the tower Fp2, Fp6 and Fp12 with the
formulas of kilic; G1 and G2 with their compressed encodings and the
verdicts of FromCompressed (flags, the point at infinity, coordinates below
p, the curve and the subgroup, checked in G2 by psi(P) = [x]P); the optimal
ate pairing with the final exponentiation of kilic, GT serialized c1 before
c0 at every level; and the hash to G1 of RFC 9380 with the DST of Quicknet.
tool/bls12381_go_vectors.go writes test/vectors/bls12381_vectors.json with
kilic and kyber-bls12381: the frozen edge cases of datekeys-ts with their Go
verdicts recomputed, and decodings, sums, multiples, pairings, hashes, maps
and BLS signatures drawn from a fixed seed. BigInt is not constant time:
the README says where that matters.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the web a shift truncates to 32 bits, so the carries of Poly1305 are
taken with a division. A fault injected in the carry of limb 0 passed every
test, on the VM, where the shift is exact, and on Node, because no vector
took that sum past 2^32. The generator now simulates the 13-bit limbs with
the largest r that clamping allows and finds two messages that do; Go's
poly1305 gives their tags, and the fault fails on Node. The sums of the
other limbs stay below 2^32 (at most 4.14e9 with that r).
The strict Ed25519 verification is also checked against
testdata/vectors/ed25519_strict.json directly.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The product of Poly1305 and that of the field of curve25519 are unrolled
over locals, as TweetNaCl-js does, and ChaCha20 XORs whole blocks: on the
VM, X25519 goes from 2.4 to 1.3 ms, Ed25519 verification from 8.6 to
4.7 ms and ChaCha20-Poly1305 from 40 to 19 ms per MiB. The bounds of the
arithmetic do not change.
tool/bench.dart times the primitives on the VM or compiled to JavaScript.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
age: the header and its limits (internal/format), with the texts of Go's
errors; the header MAC; the X25519 and scrypt stanzas, the scrypt work
factor bounded at 16 by default, as authorkey bounds it; the payload key
and the STREAM of internal/stream, decrypted as the ciphertext arrives,
with the same end-of-file cases as Go's DecryptReader. Each failure is an
AgeException with Go's text and its phase, the header or the payload.
agewrap: the stanza rules of OUTER_TIME_AGE, PAYLOAD_AGE and
INNER_ACCESS_AGE, the probe of the stanzas, and the payload and access
identities, with the fixed texts and the codes of datekeys-go.
tool/gen_age_vectors.go writes, with filippo.io/age and agewrap:
- test/vectors/age.json: X25519 and scrypt files, their truncations and
manipulations, a corpus of headers against the grammar of spec §28.1
and the 2 MiB limit, the rules and identities of agewrap, and Go's text
for each. A file of more than one chunk is its header, nonce and file
key; the tests encrypt the plaintext again and check the SHA-256 of the
whole file;
- test/vectors/age_fixtures.json: the PAYLOAD_AGE of every fixture with its
payload_identity, and the INNER_ACCESS_AGE of the time_and_key ones,
taken from OUTER_TIME_AGE with the release of the fixture.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The generator checks its copy of the strict profile against the
testdata/ of datekeys-dart, the copy synced at spec-v0.11, rather than
the working tree of datekeys-go. The vectors do not change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SHA-256 with its own compression, and on it HMAC-SHA256 with the inner and
outer states of the key computed once, HKDF-SHA256 and PBKDF2-HMAC-SHA256,
whose iterations are two compressions over words; scrypt with Salsa20/8;
ChaCha20, Poly1305 in 13-bit limbs and ChaCha20-Poly1305 with the tag
compared in constant time; X25519 on the field of TweetNaCl in doubles,
with the all-zero secret refused; the strict Ed25519 verification of
internal/ed25519strict; Go's Base64 with the offsets of its errors, and
age's Bech32.
tool/gen_primitive_vectors.go computes every expected value with Go and
x/crypto, from the inputs of RFC 5869, 7748, 7914, 8032 and 8439, edge
cases and seeded random ones. The tests also run compiled to JavaScript,
from a Dart copy of the JSON, without the cases that would take too long.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tool/check.sh runs dart test -p node after dart test: the tests that read
no file check on every commit that the integers of the library are exact
on the web, where an int is a double and the bit operators work on 32 bits.
The gate needs Node.js, as datekeys-ts does. The author decided it on 5
October.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A pure Dart package, without Flutter, for the app that the author will
write in Flutter (docs/PLAN_dart.md, stage 0):
- pubspec.yaml: the package datekeys, unpublished, for Dart 3.13; at run
time only package:crypto, and in development only package:test, which
the author approved on 5 October.
- testdata/ vendored from datekeys-go at the tag spec-v0.11 (ae33434),
124 files, with the same testdata/SOURCE.json that datekeys-ts writes for
that commit.
- tool/sync_testdata.dart, the port of scripts/sync-testdata.mjs, and
test/testdata_test.dart, which checks the copy and that every file names
specVersion; test/version_test.dart keeps pubspec.yaml and
lib/src/version.dart in step.
- tool/check.sh, the local gate: format, analysis with every info fatal,
tests, and the copy against ../datekeys-go.
- The licence, Apache-2.0, as the other two implementations.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>