You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DateKeys-App/scripts/capsule-go-verdicts.go

594 lines
21 KiB

//go:build ignore
// Prints src/lib/dkc/testing/capsule-vectors.json: the verdicts of the Go
// reference on what scripts/capsule-ts-samples.mjs wrote with the writer of
// this repository (plan of phase 3, decision 11 and section 8, point 9):
//
// - samples: each .dkc, of format 2 or 3, is inspected with capsule.Inspect
// and opened with capsule.Open and the published signature of its round,
// with each credential alone and with all of them, and the verdict, the
// format, L, the padding rule and P are recorded; in format 2 the SHA-256
// of the content, and in format 3 the files that a Sink receives, with
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
// their SHA-256, the head encoded again with capsule.EncodeHead, the
// verdicts of the security area and the size of the area. Its
// PUBLIC_HEADER, its CONTROL_CBOR, opened layer by layer with the
// identities of agewrap, and its .dkk are encoded again by the reference
// and compared with the bytes written, the public note that
// Header.PublicNote reads in its PUBLIC_HEADER is recorded, null without
// one, and so is the number of stanzas of its INNER_ACCESS_AGE.
// - mixes: the code and the step at which capsule.Open fails.
// - encoders: capsule.EncodeHeader, capsule.EncodeControl (format 2) and
// AccessKey.MarshalBody on every input, compared with the bytes of the
// TypeScript library.
// - recipients: age.ParseX25519Recipient, then agewrap.CheckX25519Recipient,
// on every string.
// - errors: the text of capsule.Encrypt for each invalid option, as a
// generator of test vectors, the only writer of format 2 (spec §62.1
// rule 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
// - note_errors: the text of capsule.EncryptFiles for each public note that
// breaks the rules of spec §24.1.
//
// Run it from a scratch module that requires the reference implementation
// (replace g.activething.com/go/DateKeys => ../datekeys-go, GOFLAGS=-mod=mod
// and the go directive of the reference, so that its toolchain is used),
// passing the output of capsule-ts-samples.mjs:
//
// go run capsule-go-verdicts.go ts-samples.json > capsule-vectors.json
package main
import (
"bytes"
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"maps"
"os"
"runtime/debug"
"slices"
"strings"
"time"
"filippo.io/age"
datekeys "g.activething.com/go/DateKeys"
"g.activething.com/go/DateKeys/accesskey"
"g.activething.com/go/DateKeys/agewrap"
"g.activething.com/go/DateKeys/capsule"
"g.activething.com/go/DateKeys/codec/bech32"
"g.activething.com/go/DateKeys/datekey"
"g.activething.com/go/DateKeys/extension"
"g.activething.com/go/DateKeys/profile"
"g.activething.com/go/DateKeys/provider"
)
// The published Quicknet signatures of the rounds of the samples, as in the
// fixtures; provider.Verify checks them in capsule.Open.
var published = map[uint64]string{
1000: "b44679b9a59af2ec876b1a6b1ad52ea9b1615fc3982b19576350f93447cb1125e342b73a8dd2bacbe47e4b6b63ed5e39",
1001: "b33bf3667cbd5a82de3a24b4e0e9fe5513cc1a0e840368c6e31f5fcfa79bea03f73896b25883abf2853d10337fb8fa41",
2000: "b6cb8f482a0b15d45936a4c4ea08e98a087e71787caee3f4d07a8a9843b1bc5423c6b3c22f446488b3137eaca799c77e",
}
type extJSON struct {
ID string `json:"id"`
Version uint64 `json:"version"`
Data *string `json:"data,omitempty"`
}
type sampleIn struct {
Name string `json:"name"`
Round uint64 `json:"round"`
Policy string `json:"policy"`
Format int `json:"format"`
Length uint64 `json:"length"`
Padding int `json:"padding"`
PaddedLength uint64 `json:"padded_length"`
// Format 2: the SHA-256 of the content. Format 3: the head written and
// its files.
ContentSHA256 string `json:"content_sha256,omitempty"`
HeadCBOR string `json:"head_cbor,omitempty"`
Files []fileJSON `json:"files,omitempty"`
Identities []string `json:"identities"`
DKK string `json:"dkk,omitempty"`
Known []extJSON `json:"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
// PublicNote is the public note that the writer was given, if any.
PublicNote *string `json:"public_note,omitempty"`
DKC string `json:"dkc"`
}
// A file of a format 3 capsule: its path, size, SHA-256 and mtime.
type fileJSON struct {
Path string `json:"path"`
Size uint64 `json:"size"`
SHA256 string `json:"sha256"`
MTime *uint64 `json:"mtime,omitempty"`
}
type encoderIn struct {
Header struct {
CapsuleID string `json:"capsule_id"`
Round uint64 `json:"round"`
Policy int `json:"policy"`
Critical []extJSON `json:"critical"`
Noncritical []extJSON `json:"noncritical"`
} `json:"header"`
Control struct {
HeaderBinding string `json:"header_binding"`
PayloadIdentity string `json:"payload_identity"`
PayloadLength uint64 `json:"payload_length"`
Padding int `json:"padding"`
Critical []extJSON `json:"critical"`
Noncritical []extJSON `json:"noncritical"`
} `json:"control"`
DKK struct {
CredentialID string `json:"credential_id"`
CapsuleID string `json:"capsule_id"`
Material string `json:"material"`
CapsuleDigest *string `json:"capsule_digest,omitempty"`
Critical []extJSON `json:"critical"`
Noncritical []extJSON `json:"noncritical"`
} `json:"dkk"`
HeaderCBOR string `json:"header_cbor"`
ControlCBOR string `json:"control_cbor"`
DKKBody string `json:"dkk_body"`
}
type errorCase struct {
Name string `json:"name"`
Policy int `json:"policy"`
Recipients []string `json:"recipients,omitempty"`
Portable bool `json:"portable,omitempty"`
UnlockAt string `json:"unlock_at"`
Now string `json:"now"`
Length int64 `json:"length"`
Padding int `json:"padding,omitempty"`
Critical []extJSON `json:"critical,omitempty"`
Noncritical []extJSON `json:"noncritical,omitempty"`
ControlCritical []extJSON `json:"control_critical,omitempty"`
ControlNoncritical []extJSON `json:"control_noncritical,omitempty"`
ChainHashFlip bool `json:"chain_hash_flip,omitempty"`
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
PublicNote string `json:"public_note,omitempty"`
TS string `json:"ts"`
Go string `json:"go"`
}
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
// noteError is a public note that breaks the rules of spec §24.1, and the
// texts of capsule.EncryptFiles and of the TypeScript library for it.
type noteError struct {
Name string `json:"name"`
Note string `json:"note"`
TS string `json:"ts"`
Go string `json:"go"`
}
type input struct {
Generator string `json:"generator"`
Samples []sampleIn `json:"samples"`
Mixes []struct {
Name string `json:"name"`
Round uint64 `json:"round"`
DKC string `json:"dkc"`
} `json:"mixes"`
Encoders struct {
Seed int `json:"seed"`
Count int `json:"count"`
SHA256 string `json:"sha256"`
Cases []encoderIn `json:"cases"`
} `json:"encoders"`
Recipients []string `json:"recipients"`
Errors []errorCase `json:"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
NoteErrors []noteError `json:"note_errors"`
}
// The verdict of one opening: "ok" with what was delivered, or the code and
// the step of the failure.
type openVerdict struct {
Credentials string `json:"credentials"`
Result string `json:"result"`
Step int `json:"step,omitempty"`
Opened *openedOut `json:"opened,omitempty"`
}
type openedOut struct {
ContentSHA256 string `json:"content_sha256,omitempty"`
Format int `json:"format"`
Length uint64 `json:"length"`
Padding int `json:"padding"`
PaddedLength uint64 `json:"padded_length"`
Files []fileJSON `json:"files,omitempty"`
HeadCBOR string `json:"head_cbor,omitempty"`
Verdicts []string `json:"verdicts,omitempty"`
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
AreaLen uint32 `json:"area_len,omitempty"`
}
// sink keeps the files of a format 3 capsule in memory.
type sink struct {
files []*bytes.Buffer
}
type buffer struct{ *bytes.Buffer }
func (buffer) Close() error { return nil }
func (s *sink) Begin(*capsule.Head) error { return nil }
func (s *sink) Create(int) (io.WriteCloser, error) {
b := &bytes.Buffer{}
s.files = append(s.files, b)
return buffer{b}, nil
}
func (s *sink) Commit() error { return nil }
func (s *sink) Abort() { s.files = nil }
type sampleOut struct {
sampleIn
Go struct {
Inspect string `json:"inspect"`
Opens []openVerdict `json:"opens"`
InnerStanzas int `json:"inner_stanzas"`
Reencoded bool `json:"reencoded"`
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
PublicNote *string `json:"public_note"`
} `json:"go"`
}
type mixOut struct {
Name string `json:"name"`
Round uint64 `json:"round"`
DKC string `json:"dkc"`
Go struct {
Code string `json:"code"`
Step int `json:"step"`
} `json:"go"`
}
type recipientOut struct {
String string `json:"string"`
Parse string `json:"parse"`
Check string `json:"check,omitempty"`
}
type output struct {
Description string `json:"description"`
Generator string `json:"generator"`
SamplesGenerator string `json:"samples_generator"`
Libraries string `json:"libraries"`
Releases []releaseOut `json:"releases"`
Samples []sampleOut `json:"samples"`
Mixes []mixOut `json:"mixes"`
Encoders encodersOut `json:"encoders"`
Recipients []recipientOut `json:"recipients"`
Errors []errorCase `json:"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
NoteErrors []noteError `json:"note_errors"`
}
type releaseOut struct {
Round uint64 `json:"round"`
Signature string `json:"signature"`
}
type encodersOut struct {
Seed int `json:"seed"`
Count int `json:"count"`
SHA256 string `json:"sha256"`
Equal int `json:"equal"`
Differences []string `json:"differences"`
}
func must[T any](v T, err error) T {
if err != nil {
panic(err)
}
return v
}
func unhex(s string) []byte { return must(hex.DecodeString(s)) }
func exts(list []extJSON) []extension.Extension {
var out []extension.Extension
for _, e := range list {
x := extension.Extension{ID: e.ID, Version: e.Version}
if e.Data != nil {
x.Data = unhex(*e.Data)
if x.Data == nil {
x.Data = []byte{}
}
}
out = append(out, x)
}
return out
}
func source(round uint64) provider.ReleaseSource {
return provider.ReleaseSourceFunc(func(_ context.Context, _ *profile.Profile, c provider.Condition) (provider.Release, error) {
return provider.Release{Round: c.Round, Signature: unhex(published[c.Round])}, nil
})
}
func opened(dkc []byte, round uint64, reg profile.Registry, ex extension.Registry, ids []age.Identity, dkk []byte) openVerdict {
var out bytes.Buffer
files := &sink{}
o := capsule.OpenOptions{Registry: reg, Extensions: ex, Source: source(round), Identities: ids, Sink: files, Now: func() time.Time {
return time.Unix(1692803367+int64(round-1)*3, 0)
}}
if dkk != nil {
o.AccessKeyFile = bytes.NewReader(dkk)
}
res, err := capsule.Open(context.Background(), &out, bytes.NewReader(dkc), o)
v := openVerdict{Result: "ok"}
if err != nil {
v.Result = datekeys.Code(err)
if v.Result == "" {
v.Result = "error: " + err.Error()
}
if res != nil && res.Inspection != nil && len(res.Inspection.Checks) > 0 {
v.Step = res.Inspection.Checks[len(res.Inspection.Checks)-1].Step
}
return v
}
v.Opened = &openedOut{Format: int(res.Format), Length: res.PayloadLength, Padding: int(res.Padding), PaddedLength: res.PaddedLength}
if res.Format != capsule.Format3 {
sum := sha256.Sum256(out.Bytes())
v.Opened.ContentSHA256 = hex.EncodeToString(sum[:])
return v
}
for i, f := range res.Head.Files {
sum := sha256.Sum256(files.files[i].Bytes())
fj := fileJSON{Path: f.Path, Size: f.Size, SHA256: hex.EncodeToString(sum[:])}
if f.HasMTime {
mtime := f.MTime
fj.MTime = &mtime
}
v.Opened.Files = append(v.Opened.Files, fj)
}
v.Opened.HeadCBOR = hex.EncodeToString(must(capsule.EncodeHead(res.Head)))
v.Opened.Verdicts = []string{string(res.Verdicts.Signature), string(res.Verdicts.Seal)}
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
v.Opened.AreaLen = res.AreaLen
return v
}
func main() {
var in input
must(0, json.Unmarshal(must(os.ReadFile(os.Args[1])), &in))
reg := must(profile.Default())
p := profile.Quicknet()
out := output{
Description: "Verdicts of the Go reference on capsules, mixes, encodings, recipients and invalid options of the TypeScript writer (plan of phase 3, section 8, point 9); see the header of scripts/capsule-go-verdicts.go.",
Generator: "scripts/capsule-go-verdicts.go",
SamplesGenerator: in.Generator,
Libraries: libraries(),
}
for _, r := range slices.Sorted(maps.Keys(published)) {
out.Releases = append(out.Releases, releaseOut{r, published[r]})
}
for _, s := range in.Samples {
dkc := unhex(s.DKC)
known := extension.Set{}
for _, k := range s.Known {
known[k.ID] = append(known[k.ID], k.Version)
}
so := sampleOut{sampleIn: s}
if _, err := capsule.Inspect(bytes.NewReader(dkc), capsule.InspectOptions{Registry: reg, Extensions: known}); err != nil {
so.Go.Inspect = datekeys.Code(err)
} else {
so.Go.Inspect = "ok"
}
var ids []age.Identity
for i, raw := range s.Identities {
id := must(agewrap.X25519IdentityFromRaw(unhex(raw)))
ids = append(ids, id)
v := opened(dkc, s.Round, reg, known, []age.Identity{id}, nil)
v.Credentials = fmt.Sprintf("identity %d", i)
so.Go.Opens = append(so.Go.Opens, v)
}
var dkk []byte
if s.DKK != "" {
dkk = unhex(s.DKK)
v := opened(dkc, s.Round, reg, known, nil, dkk)
v.Credentials = ".dkk"
so.Go.Opens = append(so.Go.Opens, v)
}
v := opened(dkc, s.Round, reg, known, ids, dkk)
v.Credentials = "all"
if ids == nil && dkk == nil {
v.Credentials = "none"
}
so.Go.Opens = append(so.Go.Opens, v)
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
so.Go.InnerStanzas, so.Go.Reencoded, so.Go.PublicNote = layers(dkc, s, p, dkk)
out.Samples = append(out.Samples, so)
}
for _, m := range in.Mixes {
v := opened(unhex(m.DKC), m.Round, reg, extension.Set{}, nil, nil)
mo := mixOut{Name: m.Name, Round: m.Round, DKC: m.DKC}
mo.Go.Code, mo.Go.Step = v.Result, v.Step
out.Mixes = append(out.Mixes, mo)
}
out.Encoders = encodersOut{Seed: in.Encoders.Seed, Count: in.Encoders.Count, SHA256: in.Encoders.SHA256, Differences: []string{}}
for i, c := range in.Encoders.Cases {
if d := encoders(c); d != "" {
out.Encoders.Differences = append(out.Encoders.Differences, fmt.Sprintf("case %d: %s", i, d))
} else {
out.Encoders.Equal++
}
}
for _, s := range in.Recipients {
r := recipientOut{String: s, Parse: "ok"}
x, err := age.ParseX25519Recipient(s)
if err != nil {
r.Parse = err.Error()
} else if err := agewrap.CheckX25519Recipient(x); err != nil {
r.Check = err.Error()
} else {
r.Check = "ok"
}
out.Recipients = append(out.Recipients, r)
}
for _, c := range in.Errors {
c.Go = encryptError(c)
out.Errors = append(out.Errors, c)
}
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
for _, c := range in.NoteErrors {
c.Go = noteText(c.Note)
out.NoteErrors = append(out.NoteErrors, c)
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
must(0, enc.Encode(out))
}
// layers opens SEALED_CONTROL of a sample with the published release and, in
// time_and_key, with its first credential, and encodes PUBLIC_HEADER,
// CONTROL_CBOR and the .dkk again. It returns the number of stanzas of
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
// INNER_ACCESS_AGE, whether every encoding equals the bytes written, and the
// public note of PUBLIC_HEADER, nil when there is none that is usable.
func layers(dkc []byte, s sampleIn, p *profile.Profile, dkk []byte) (int, bool, *string) {
pre := must(capsule.ParsePrelude(dkc))
header := dkc[capsule.PreludeSize : capsule.PreludeSize+int(pre.PublicHeaderLen)]
sealed := dkc[capsule.PreludeSize+int(pre.PublicHeaderLen) : capsule.PreludeSize+int(pre.PublicHeaderLen)+int(pre.SealedControlLen)]
same := true
h := must(capsule.DecodeHeader(header))
same = same && bytes.Equal(must(capsule.EncodeHeader(h)), header)
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
var note *string
if text, ok := h.PublicNote(); ok {
note = &text
}
tid := must(agewrap.NewTimeIdentity(p, s.Round, provider.Release{Round: s.Round, Signature: unhex(published[s.Round])}))
inner := must(io.ReadAll(must(age.Decrypt(bytes.NewReader(sealed), tid))))
control := inner
stanzas := 0
if s.Policy == "time_and_key" {
st := must(agewrap.Stanzas(bytes.NewReader(inner)))
stanzas = len(st)
var id age.Identity
if len(s.Identities) > 0 {
id = must(agewrap.X25519IdentityFromRaw(unhex(s.Identities[0])))
} else {
k := must(accesskey.Decode(bytes.NewReader(dkk)))
id = must(agewrap.X25519IdentityFromRaw(k.Material))
}
aid := must(agewrap.NewAccessIdentity(agewrap.AccessSlots, id))
control = must(io.ReadAll(must(age.Decrypt(bytes.NewReader(inner), aid))))
}
c := must(capsule.DecodeControl(control, pre.Format))
same = same && bytes.Equal(must(capsule.EncodeControl(c, pre.Format)), control)
if dkk != nil {
k := must(accesskey.Decode(bytes.NewReader(dkk)))
var b bytes.Buffer
must(0, accesskey.Encode(&b, k))
same = same && bytes.Equal(b.Bytes(), dkk)
}
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
return stanzas, same, note
}
// encoders encodes one input with the reference and names the first encoding
// that differs from the bytes of the TypeScript library, or returns "".
func encoders(c encoderIn) string {
var h capsule.Header
copy(h.CapsuleID[:], unhex(c.Header.CapsuleID))
h.DateKey = datekey.DateKey{ProfileID: "datekeys:quicknet:v1", Round: c.Header.Round}
h.Policy = capsule.Policy(c.Header.Policy)
h.Critical, h.Noncritical = exts(c.Header.Critical), exts(c.Header.Noncritical)
hb, err := capsule.EncodeHeader(&h)
if err != nil || hex.EncodeToString(hb) != c.HeaderCBOR {
return fmt.Sprintf("PUBLIC_HEADER (%v)", err)
}
var ctrl capsule.Control
copy(ctrl.HeaderBinding[:], unhex(c.Control.HeaderBinding))
copy(ctrl.PayloadIdentity[:], unhex(c.Control.PayloadIdentity))
ctrl.PayloadLength, ctrl.Padding = c.Control.PayloadLength, capsule.Padding(c.Control.Padding)
ctrl.Critical, ctrl.Noncritical = exts(c.Control.Critical), exts(c.Control.Noncritical)
cb, err := capsule.EncodeControl(&ctrl, capsule.Format2)
if err != nil || hex.EncodeToString(cb) != c.ControlCBOR {
return fmt.Sprintf("CONTROL_CBOR (%v)", err)
}
k := accesskey.AccessKey{Type: accesskey.TypeX25519, Material: unhex(c.DKK.Material)}
copy(k.CredentialID[:], unhex(c.DKK.CredentialID))
copy(k.CapsuleID[:], unhex(c.DKK.CapsuleID))
if c.DKK.CapsuleDigest != nil {
k.Verification = &accesskey.Verification{CapsuleDigest: unhex(*c.DKK.CapsuleDigest)}
}
k.Critical, k.Noncritical = exts(c.DKK.Critical), exts(c.DKK.Noncritical)
kb, err := k.MarshalBody()
if err != nil || hex.EncodeToString(kb) != c.DKKBody {
return fmt.Sprintf(".dkk BODY_CBOR (%v)", err)
}
return ""
}
// encryptError runs capsule.Encrypt with the options of a case and returns
// its error text, or "ok".
func encryptError(c errorCase) string {
p := profile.Quicknet()
if c.ChainHashFlip {
p.ChainHash[0] ^= 1
}
var recipients []age.Recipient
for _, raw := range c.Recipients {
s := must(bech32.Encode("age", unhex(raw)))
recipients = append(recipients, must(age.ParseX25519Recipient(s)))
}
opts := capsule.EncryptOptions{
Profile: p,
UnlockAt: must(time.Parse(time.RFC3339Nano, c.UnlockAt)),
Policy: capsule.Policy(c.Policy),
Recipients: recipients,
NewPortableKey: c.Portable,
Length: c.Length,
Padding: capsule.Padding(c.Padding),
Critical: exts(c.Critical),
Noncritical: exts(c.Noncritical),
ControlCritical: exts(c.ControlCritical),
ControlNoncritical: exts(c.ControlNoncritical),
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
PublicNote: c.PublicNote,
TestVectors: true,
Now: func() time.Time { return must(time.Parse(time.RFC3339Nano, c.Now)) },
}
src := bytes.NewReader(make([]byte, min(c.Length, 1)))
if _, err := capsule.Encrypt(io.Discard, src, opts); err != nil {
return err.Error()
}
return "ok"
}
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
// noteText runs capsule.EncryptFiles on a file of one byte, for round 1000
// with now at the genesis, with the public note given, and returns its error
// text, or "ok".
func noteText(note string) string {
genesis := time.Unix(1692803367, 0).UTC()
opts := capsule.EncryptOptions{
Profile: profile.Quicknet(),
UnlockAt: genesis.Add(999 * 3 * time.Second),
Policy: capsule.TimeOnly,
PublicNote: note,
Now: func() time.Time { return genesis },
}
src := []capsule.Source{{Path: "a.txt", Size: 1, Open: func() (io.ReadCloser, error) { return io.NopCloser(strings.NewReader("x")), nil }}}
if _, err := capsule.EncryptFiles(io.Discard, src, opts); err != nil {
return err.Error()
}
return "ok"
}
func libraries() string {
info, ok := debug.ReadBuildInfo()
if !ok {
return ""
}
var parts []string
for _, d := range info.Deps {
switch d.Path {
case "filippo.io/age", "github.com/drand/drand/v2", "github.com/drand/kyber", "github.com/drand/kyber-bls12381", "github.com/drand/tlock":
parts = append(parts, d.Path+" "+d.Version)
}
}
return strings.Join(parts, ", ")
}

Powered by TurnKey Linux.