Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
#!/usr/bin/env node
// Writes, as JSON, what scripts/capsule-go-verdicts.go checks with the Go
// reference (plan of phase 3, decision 11 and section 8, point 9):
//
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
// - samples: .dkc of format 2 written by encryptVectors of
// src/lib/dkc/testing/encrypt.ts, as a generator of test vectors, the only
// writer of format 2, and of format 3 written by encryptFiles as any
// caller writes them, with the area of 32 KiB and, in two of them, a
// public note; for rounds 1000, 1001 and 2000, with now at the genesis and
// fixed identities, each with the credentials that open it and the
// SHA-256 of its content, generated from its length, or in format 3 the
// head written and the SHA-256 of each file;
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
// - mixes: capsules spliced from two capsules of one round;
// - encoders: every input of the encoder differential, drawn from a seed
// (src/lib/dkc/testing/interop.ts), with its encodings by this library;
// - recipients: strings for age.ParseX25519Recipient and
// agewrap.CheckX25519Recipient;
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
// - errors: the invalid options of encrypt as a generator of test vectors
// that Go also rejects, with the text of this library;
// - note_errors: the public notes that encryptFiles refuses, with the text
// of this library.
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
//
// The capsules are random (age draws its file keys and shares), so the output
// is generated once and frozen with the verdicts of Go in
// src/lib/dkc/testing/capsule-vectors.json. Node runs the TypeScript sources
// directly (type stripping, Node 22.6+):
//
// node scripts/capsule-ts-samples.mjs > ts-samples.json
import { encodeAccessKey , marshalAccessKeyBody } from '../src/lib/dkc/accesskey.ts' ;
import { concatBytes , sha256 , toHex } from '../src/lib/dkc/bytes.ts' ;
import { encodeControl } from '../src/lib/dkc/control.ts' ;
import { parseRFC3339 } from '../src/lib/dkc/datekey.ts' ;
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
import { encryptFiles } from '../src/lib/dkc/encrypt.ts' ;
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
import { FORMAT _2 } from '../src/lib/dkc/framing.ts' ;
Format 3, step 4: Go opens what encryptFiles writes
capsule-vectors.json is written again with six capsules of format 3
from encryptFiles, next to the thirteen of format 2:
- one file with its mtime; a tree of seven files, one of them over two
STREAM chunks, with paths out of ASCII and the pair U+FFFD and
U+10000, which UTF-8 and UTF-16 order the other way round, a comment
and a declared author; a comment and no file; bloque256; time_and_key
with three recipients and a portable key; and head extensions.
- capsule-go-verdicts.go opens them with capsule.Open into a Sink, with
each credential alone and with all of them, and records the files it
receives with their SHA-256, the head encoded again with
capsule.EncodeHead and the verdicts of the security area. It decodes
the control of each capsule in the format of its prelude, and runs
capsule.Encrypt on the invalid options as a generator of test vectors.
- interop.test.ts requires Go to find the files, the head and the
verdicts written, and open, into a MemorySink, to reach the same
verdicts on the same bytes.
The format 2 samples, the mixes, the encoder differential (500 equal),
the recipients and the 21 option errors are regenerated too, with the
same verdicts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
import { encodeHead } from '../src/lib/dkc/head.ts' ;
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
import { encodeHeader , TIME _AND _KEY , TIME _ONLY } from '../src/lib/dkc/header.ts' ;
import { quicknet } from '../src/lib/dkc/profile.ts' ;
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
import { encryptVectors } from '../src/lib/dkc/testing/encrypt.ts' ;
import {
encoderCaseJSON ,
encoderCases ,
errorCaseInput ,
errorCases ,
noteErrorCases ,
noteErrorInput ,
recipientStrings ,
sampleIdentity ,
} from '../src/lib/dkc/testing/interop.ts' ;
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
import { x25519PublicKey } from '../src/lib/dkc/x25519.ts' ;
const GENESIS = parseRFC3339 ( '2023-08-23T15:09:27Z' ) ;
const roundAt = ( r ) => ( { seconds : GENESIS . seconds + ( r - 1 ) * 3 , nanos : 0 } ) ;
const ENCODER _SEED = 20260929 ;
const ENCODER _COUNT = 500 ;
// A deterministic content of n bytes, as in the tests of the writer.
function content ( n , seed = 1 ) {
const b = new Uint8Array ( n ) ;
let x = seed ;
for ( let i = 0 ; i < n ; i ++ ) {
x = ( x * 1103515245 + 12345 ) >>> 0 ;
b [ i ] = x >>> 24 ;
}
return b ;
}
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
const base = ( extra ) => ( { profile : quicknet ( ) , now : ( ) => GENESIS , policy : TIME _ONLY , unlockAt : roundAt ( 1000 ) , ... extra } ) ;
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
// Format 2, which only a generator of test vectors writes (spec §62.1 rule 1).
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
async function sample ( name , body , opts , identities = [ ] , dkkExtensions = [ ] , known = [ ] ) {
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
const res = await encryptVectors ( body , opts ) ;
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
let dkk ;
if ( res . portableKey !== undefined ) dkk = encodeAccessKey ( { ... res . portableKey , noncritical : dkkExtensions } ) ;
return {
name ,
round : res . dateKey . round ,
policy : opts . policy === TIME _AND _KEY ? 'time_and_key' : 'time_only' ,
Format 3, step 4: Go opens what encryptFiles writes
capsule-vectors.json is written again with six capsules of format 3
from encryptFiles, next to the thirteen of format 2:
- one file with its mtime; a tree of seven files, one of them over two
STREAM chunks, with paths out of ASCII and the pair U+FFFD and
U+10000, which UTF-8 and UTF-16 order the other way round, a comment
and a declared author; a comment and no file; bloque256; time_and_key
with three recipients and a portable key; and head extensions.
- capsule-go-verdicts.go opens them with capsule.Open into a Sink, with
each credential alone and with all of them, and records the files it
receives with their SHA-256, the head encoded again with
capsule.EncodeHead and the verdicts of the security area. It decodes
the control of each capsule in the format of its prelude, and runs
capsule.Encrypt on the invalid options as a generator of test vectors.
- interop.test.ts requires Go to find the files, the head and the
verdicts written, and open, into a MemorySink, to reach the same
verdicts on the same bytes.
The format 2 samples, the mixes, the encoder differential (500 equal),
the recipients and the 21 option errors are regenerated too, with the
same verdicts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
format : res . format ,
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
length : res . length ,
padding : res . padding ,
padded _length : res . paddedLength ,
content _sha256 : toHex ( await sha256 ( body ) ) ,
identities : identities . map ( toHex ) ,
... ( dkk === undefined ? { } : { dkk : toHex ( dkk ) } ) ,
known ,
dkc : toHex ( res . dkc ) ,
} ;
}
const samples = [ ] ;
for ( const n of [ 0 , 46 , 65536 , 78000 ] ) {
for ( const padding of [ 1 , 2 ] ) {
samples . push ( await sample ( ` time_only, ${ n } bytes, padding ${ padding } ` , content ( n , n + padding ) , base ( { padding } ) ) ) ;
}
}
const ids = ( from , n ) => Array . from ( { length : n } , ( _ , i ) => sampleIdentity ( from + i ) ) ;
const three = ids ( 10 , 3 ) ;
const sixteen = ids ( 20 , 16 ) ;
samples . push ( await sample ( 'time_and_key, a portable key' , content ( 41 ) , base ( { policy : TIME _AND _KEY , unlockAt : roundAt ( 1001 ) , newPortableKey : true } ) ) ) ;
samples . push (
await sample (
'time_and_key, three recipients and a portable key' ,
content ( 41 ) ,
base ( { policy : TIME _AND _KEY , unlockAt : roundAt ( 1001 ) , recipients : three . map ( x25519PublicKey ) , newPortableKey : true } ) ,
three ,
) ,
) ;
samples . push (
await sample ( 'time_and_key, sixteen recipients' , content ( 41 ) , base ( { policy : TIME _AND _KEY , unlockAt : roundAt ( 1001 ) , recipients : sixteen . map ( x25519PublicKey ) } ) , sixteen ) ,
) ;
const ext = ( id , version , data ) => ( { id , version , data : data === undefined ? undefined : new TextEncoder ( ) . encode ( data ) } ) ;
samples . push (
await sample (
'extensions in PUBLIC_HEADER, CONTROL_CBOR and the .dkk' ,
content ( 1000 ) ,
base ( {
policy : TIME _AND _KEY ,
unlockAt : roundAt ( 2000 ) ,
newPortableKey : true ,
critical : [ ext ( 'org.example.header-critical' , 1 ) ] ,
noncritical : [ ext ( 'org.example.header' , 7 , 'public data' ) , ext ( '。' , 2 ) , ext ( '𐀀' , 3 , 'x' ) ] ,
controlCritical : [ ext ( 'org.example.control-critical' , 4294967295 , 'sealed' ) ] ,
controlNoncritical : [ ext ( 'org.example.control' , 1 , 'sealed data' ) ] ,
} ) ,
[ ] ,
[ ext ( 'org.example.dkk' , 2 , 'dkk data' ) ] ,
[
{ id : 'org.example.header-critical' , version : 1 } ,
{ id : 'org.example.control-critical' , version : 4294967295 } ,
] ,
) ,
) ;
samples . push ( await sample ( 'an instant one nanosecond after round 1000' , content ( 10 ) , base ( { unlockAt : { seconds : roundAt ( 1000 ) . seconds , nanos : 1 } } ) ) ) ;
Format 3, step 4: Go opens what encryptFiles writes
capsule-vectors.json is written again with six capsules of format 3
from encryptFiles, next to the thirteen of format 2:
- one file with its mtime; a tree of seven files, one of them over two
STREAM chunks, with paths out of ASCII and the pair U+FFFD and
U+10000, which UTF-8 and UTF-16 order the other way round, a comment
and a declared author; a comment and no file; bloque256; time_and_key
with three recipients and a portable key; and head extensions.
- capsule-go-verdicts.go opens them with capsule.Open into a Sink, with
each credential alone and with all of them, and records the files it
receives with their SHA-256, the head encoded again with
capsule.EncodeHead and the verdicts of the security area. It decodes
the control of each capsule in the format of its prelude, and runs
capsule.Encrypt on the invalid options as a generator of test vectors.
- interop.test.ts requires Go to find the files, the head and the
verdicts written, and open, into a MemorySink, to reach the same
verdicts on the same bytes.
The format 2 samples, the mixes, the encoder differential (500 equal),
the recipients and the 21 option errors are regenerated too, with the
same verdicts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
// Format 3, written by encryptFiles: the files given as paths, contents and
// mtimes in milliseconds.
async function filesSample ( name , files , opts , identities = [ ] , known = [ ] ) {
const sources = files . map ( ( [ path , bytes , mtime ] ) => ( { path , size : bytes . length , ... ( mtime === undefined ? { } : { mtime } ) , open : ( ) => new Blob ( [ bytes ] ) . stream ( ) } ) ) ;
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
const res = await encryptFiles ( sources , opts ) ;
Format 3, step 4: Go opens what encryptFiles writes
capsule-vectors.json is written again with six capsules of format 3
from encryptFiles, next to the thirteen of format 2:
- one file with its mtime; a tree of seven files, one of them over two
STREAM chunks, with paths out of ASCII and the pair U+FFFD and
U+10000, which UTF-8 and UTF-16 order the other way round, a comment
and a declared author; a comment and no file; bloque256; time_and_key
with three recipients and a portable key; and head extensions.
- capsule-go-verdicts.go opens them with capsule.Open into a Sink, with
each credential alone and with all of them, and records the files it
receives with their SHA-256, the head encoded again with
capsule.EncodeHead and the verdicts of the security area. It decodes
the control of each capsule in the format of its prelude, and runs
capsule.Encrypt on the invalid options as a generator of test vectors.
- interop.test.ts requires Go to find the files, the head and the
verdicts written, and open, into a MemorySink, to reach the same
verdicts on the same bytes.
The format 2 samples, the mixes, the encoder differential (500 equal),
the recipients and the 21 option errors are regenerated too, with the
same verdicts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
return {
name ,
round : res . dateKey . round ,
policy : opts . policy === TIME _AND _KEY ? 'time_and_key' : 'time_only' ,
format : res . format ,
length : res . length ,
padding : res . padding ,
padded _length : res . paddedLength ,
head _cbor : toHex ( encodeHead ( res . head ) ) ,
files : res . head . files . map ( ( f ) => ( { path : f . path , size : f . size , sha256 : toHex ( f . sha256 ) , ... ( f . mtime === undefined ? { } : { mtime : f . mtime } ) } ) ) ,
identities : identities . map ( toHex ) ,
... ( res . portableKey === undefined ? { } : { dkk : toHex ( encodeAccessKey ( res . portableKey ) ) } ) ,
known ,
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
... ( opts . publicNote === undefined ? { } : { public _note : opts . publicNote } ) ,
Format 3, step 4: Go opens what encryptFiles writes
capsule-vectors.json is written again with six capsules of format 3
from encryptFiles, next to the thirteen of format 2:
- one file with its mtime; a tree of seven files, one of them over two
STREAM chunks, with paths out of ASCII and the pair U+FFFD and
U+10000, which UTF-8 and UTF-16 order the other way round, a comment
and a declared author; a comment and no file; bloque256; time_and_key
with three recipients and a portable key; and head extensions.
- capsule-go-verdicts.go opens them with capsule.Open into a Sink, with
each credential alone and with all of them, and records the files it
receives with their SHA-256, the head encoded again with
capsule.EncodeHead and the verdicts of the security area. It decodes
the control of each capsule in the format of its prelude, and runs
capsule.Encrypt on the invalid options as a generator of test vectors.
- interop.test.ts requires Go to find the files, the head and the
verdicts written, and open, into a MemorySink, to reach the same
verdicts on the same bytes.
The format 2 samples, the mixes, the encoder differential (500 equal),
the recipients and the 21 option errors are regenerated too, with the
same verdicts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
dkc : toHex ( res . dkc ) ,
} ;
}
samples . push ( await filesSample ( 'format 3: one file with its mtime' , [ [ 'nota.txt' , content ( 46 ) , 1_790_769_600_000 ] ] , base ( ) ) ) ;
samples . push (
await filesSample (
'format 3: a tree of files, one over two STREAM chunks, and paths out of ASCII' ,
[
[ 'fotos/2025/playa.jpg' , content ( 80_000 , 7 ) , 1_790_683_200_000 ] ,
[ 'fotos/2025/atardecer.jpg' , content ( 3000 , 8 ) ] ,
[ 'carta.txt' , new TextEncoder ( ) . encode ( 'Para abrir en familia.\n' ) , 1_790_769_600_000 ] ,
[ 'docs/vacío.txt' , new Uint8Array ( 0 ) ] ,
[ 'Ñandú/nota 🙂.txt' , content ( 10 , 9 ) ] ,
[ '\uFFFD.txt' , content ( 3 , 10 ) ] ,
[ '\u{10000}.txt' , content ( 4 , 11 ) ] ,
] ,
base ( { comment : 'Para ti,\r\ncon cariño.' , author : 'Ana López' } ) ,
) ,
) ;
samples . push ( await filesSample ( 'format 3: a comment and a declared author, and no file' , [ ] , base ( { comment : 'Solo unas líneas.\n\tCon un tabulador.' , author : 'Ana' } ) ) ) ;
samples . push ( await filesSample ( 'format 3: bloque256' , [ [ 'datos.bin' , content ( 20_000 , 12 ) ] ] , base ( { padding : 1 } ) ) ) ;
samples . push (
await filesSample (
'format 3: time_and_key, three recipients and a portable key' ,
[ [ 'carta.txt' , content ( 41 , 13 ) ] ] ,
base ( { policy : TIME _AND _KEY , unlockAt : roundAt ( 1001 ) , recipients : three . map ( x25519PublicKey ) , newPortableKey : true } ) ,
three ,
) ,
) ;
samples . push (
await filesSample (
'format 3: extensions of the head' ,
[ [ 'a.txt' , content ( 5 , 14 ) ] ] ,
base ( {
unlockAt : roundAt ( 2000 ) ,
headCritical : [ ext ( 'org.example.head-critical' , 1 ) ] ,
headNoncritical : [ ext ( 'org.example.head' , 3 , 'head data' ) ] ,
} ) ,
[ ] ,
[ { id : 'org.example.head-critical' , version : 1 } ] ,
) ,
) ;
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
// The public note of spec v0.11 §24.1, in PUBLIC_HEADER, which Go reads with
// Header.PublicNote: one out of ASCII, and one of the 1024 bytes of the most,
// beside a noncritical extension of the header, in time_and_key.
samples . push ( await filesSample ( 'format 3: a public note' , [ [ 'carta.txt' , content ( 500 , 15 ) ] ] , base ( { publicNote : 'Cartas del viaje a Lisboa · 2026, para abrir en familia' } ) ) ) ;
samples . push (
await filesSample (
'format 3: time_and_key, a portable key and a public note of 1024 bytes' ,
[ [ 'fotos/playa.jpg' , content ( 3000 , 16 ) , 1_790_683_200_000 ] ] ,
base ( { policy : TIME _AND _KEY , unlockAt : roundAt ( 2000 ) , newPortableKey : true , noncritical : [ ext ( 'org.example.header' , 1 , 'public data' ) ] , publicNote : 'ñ' . repeat ( 512 ) } ) ,
) ,
) ;
Format 3, step 4: Go opens what encryptFiles writes
capsule-vectors.json is written again with six capsules of format 3
from encryptFiles, next to the thirteen of format 2:
- one file with its mtime; a tree of seven files, one of them over two
STREAM chunks, with paths out of ASCII and the pair U+FFFD and
U+10000, which UTF-8 and UTF-16 order the other way round, a comment
and a declared author; a comment and no file; bloque256; time_and_key
with three recipients and a portable key; and head extensions.
- capsule-go-verdicts.go opens them with capsule.Open into a Sink, with
each credential alone and with all of them, and records the files it
receives with their SHA-256, the head encoded again with
capsule.EncodeHead and the verdicts of the security area. It decodes
the control of each capsule in the format of its prelude, and runs
capsule.Encrypt on the invalid options as a generator of test vectors.
- interop.test.ts requires Go to find the files, the head and the
verdicts written, and open, into a MemorySink, to reach the same
verdicts on the same bytes.
The format 2 samples, the mixes, the encoder differential (500 equal),
the recipients and the 21 option errors are regenerated too, with the
same verdicts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
// Mixes of two capsules of round 1000 (section 8, point 8).
const parts = ( dkc ) => {
const v = new DataView ( dkc . buffer , dkc . byteOffset ) ;
const hl = v . getUint32 ( 8 ) ;
const sl = v . getUint32 ( 12 ) ;
return { prelude : dkc . slice ( 0 , 16 ) , header : dkc . slice ( 16 , 16 + hl ) , sealed : dkc . slice ( 16 + hl , 16 + hl + sl ) , payload : dkc . slice ( 16 + hl + sl ) } ;
} ;
const frame = ( prelude , header , sealed , payload ) => {
const out = concatBytes ( prelude , header , sealed , payload ) ;
const v = new DataView ( out . buffer ) ;
v . setUint32 ( 8 , header . length ) ;
v . setUint32 ( 12 , sealed . length ) ;
return out ;
} ;
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
const a = parts ( ( await encryptVectors ( new TextEncoder ( ) . encode ( 'A' ) , base ( ) ) ) . dkc ) ;
const b = parts ( ( await encryptVectors ( new TextEncoder ( ) . encode ( 'B' ) , base ( ) ) ) . dkc ) ;
const k = parts ( ( await encryptVectors ( new TextEncoder ( ) . encode ( 'K' ) , base ( { policy : TIME _AND _KEY , newPortableKey : true } ) ) ) . dkc ) ;
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
const mixes = [
[ 'the header of A with the rest of B' , frame ( a . prelude , a . header , b . sealed , b . payload ) ] ,
[ 'the control of B inside A' , frame ( a . prelude , a . header , b . sealed , a . payload ) ] ,
[ 'the payload of B inside A' , frame ( a . prelude , a . header , a . sealed , b . payload ) ] ,
[ 'a time_only header over the control of a time_and_key capsule' , frame ( a . prelude , a . header , k . sealed , k . payload ) ] ,
] . map ( ( [ name , dkc ] ) => ( { name , round : 1000 , dkc : toHex ( dkc ) } ) ) ;
// The encoder differential.
const cases = encoderCases ( ENCODER _SEED , ENCODER _COUNT ) ;
const encodings = [ ] ;
const encoders = cases . map ( ( c ) => {
const header = encodeHeader ( c . header ) ;
const control = encodeControl ( c . control , FORMAT _2 ) ;
const body = marshalAccessKeyBody ( c . dkk ) ;
encodings . push ( header , control , body ) ;
return { ... encoderCaseJSON ( c ) , header _cbor : toHex ( header ) , control _cbor : toHex ( control ) , dkk _body : toHex ( body ) } ;
} ) ;
// The invalid options, with the text of this library.
const errors = [ ] ;
for ( const c of errorCases ( ) ) {
const { src , opts } = errorCaseInput ( c ) ;
let text = 'ok' ;
try {
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
await encryptVectors ( src , opts ) ;
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
} catch ( err ) {
text = err . message ;
}
errors . push ( { ... c , ts : text } ) ;
}
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
// The public notes that encryptFiles refuses, with the text of this library.
const noteErrors = [ ] ;
for ( const c of noteErrorCases ( ) ) {
const { files , opts } = noteErrorInput ( c ) ;
let text = 'ok' ;
try {
await encryptFiles ( files , opts ) ;
} catch ( err ) {
text = err . message ;
}
noteErrors . push ( { ... c , ts : text } ) ;
}
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
process . stdout . write (
` ${ JSON . stringify (
{
generator : 'scripts/capsule-ts-samples.mjs' ,
samples ,
mixes ,
encoders : { seed : ENCODER _SEED , count : ENCODER _COUNT , sha256 : toHex ( await sha256 ( concatBytes ( ... encodings ) ) ) , cases : encoders } ,
recipients : recipientStrings ( ) ,
errors ,
Go opens what the writer of v0.11 writes: capsule-vectors.json again
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>
6 days ago
note _errors : noteErrors ,
Phase 3, step 5: interoperability with Go at the level of the capsule
scripts/capsule-ts-samples.mjs writes thirteen capsules of format 2 with
encrypt (both policies and padding rules, 0 to 16 credentials, chunk
borders, extensions in the three objects, an instant with nanoseconds),
four mixes of two capsules, the inputs of an encoder differential drawn
from a seed, a corpus of recipient strings and the invalid options that
Go also rejects. scripts/capsule-go-verdicts.go gives the verdicts of the
reference on them:
- capsule.Inspect, and capsule.Open with each credential alone and all
together: every sample opens to its content, with format 2 and the L,
padding rule and P requested;
- SEALED_CONTROL opened layer by layer with the agewrap identities, 16
stanzas in INNER_ACCESS_AGE, and PUBLIC_HEADER, CONTROL_CBOR and the
.dkk encoded again to the same bytes;
- the code and step of each mix;
- EncodeHeader, EncodeControl (format 2) and MarshalBody equal on all 500
encoder inputs;
- the texts of age.ParseX25519Recipient, agewrap.CheckX25519Recipient and
capsule.Encrypt, equal to those of this library.
The capsules are random, so the output is frozen in
src/lib/dkc/testing/capsule-vectors.json, and interop.test.ts checks the
verdicts of Go and that open reaches the same ones on the frozen bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
} ,
null ,
1 ,
) } \ n ` ,
) ;