open_cases_test.dart compares the opening of each fixture with each of its
credentials with the record of the fixture itself, not only with what Go
wrote: the content of formats 1 and 2 is its .plaintext, whose SHA-256 the
record gives, and in format 3 each file is the range of BODY that the
record names, with its comment, its declared author and the size of its
area. The changelog counts 1320 tests on the VM.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/src/open.dart and open3.dart port Open and openBody of package capsule
of datekeys-go at c531e93, with the checks, codes, steps and texts of the
reference and the detail of each check: the .dkk of step 9.a, decoded or
still encoded, with its material, its critical extensions, its capsule_id
and its capsule_digest; at least one credential; the clock and the release,
with the rule of step 9 for the failures of its source (sourceFailure);
its verification at step 10; OUTER_TIME_AGE with the tlock stanza;
INNER_ACCESS_AGE with the X25519 identities, those of the .dkk and the key
of words, and the rules of the slots; CONTROL_CBOR, header_binding,
I_PAYLOAD and P; PAYLOAD_AGE streamed, with the padding of format 2
checked and never delivered, and in format 3 the frame of BODY, the area,
the head, each file to the sink with its SHA-256 and the padding, with the
precedence of spec §63; and the commit. A failure of age keeps the code of
the identity that reports it, or is ERR_INTEGRITY with the reason of its
phase, as classify of Go.
openCapsule opens a capsule in memory and openCapsuleSource one that a
ByteSource reads: the prefix of the inspection and the nonce of
PAYLOAD_AGE before the release, then pieces of 1 MiB. lib/src/sink.dart
has ByteSink, for the content of formats 1 and 2 and for each file, and
FileSink, for the files of format 3, as the dst and the Sink of Go, with
MemoryByteSink and MemoryFileSink. Nothing is presented as valid before
step 17 ends: the output is closed only then and aborted after any
failure, and the sink aborted after any failure that follows its begin
(spec §56).
The signature and the seal are stage 5: lib/src/verdicts.dart has the
verdicts and the SecurityEvaluator, given what newSecurityContext and
EvaluateSecurityIn of Go take, which never fails the opening; the default
evaluates nothing. OpenOptions.accept is Accept of Go. And
AgePayloadDecryptor.wipe clears the key of a STREAM left unread.
The tests run open_cases.json and the mutation corpus with the texts and
the checks of Go, in memory and from a source read in pieces; capsules of
several MiB made from the fixtures, for the streaming; a capsule with a
stanza for a key of words; and the caller, the sinks and the evaluator.
open_test.dart runs on Node.js too, with open_vectors.g.dart.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/src/inspect.dart ports Inspect of package capsule of datekeys-go at
c531e93: the steps 1 to 8 of spec §63, without network and without
secrets, with the check of each step as Go records it, its name and its
detail, and Inspection with the fields of the steps that passed. The
opening runs them with a hook right after step 2, as the afterPrelude of
Go. inspectedLength, from prefix.ts of datekeys-ts, names the first bytes
that give the inspection of a whole file, so that a large capsule is read
up to one byte after the largest age header of PAYLOAD_AGE, and
maxAccessKeyRead the most bytes of a .dkk that its decoder needs. And
inspectView and inspectJson, the exact output of datekeys inspect -json
of internal/inspectview, with the public note.
lib/src/source.dart has ByteSource, the bytes of a capsule read by ranges,
which the application adapts from a file or a Blob, and BytesSource, over
bytes in memory; inspectCapsuleSource reads only the prefix.
The tests compare, byte for byte, the 24 fixtures/*.inspect.json and the
views of open_inspect.json, and each of the 5110 mutations of
inspect_differential.json with its code, its step and the text of Go,
also from a source read in pieces; and the prefix at the limits of age.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/src/note.dart ports CheckNote, NewNote and Note of package extension
of datekeys-go at c531e93: checkNote and checkNoteData check the length,
the UTF-8 and the rules of text of the declared author, in that order and
with the texts of Go, on the bytes of the note as Go reads its string;
newNote, publicNote and unusableNote, and Header.publicNote and
Header.unusableNote. StandardExtensions checks the data of a note as the
Standard of Go does, and its parameter validateNote, which could replace
those rules, is gone.
lib/src/head.dart ports DecodeHead, EncodeHead and CheckHeadEnd of
format3.go: the limit of HEAD_LEN, the type tag and the version, the CDDL
with R1 and R8 on the UTF-8 bytes of the paths, never on the UTF-16 code
units of a String, and then the comment, the declared author and the files
with the rules of pathrule and their layout, by subtraction, and R7 and R9,
as ERR_HEAD_INVALID with the text of Go, and the critical extensions of the
head. decodeWrittenHead is the decoder without the critical extensions, for
the self-check of the writer of stage 6.
The tests read open_heads.json, open_notes.json, head_schema.json with the
detail of each ERR_HEAD_INVALID, the trees of paths.json as heads of files
of 0 bytes, and the head of each fixture of format 3.
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>
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>
lib/datekeys.dart exports the formats, as index.ts of datekeys-ts: the
frames, PUBLIC_HEADER, CONTROL_CBOR, the .dkk, the extensions and their
registries, the Provider Profile, the DateKey with its rounds and times,
and the padding; the frame of BODY, the digest and the helpers of the
schemas stay internal for stage 4c. The README describes the modules, the
enums and the errors without a code, the Standard registry and the checks
it is given, the one difference of the formats between Go at c531e93 and
the tag spec-v0.11, and the generator of the vectors; the changelog the
stage, its tests and the faults injected. cbor_vectors_test.dart drops the
test it kept skipped until the decoders of the schemas, which
formats_vectors_test.dart now runs.
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>
lib/src/header.dart, control.dart and accesskey.dart port DecodeHeader,
EncodeHeader, DecodeControl and EncodeControl of package capsule and
package accesskey of datekeys-go at c531e93, in the layers of spec §69.1
and with the texts of Go: the limit of the frame, the type tag and the
schema version, the CBOR profile with the re-encoding and the CDDL, keys 6
and 7 of CONTROL_CBOR versions 2 and 3, and only then the DateKey of the
header and access_type and access_material of the .dkk. The .dkk is
written with the rule of spec §72 for the extensions of the specification
and read back before it is returned, as MarshalBody. I_PAYLOAD and
access_material are copied once and wiped on every path; their objects
print without them. The access policy is the enum AccessPolicy.
The tests read every fixture of testdata/: the PRELUDE, the sections and
header_binding of the 24 capsules, their header and control decoded and
written back, the round time of their DateKey, P, and in format 3 the frame
of BODY, the area, the head and the files; the six .dkk with their
capsule_digest. And the shared vectors dk1.json, quicknet_rounds.json,
profile_quicknet.json, padding.json and the 172 schemas of cbor.json,
which stage 1 left aside, each decoded by its schema and written back.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/src/profile.dart ports package profile of datekeys-go at c531e93: the
Deterministic CBOR of a Provider Profile and its profile_hash, Decode and
Validate with rules 1 to 3 of spec §12.1 in their order and the texts of
Go (a period printed as Go prints a time.Duration), the drand schemes that
tlock supports and the group of their key, checked with
checkCompressedPoint, the chain hash of drand's chain.Info, MaxRound, the
pinned Quicknet profile and the registry with Default. Profile implements
PinnedProfile, which the verification of releases of stage 3 reads.
lib/src/datekey.dart ports package datekey: dk1_ strings, parsed with the
four Base64 decoders of Go and a JSON reader with the acceptance of
encoding/json with UseNumber, and numbers read by their exact decimal
value, with the texts of Go and its %v of the values; Resolve, RoundTime,
Validate and UnlockAt; and Instant, seconds and nanoseconds, with the RFC
3339 of Go's time.Parse(time.RFC3339Nano) and of Format, as datekey.ts of
datekeys-ts. A round is an int up to 2^53-1, exact on the web.
The tests, on the VM and compiled to JavaScript, check properties on
values of a fixed seed: dk1_ strings that read back, instants that format
and parse back to the nanosecond, and rounds whose time is the first at or
after the instant, at the end of the range of several profiles.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/src/extension.dart ports package extension of datekeys-go at c531e93:
the structural rules of an array (1 to 64 entries in the order of the
UTF-8 bytes of extension_id, never of the UTF-16 code units of a String;
an extension_id of 1 to 256 bytes; data absent or non-empty) checked while
it is decoded and before it is written; Canonical, CheckDisjoint; the
registries with the optional data check and places of Go (an abstract
ExtensionRegistry whose defaults are those of a Go registry that is not a
DataValidator nor a Placement), ExtensionSet and KnownIn; CheckCritical
and CheckNoncritical, with and without the object; and CheckWrite with the
Standard registry of the extensions of spec §72, whose checks of the data
of a note and of a locator are given to it, since the rules of a note need
the tables of the rules of paths of stage 4a.
lib/src/schema.dart holds the helpers of the decoders of the objects, as
schema.ts of datekeys-ts: the key of a failing read, the required keys and
the extension arrays at their keys.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/src/framing.dart ports ParsePrelude, Prelude.Bytes, PayloadOffset and
HeaderBinding of package capsule and the frame of Decode of package
accesskey of datekeys-go at c531e93, with their checks in the order of
spec §23 and §40 and their texts, and splitCapsule and FramingException,
the steps 1 to 3 of capsule.Inspect, as framing.ts of datekeys-ts. The
format of a capsule is the enum CapsuleFormat.
lib/src/padding.dart is padding.go: PaddedLength and PayloadAgeLength for
the codes of PaddingRule, exact up to L_MAX on the web too, where an int is
a double: bitlen doubles a power of two and the roundings divide and
multiply by powers of two, with no shift or mask of more than 31 bits. And
PaddingCheck, the checkPadding of capsule.Open at step 17, fed the
plaintext piece by piece.
lib/src/body.dart is the frame of BODY of format3.go (ParseBodyFrame,
CheckArea, ContentLength), and lib/src/digest.dart the incremental SHA-256
of a capsule_digest, with the comparison of checkCapsuleDigest. The errors
that Go returns without a normative code are ArgumentErrors with its text.
The tests run on the VM and compiled to JavaScript: the order of the
checks on capsules built in memory, P against a statement of spec §29.1 in
BigInt, next to 2^53 and at the boundaries of 32 bits, and the digest
against package:crypto however the file is cut.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The faults injected at the end of the stage were all caught on the VM, but
three of them only there: the point at infinity taken for a signature, the
code of a failing source kept at step 9, and the length of the stanza body
left unchecked. Three tests that read no file now catch them compiled to
JavaScript as well, the stanza being the one of the encryption of Go.
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>
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>
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>
lib/src/der.dart is the port of internal/der/der.go at 601e6d2, the
draft of v0.12, whose DER already differs from spec-v0.11: check, split,
content, setOfSorted and parseTime, with the texts of the reference. It
is internal, as in Go, and keeps the names of the Go package for an
import with a prefix.
parseTime reads UTCTime and GeneralizedTime in their forms of X.690
and refuses a date or a time that does not exist. It returns a DerTime,
exact to the nanosecond as Go's time.Time and unlike Dart's DateTime:
its fields and its seconds since the epoch, below 2^53.
The tests port der_test.go, with the texts that Go prints. The fuzz
target is a property over seeded mutations of its seeds and of the
signatures and tokens of security_cms.json.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/src/cbor.dart is the port of codec/codec.go: CborEncoder,
CborDecoder, unmarshalCbor, peekSchema, checkSchema and walkCbor, with
the same reads, the same checks in the same order and the same error
texts, such as "codec: offset 0: 23 is not in its shortest form
(initial byte 0x18): ERR_NON_CANONICAL_CBOR".
Integers are exact on the VM and on the web, where an int is a double
and the bit operators work on 32 bits. An argument of eight bytes is
read as two halves of 32 bits, and is an int up to 2^53-1 and a BigInt
above, map keys and the numbers of the error texts included. uint
returns an int, since every schema bounds its integers at 2^53-1, and
uint64 a BigInt. The map that peekSchema reads is bounded at 2^63-1,
Go's math.MaxInt, on the web too.
Two kinds of text are of Dart only. CborEncoder.uint refuses an int
outside 0..2^53-1 and uint64 a BigInt outside 0..2^64-1, with the text
of datekeys-ts, where Go's uint64 cannot hold such a value. And the only
invalid text that a Dart String holds is a lone surrogate: the error
quotes it as Go quotes its bytes in generalized UTF-8.
The tests port codec_test.go, internal_test.go and vectors_test.go,
with the texts that Go prints, and cbor.test.ts. The fuzz targets are
properties over seeded inputs, checked against a reference encoder and
decoder written apart, as internal/cbortest. cbor.json runs its 36
accept and 67 reject vectors with the walk limits and the values; its
172 schema vectors are read and wait for the schema decoders of stage 4.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- lib/src/errors.dart, the port of errors.go: ErrorCode, the 19 codes in
the order of section 69, and DateKeysException, which carries one of
them with the message of the reference, the context and then the code.
wrap and withContext are fmt.Errorf("prefix: %w"), errorCode is
datekeys.Code. test/errors_spec_test.dart reads section 69 from
../datekeys-go at the tag spec-v0.11 and compares its ERR_ lines with
the catalogue; it is skipped when that repository is missing.
- lib/src/bytes.dart, as bytes.ts of datekeys-ts: hexadecimal,
comparison and concatenation; strict UTF-8 that keeps a leading
U+FEFF, which the Utf8Decoder of dart:convert drops on the VM and on
the web; Go's utf8.DecodeRune; and Go's %q, with the table of
strconv.IsPrint of Go 1.26 copied from datekeys-ts and the SHA-256 of
the whole rune set pinned. A lone surrogate, which a Dart String may
hold, is written in generalized UTF-8, which is not UTF-8.
- lib/datekeys.dart exports the errors and the byte functions that a
user needs.
- The tests that read files are marked @TestOn('vm'), those of stage 0
included, so that the others also run compiled to JavaScript with
dart test -p node.
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>