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/capsule/example_test.go

127 lines
4.2 KiB

package capsule_test
import (
"bytes"
"context"
"encoding/hex"
"errors"
"fmt"
Format 3, step 4: the writer EncryptFiles writes format 3 (spec 29.2 to 29.6, 61, 62, 62.1): the files of a list of Sources, each read twice, with the comment and the declared author. - Before anything is written: the paths and the texts are checked with the rules of the reader, in the words of a writer, naming the rule and the character, and the two paths of an R7 collision (rule 15); the comment has its CR LF and lone CR turned into LF (29.6); L is measured with a head whose salt and SHA-256 are zero, as long as the final one, and the first reading hashes each file, which must have exactly its Size. - The files go in the byte order of their paths (R8), whatever the order of the Sources; the mtime is kept only from 1970 to 9999, never clipped (rule 16); at least one file or a comment (rule 14). - The head, with a fresh salt, the control and the security area are decoded with the rules of the reader before sealing (rule 17), and the frame is checked against L. The area is 512 bytes with the empty security, whatever the options (rule 13). - The second reading writes each file into PAYLOAD_AGE and fails if its size or SHA-256 changed (rule 18). - Encrypt and EncryptFiles share the sealing; Encrypt writes format 2 only with the new TestVectors option (rule 1), and takes no head. The test data generators set it, and so does the CLI until step 5 moves it to EncryptFiles. - Result.Head is the head written. DecodeHead keeps the check of the critical extensions apart, so that the self-check decodes the head as the one of the control does. - The examples and the live test write with EncryptFiles. - The reader tests had a literal U+202E, now escaped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
"io"
"strings"
"time"
datekeys "g.activething.com/go/DateKeys"
"g.activething.com/go/DateKeys/accesskey"
"g.activething.com/go/DateKeys/capsule"
"g.activething.com/go/DateKeys/profile"
"g.activething.com/go/DateKeys/provider"
)
// The published Quicknet signature of round 1000. In real use the release
// comes from drand.New(), which verifies it the same way.
var round1000, _ = hex.DecodeString("b44679b9a59af2ec876b1a6b1ad52ea9b1615fc3982b19576350f93447cb1125e342b73a8dd2bacbe47e4b6b63ed5e39")
Format 3, step 4: the writer EncryptFiles writes format 3 (spec 29.2 to 29.6, 61, 62, 62.1): the files of a list of Sources, each read twice, with the comment and the declared author. - Before anything is written: the paths and the texts are checked with the rules of the reader, in the words of a writer, naming the rule and the character, and the two paths of an R7 collision (rule 15); the comment has its CR LF and lone CR turned into LF (29.6); L is measured with a head whose salt and SHA-256 are zero, as long as the final one, and the first reading hashes each file, which must have exactly its Size. - The files go in the byte order of their paths (R8), whatever the order of the Sources; the mtime is kept only from 1970 to 9999, never clipped (rule 16); at least one file or a comment (rule 14). - The head, with a fresh salt, the control and the security area are decoded with the rules of the reader before sealing (rule 17), and the frame is checked against L. The area is 512 bytes with the empty security, whatever the options (rule 13). - The second reading writes each file into PAYLOAD_AGE and fails if its size or SHA-256 changed (rule 18). - Encrypt and EncryptFiles share the sealing; Encrypt writes format 2 only with the new TestVectors option (rule 1), and takes no head. The test data generators set it, and so does the CLI until step 5 moves it to EncryptFiles. - Result.Head is the head written. DecodeHead keeps the check of the critical extensions apart, so that the self-check decodes the head as the one of the control does. - The examples and the live test write with EncryptFiles. - The reader tests had a literal U+202E, now escaped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
// memorySink is a capsule.Sink that keeps the files in memory. A Sink that
// writes to disk, as the datekeys CLI does, writes them to a temporary
// folder and moves it into place in Commit.
type memorySink struct{ files []*bytes.Buffer }
func (m *memorySink) Begin(h *capsule.Head) error {
m.files = make([]*bytes.Buffer, len(h.Files))
return nil
}
func (m *memorySink) Create(i int) (io.WriteCloser, error) {
m.files[i] = new(bytes.Buffer)
return bufferCloser{m.files[i]}, nil
}
func (m *memorySink) Commit() error { return nil }
func (m *memorySink) Abort() { m.files = nil }
type bufferCloser struct{ io.Writer }
func (bufferCloser) Close() error { return nil }
// source is a capsule.Source of a file held in memory.
func source(path, content string) capsule.Source {
return capsule.Source{Path: path, Size: int64(len(content)), Open: func() (io.ReadCloser, error) {
return io.NopCloser(strings.NewReader(content)), nil
}}
}
func Example() {
reg, err := profile.Default()
if err != nil {
panic(err)
}
p := profile.Quicknet()
// A clock stopped at the Quicknet genesis makes round 1000
// (2023-08-23T15:59:24Z) "the future", so the example runs offline.
genesis := func() time.Time { return time.Unix(p.GenesisTime, 0) }
var dkc bytes.Buffer
Format 3, step 4: the writer EncryptFiles writes format 3 (spec 29.2 to 29.6, 61, 62, 62.1): the files of a list of Sources, each read twice, with the comment and the declared author. - Before anything is written: the paths and the texts are checked with the rules of the reader, in the words of a writer, naming the rule and the character, and the two paths of an R7 collision (rule 15); the comment has its CR LF and lone CR turned into LF (29.6); L is measured with a head whose salt and SHA-256 are zero, as long as the final one, and the first reading hashes each file, which must have exactly its Size. - The files go in the byte order of their paths (R8), whatever the order of the Sources; the mtime is kept only from 1970 to 9999, never clipped (rule 16); at least one file or a comment (rule 14). - The head, with a fresh salt, the control and the security area are decoded with the rules of the reader before sealing (rule 17), and the frame is checked against L. The area is 512 bytes with the empty security, whatever the options (rule 13). - The second reading writes each file into PAYLOAD_AGE and fails if its size or SHA-256 changed (rule 18). - Encrypt and EncryptFiles share the sealing; Encrypt writes format 2 only with the new TestVectors option (rule 1), and takes no head. The test data generators set it, and so does the CLI until step 5 moves it to EncryptFiles. - Result.Head is the head written. DecodeHead keeps the check of the critical extensions apart, so that the self-check decodes the head as the one of the control does. - The examples and the live test write with EncryptFiles. - The reader tests had a literal U+202E, now escaped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
res, err := capsule.EncryptFiles(&dkc, []capsule.Source{source("carta.txt", "hello from the past")}, capsule.EncryptOptions{
Profile: p,
UnlockAt: time.Date(2023, 8, 23, 15, 59, 24, 0, time.UTC),
Policy: capsule.TimeAndKey,
NewPortableKey: true,
Format 3, step 4: the writer EncryptFiles writes format 3 (spec 29.2 to 29.6, 61, 62, 62.1): the files of a list of Sources, each read twice, with the comment and the declared author. - Before anything is written: the paths and the texts are checked with the rules of the reader, in the words of a writer, naming the rule and the character, and the two paths of an R7 collision (rule 15); the comment has its CR LF and lone CR turned into LF (29.6); L is measured with a head whose salt and SHA-256 are zero, as long as the final one, and the first reading hashes each file, which must have exactly its Size. - The files go in the byte order of their paths (R8), whatever the order of the Sources; the mtime is kept only from 1970 to 9999, never clipped (rule 16); at least one file or a comment (rule 14). - The head, with a fresh salt, the control and the security area are decoded with the rules of the reader before sealing (rule 17), and the frame is checked against L. The area is 512 bytes with the empty security, whatever the options (rule 13). - The second reading writes each file into PAYLOAD_AGE and fails if its size or SHA-256 changed (rule 18). - Encrypt and EncryptFiles share the sealing; Encrypt writes format 2 only with the new TestVectors option (rule 1), and takes no head. The test data generators set it, and so does the CLI until step 5 moves it to EncryptFiles. - Result.Head is the head written. DecodeHead keeps the check of the critical extensions apart, so that the self-check decodes the head as the one of the control does. - The examples and the live test write with EncryptFiles. - The reader tests had a literal U+202E, now escaped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
Comment: "Para abrir dentro de un rato.",
Now: genesis,
})
if err != nil {
panic(err)
}
var dkk bytes.Buffer
if err := accesskey.Encode(&dkk, res.PortableKey); err != nil {
panic(err)
}
fmt.Println("round", res.DateKey.Round, "unlocks at", res.UnlockAt.Format(time.RFC3339))
// Before the round: no request is made.
key, _ := accesskey.Decode(&dkk)
src := provider.ReleaseSourceFunc(func(_ context.Context, _ *profile.Profile, c provider.Condition) (provider.Release, error) {
return provider.Release{Round: c.Round, Signature: round1000}, nil
})
Format 3, step 4: the writer EncryptFiles writes format 3 (spec 29.2 to 29.6, 61, 62, 62.1): the files of a list of Sources, each read twice, with the comment and the declared author. - Before anything is written: the paths and the texts are checked with the rules of the reader, in the words of a writer, naming the rule and the character, and the two paths of an R7 collision (rule 15); the comment has its CR LF and lone CR turned into LF (29.6); L is measured with a head whose salt and SHA-256 are zero, as long as the final one, and the first reading hashes each file, which must have exactly its Size. - The files go in the byte order of their paths (R8), whatever the order of the Sources; the mtime is kept only from 1970 to 9999, never clipped (rule 16); at least one file or a comment (rule 14). - The head, with a fresh salt, the control and the security area are decoded with the rules of the reader before sealing (rule 17), and the frame is checked against L. The area is 512 bytes with the empty security, whatever the options (rule 13). - The second reading writes each file into PAYLOAD_AGE and fails if its size or SHA-256 changed (rule 18). - Encrypt and EncryptFiles share the sealing; Encrypt writes format 2 only with the new TestVectors option (rule 1), and takes no head. The test data generators set it, and so does the CLI until step 5 moves it to EncryptFiles. - Result.Head is the head written. DecodeHead keeps the check of the critical extensions apart, so that the self-check decodes the head as the one of the control does. - The examples and the live test write with EncryptFiles. - The reader tests had a literal U+202E, now escaped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
files := &memorySink{}
opts := capsule.OpenOptions{Registry: reg, Source: src, AccessKey: key, Now: genesis, Sink: files}
_, err = capsule.Open(context.Background(), nil, bytes.NewReader(dkc.Bytes()), opts)
fmt.Println("too early:", errors.Is(err, datekeys.ErrReleaseUnavailable))
// After the round: the release is verified locally and the capsule opens.
Format 3, step 4: the writer EncryptFiles writes format 3 (spec 29.2 to 29.6, 61, 62, 62.1): the files of a list of Sources, each read twice, with the comment and the declared author. - Before anything is written: the paths and the texts are checked with the rules of the reader, in the words of a writer, naming the rule and the character, and the two paths of an R7 collision (rule 15); the comment has its CR LF and lone CR turned into LF (29.6); L is measured with a head whose salt and SHA-256 are zero, as long as the final one, and the first reading hashes each file, which must have exactly its Size. - The files go in the byte order of their paths (R8), whatever the order of the Sources; the mtime is kept only from 1970 to 9999, never clipped (rule 16); at least one file or a comment (rule 14). - The head, with a fresh salt, the control and the security area are decoded with the rules of the reader before sealing (rule 17), and the frame is checked against L. The area is 512 bytes with the empty security, whatever the options (rule 13). - The second reading writes each file into PAYLOAD_AGE and fails if its size or SHA-256 changed (rule 18). - Encrypt and EncryptFiles share the sealing; Encrypt writes format 2 only with the new TestVectors option (rule 1), and takes no head. The test data generators set it, and so does the CLI until step 5 moves it to EncryptFiles. - Result.Head is the head written. DecodeHead keeps the check of the critical extensions apart, so that the self-check decodes the head as the one of the control does. - The examples and the live test write with EncryptFiles. - The reader tests had a literal U+202E, now escaped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
// The verdicts of the security area come before the comment.
opts.Now = time.Now
Format 3, step 4: the writer EncryptFiles writes format 3 (spec 29.2 to 29.6, 61, 62, 62.1): the files of a list of Sources, each read twice, with the comment and the declared author. - Before anything is written: the paths and the texts are checked with the rules of the reader, in the words of a writer, naming the rule and the character, and the two paths of an R7 collision (rule 15); the comment has its CR LF and lone CR turned into LF (29.6); L is measured with a head whose salt and SHA-256 are zero, as long as the final one, and the first reading hashes each file, which must have exactly its Size. - The files go in the byte order of their paths (R8), whatever the order of the Sources; the mtime is kept only from 1970 to 9999, never clipped (rule 16); at least one file or a comment (rule 14). - The head, with a fresh salt, the control and the security area are decoded with the rules of the reader before sealing (rule 17), and the frame is checked against L. The area is 512 bytes with the empty security, whatever the options (rule 13). - The second reading writes each file into PAYLOAD_AGE and fails if its size or SHA-256 changed (rule 18). - Encrypt and EncryptFiles share the sealing; Encrypt writes format 2 only with the new TestVectors option (rule 1), and takes no head. The test data generators set it, and so does the CLI until step 5 moves it to EncryptFiles. - Result.Head is the head written. DecodeHead keeps the check of the critical extensions apart, so that the self-check decodes the head as the one of the control does. - The examples and the live test write with EncryptFiles. - The reader tests had a literal U+202E, now escaped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
opened, err := capsule.Open(context.Background(), nil, bytes.NewReader(dkc.Bytes()), opts)
if err != nil {
panic(err)
}
Format 3, step 4: the writer EncryptFiles writes format 3 (spec 29.2 to 29.6, 61, 62, 62.1): the files of a list of Sources, each read twice, with the comment and the declared author. - Before anything is written: the paths and the texts are checked with the rules of the reader, in the words of a writer, naming the rule and the character, and the two paths of an R7 collision (rule 15); the comment has its CR LF and lone CR turned into LF (29.6); L is measured with a head whose salt and SHA-256 are zero, as long as the final one, and the first reading hashes each file, which must have exactly its Size. - The files go in the byte order of their paths (R8), whatever the order of the Sources; the mtime is kept only from 1970 to 9999, never clipped (rule 16); at least one file or a comment (rule 14). - The head, with a fresh salt, the control and the security area are decoded with the rules of the reader before sealing (rule 17), and the frame is checked against L. The area is 512 bytes with the empty security, whatever the options (rule 13). - The second reading writes each file into PAYLOAD_AGE and fails if its size or SHA-256 changed (rule 18). - Encrypt and EncryptFiles share the sealing; Encrypt writes format 2 only with the new TestVectors option (rule 1), and takes no head. The test data generators set it, and so does the CLI until step 5 moves it to EncryptFiles. - Result.Head is the head written. DecodeHead keeps the check of the critical extensions apart, so that the self-check decodes the head as the one of the control does. - The examples and the live test write with EncryptFiles. - The reader tests had a literal U+202E, now escaped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
for _, line := range opened.Verdicts.Lines() {
fmt.Println(line)
}
fmt.Println(opened.Head.Comment)
fmt.Println(opened.Head.Files[0].Path+":", files.files[0])
// Output:
// round 1000 unlocks at 2023-08-23T15:59:24Z
// too early: true
Format 3, step 4: the writer EncryptFiles writes format 3 (spec 29.2 to 29.6, 61, 62, 62.1): the files of a list of Sources, each read twice, with the comment and the declared author. - Before anything is written: the paths and the texts are checked with the rules of the reader, in the words of a writer, naming the rule and the character, and the two paths of an R7 collision (rule 15); the comment has its CR LF and lone CR turned into LF (29.6); L is measured with a head whose salt and SHA-256 are zero, as long as the final one, and the first reading hashes each file, which must have exactly its Size. - The files go in the byte order of their paths (R8), whatever the order of the Sources; the mtime is kept only from 1970 to 9999, never clipped (rule 16); at least one file or a comment (rule 14). - The head, with a fresh salt, the control and the security area are decoded with the rules of the reader before sealing (rule 17), and the frame is checked against L. The area is 512 bytes with the empty security, whatever the options (rule 13). - The second reading writes each file into PAYLOAD_AGE and fails if its size or SHA-256 changed (rule 18). - Encrypt and EncryptFiles share the sealing; Encrypt writes format 2 only with the new TestVectors option (rule 1), and takes no head. The test data generators set it, and so does the CLI until step 5 moves it to EncryptFiles. - Result.Head is the head written. DecodeHead keeps the check of the critical extensions apart, so that the self-check decodes the head as the one of the control does. - The examples and the live test write with EncryptFiles. - The reader tests had a literal U+202E, now escaped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
// Sin firma de autor.
// Para abrir dentro de un rato.
// carta.txt: hello from the past
}
func ExampleInspect() {
reg, _ := profile.Default()
p := profile.Quicknet()
var dkc bytes.Buffer
Format 3, step 4: the writer EncryptFiles writes format 3 (spec 29.2 to 29.6, 61, 62, 62.1): the files of a list of Sources, each read twice, with the comment and the declared author. - Before anything is written: the paths and the texts are checked with the rules of the reader, in the words of a writer, naming the rule and the character, and the two paths of an R7 collision (rule 15); the comment has its CR LF and lone CR turned into LF (29.6); L is measured with a head whose salt and SHA-256 are zero, as long as the final one, and the first reading hashes each file, which must have exactly its Size. - The files go in the byte order of their paths (R8), whatever the order of the Sources; the mtime is kept only from 1970 to 9999, never clipped (rule 16); at least one file or a comment (rule 14). - The head, with a fresh salt, the control and the security area are decoded with the rules of the reader before sealing (rule 17), and the frame is checked against L. The area is 512 bytes with the empty security, whatever the options (rule 13). - The second reading writes each file into PAYLOAD_AGE and fails if its size or SHA-256 changed (rule 18). - Encrypt and EncryptFiles share the sealing; Encrypt writes format 2 only with the new TestVectors option (rule 1), and takes no head. The test data generators set it, and so does the CLI until step 5 moves it to EncryptFiles. - Result.Head is the head written. DecodeHead keeps the check of the critical extensions apart, so that the self-check decodes the head as the one of the control does. - The examples and the live test write with EncryptFiles. - The reader tests had a literal U+202E, now escaped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
_, _ = capsule.EncryptFiles(&dkc, []capsule.Source{source("x.txt", "x")}, capsule.EncryptOptions{
Profile: p,
UnlockAt: time.Date(2030, 1, 1, 0, 0, 0, 0, time.UTC),
Now: func() time.Time { return time.Date(2026, 9, 25, 0, 0, 0, 0, time.UTC) },
})
in, err := capsule.Inspect(bytes.NewReader(dkc.Bytes()), capsule.InspectOptions{Registry: reg})
if err != nil {
panic(err)
}
fmt.Println(in.Header.Policy, in.Header.DateKey.Round, in.UnlockAt.Format(time.RFC3339), len(in.Checks), "checks passed")
// Output: time_only 66884212 2030-01-01T00:00:00Z 8 checks passed
}

Powered by TurnKey Linux.