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.
100 lines
3.1 KiB
100 lines
3.1 KiB
//go:build interop
|
|
|
|
// Interoperability with third-party tools (plan §7.9): SEALED_CONTROL and
|
|
// PAYLOAD_AGE of an official fixture are standard age files, opened here by
|
|
// the official age and tle command-line tools.
|
|
//
|
|
// go install filippo.io/age/cmd/age@v1.3.2
|
|
// go install github.com/drand/tlock/cmd/tle@v1.2.0
|
|
// go test -tags interop ./capsule -run Interop
|
|
//
|
|
// DATEKEYS_AGE and DATEKEYS_TLE may point at the binaries. The tle part
|
|
// fetches round 1000 from the public drand relay.
|
|
package capsule_test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"filippo.io/age"
|
|
|
|
"g.activething.com/go/DateKeys/agewrap"
|
|
"g.activething.com/go/DateKeys/internal/testkit"
|
|
)
|
|
|
|
func tool(t *testing.T, env, name string) string {
|
|
t.Helper()
|
|
if p := os.Getenv(env); p != "" {
|
|
return p
|
|
}
|
|
p, err := exec.LookPath(name)
|
|
if err != nil {
|
|
t.Skipf("%s not found; install it or set %s", name, env)
|
|
}
|
|
return p
|
|
}
|
|
|
|
func TestInteropAgeOpensPayload(t *testing.T) {
|
|
bin := tool(t, "DATEKEYS_AGE", "age")
|
|
f := loadFixture(t, "time_only")
|
|
parts, _ := testkit.Split(f.dkc)
|
|
raw, _ := hex.DecodeString(f.PayloadIdentity)
|
|
id, err := agewrap.X25519IdentityFromRaw(raw)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
dir := t.TempDir()
|
|
os.WriteFile(filepath.Join(dir, "payload.age"), parts.Payload, 0o600)
|
|
os.WriteFile(filepath.Join(dir, "id.txt"), []byte(id.String()+"\n"), 0o600)
|
|
out := filepath.Join(dir, "plain")
|
|
cmd := exec.Command(bin, "-d", "-i", filepath.Join(dir, "id.txt"), "-o", out, filepath.Join(dir, "payload.age"))
|
|
if b, err := cmd.CombinedOutput(); err != nil {
|
|
t.Fatalf("age: %v\n%s", err, b)
|
|
}
|
|
if got, _ := os.ReadFile(out); !bytes.Equal(got, f.plaintext) {
|
|
t.Fatal("age produced a different plaintext")
|
|
}
|
|
}
|
|
|
|
func TestInteropAgeEncryptsPayloadWeOpen(t *testing.T) {
|
|
bin := tool(t, "DATEKEYS_AGE", "age")
|
|
id, _ := age.GenerateX25519Identity()
|
|
dir := t.TempDir()
|
|
os.WriteFile(filepath.Join(dir, "in"), []byte("written by age"), 0o600)
|
|
out := filepath.Join(dir, "out.age")
|
|
if b, err := exec.Command(bin, "-r", id.Recipient().String(), "-o", out, filepath.Join(dir, "in")).CombinedOutput(); err != nil {
|
|
t.Fatalf("age: %v\n%s", err, b)
|
|
}
|
|
file, _ := os.ReadFile(out)
|
|
raw, _ := agewrap.RawX25519Identity(id)
|
|
pid, _ := agewrap.NewPayloadIdentity(raw)
|
|
if got := decryptAge(t, file, pid); string(got) != "written by age" {
|
|
t.Fatal("plaintext differs")
|
|
}
|
|
}
|
|
|
|
func TestInteropTleOpensSealedControl(t *testing.T) {
|
|
bin := tool(t, "DATEKEYS_TLE", "tle")
|
|
f := loadFixture(t, "time_only")
|
|
parts, _ := testkit.Split(f.dkc)
|
|
dir := t.TempDir()
|
|
in := filepath.Join(dir, "sealed.age")
|
|
os.WriteFile(in, parts.Sealed, 0o600)
|
|
out := filepath.Join(dir, "control.cbor")
|
|
cmd := exec.Command(bin, "-d", "-o", out, in)
|
|
if b, err := cmd.CombinedOutput(); err != nil {
|
|
if strings.Contains(string(b), "dial") || strings.Contains(string(b), "no such host") {
|
|
t.Skipf("tle needs network access: %s", b)
|
|
}
|
|
t.Fatalf("tle: %v\n%s", err, b)
|
|
}
|
|
if got, _ := os.ReadFile(out); hex.EncodeToString(got) != f.ControlCBOR {
|
|
t.Fatal("tle produced a different CONTROL_CBOR")
|
|
}
|
|
}
|