package wgtunnel // Group A — keygen (S3 Part 1). The fixed vector is the red-proof-(c) anchor: remove the clamp // and the derived public key diverges from the real `wg pubkey`. import ( "encoding/base64" "os" "path/filepath" "runtime" "strings" "testing" ) // TestInstallRecoveredKey_SameIdentityCreateOnly (S5): a recovered WG key installs into a fresh // state dir, EnsureKey LOADS it (no keygen) yielding the SAME pubkey (→ same /32); a second install // REFUSES (create-only, never overwrite); an invalid key errors and writes nothing. func TestInstallRecoveredKey_SameIdentityCreateOnly(t *testing.T) { src := t.TempDir() srcPub, created, err := EnsureKey(src) if err != nil || !created { t.Fatalf("seed EnsureKey: created=%v err=%v", created, err) } recovered, err := readPrivateKeyB64(src) // the base64 the escrow bundle carries if err != nil { t.Fatal(err) } dst := t.TempDir() if err := InstallRecoveredKey(dst, recovered); err != nil { t.Fatalf("InstallRecoveredKey: %v", err) } pub, created, err := EnsureKey(dst) // must LOAD, not generate if err != nil { t.Fatal(err) } if created { t.Error("EnsureKey generated a fresh key instead of loading the installed one (no-keygen negative)") } if pub != srcPub { t.Errorf("recovered pubkey = %q, want same as source %q (same /32)", pub, srcPub) } // Create-only: a second install REFUSES (a present key may be a live identity). if err := InstallRecoveredKey(dst, recovered); err == nil || !strings.Contains(err.Error(), "refusing to overwrite") { t.Errorf("second install must refuse (create-only), got %v", err) } // Invalid recovered key → error, nothing written. bad := t.TempDir() if err := InstallRecoveredKey(bad, "not-base64!!"); err == nil { t.Error("invalid recovered key accepted") } if _, serr := os.Stat(KeyFilePath(bad)); !os.IsNotExist(serr) { t.Error("a key file was written despite an invalid recovered key") } } // Fixed test vector. PROVENANCE: public key generated ONCE with the real `wg pubkey` ( // wireguard-tools on felhom-hetzner, 2026-07-04) from the spec's published test private key — // this private key is a PUBLISHED test constant, not a secret. const ( vectorPrivB64 = "YAn1SdYWjNSVZBM4CxJGQ738mUhSMuZ1yA6ZNZ1XwFg=" vectorPubB64 = "3F+nlkwVVl5OoVY+/vfWH6PDf0H7LCqcHExfJ6ypZj4=" ) func TestDerivePublic_MatchesWgPubkeyVector(t *testing.T) { priv, err := base64.StdEncoding.DecodeString(vectorPrivB64) if err != nil { t.Fatal(err) } // The vector private key is already clamped the way `wg genkey` emits; clamp anyway — it // must be a no-op for an already-clamped key and is required for raw random bytes. clampPrivateKey(priv) pub, err := derivePublic(priv) if err != nil { t.Fatal(err) } if pub != vectorPubB64 { t.Fatalf("derived pubkey = %s, want %s (the real `wg pubkey` output)", pub, vectorPubB64) } } // The UNCLAMPED vector is the red-proof-(c) anchor proper: all-0xFF private bytes are invalid // until clamped; `wg pubkey` clamps internally, so its output equals our clamp+derive. Remove // the clamp and THIS test fails (the primary vector above is already-clamped `wg genkey` output, // which cannot detect a missing clamp). // PROVENANCE: public generated ONCE with the real `wg pubkey` on felhom-hetzner, 2026-07-04. const ( unclampedPrivB64 = "//////////////////////////////////////////8=" unclampedPubB64 = "hHwNLDdSNPNl5mCVUYejc1oPdhPRYJ06ak2MU66qWiI=" ) func TestDerivePublic_ClampRequiredForRawBytes(t *testing.T) { priv, err := base64.StdEncoding.DecodeString(unclampedPrivB64) if err != nil { t.Fatal(err) } clampPrivateKey(priv) pub, err := derivePublic(priv) if err != nil { t.Fatal(err) } if pub != unclampedPubB64 { t.Fatalf("clamped derivation = %s, want %s (real `wg pubkey` on the raw bytes)", pub, unclampedPubB64) } } func TestEnsureKey_CreateOnceThenReload(t *testing.T) { dir := t.TempDir() pub1, created, err := EnsureKey(dir) if err != nil || !created { t.Fatalf("first EnsureKey: pub=%q created=%v err=%v", pub1, created, err) } if len(pub1) != 44 { t.Fatalf("pubkey %q is not 44 base64 chars", pub1) } fi, err := os.Stat(KeyFilePath(dir)) if err != nil { t.Fatal(err) } // POSIX modes are not representable on Windows (Go maps everything to 666/777) — assert on // Linux only; the live bring-up (§13) verifies the real 0600/0700 on the box. if runtime.GOOS != "windows" { if fi.Mode().Perm() != 0o600 { t.Errorf("key file mode = %o, want 0600", fi.Mode().Perm()) } if di, _ := os.Stat(filepath.Join(dir, "wg")); di.Mode().Perm() != 0o700 { t.Errorf("wg dir mode = %o, want 0700", di.Mode().Perm()) } } // Reload: same key, not recreated. pub2, created, err := EnsureKey(dir) if err != nil || created { t.Fatalf("second EnsureKey: created=%v err=%v", created, err) } if pub2 != pub1 { t.Errorf("reload derived a different pubkey: %s vs %s", pub2, pub1) } } // The stored key file must hold CANONICAL CLAMPED bytes: x/crypto X25519 clamps internally (so // derivation is clamp-invariant — a missing clamp is invisible to the pubkey tests above), but // an unclamped stored key would still be a non-canonical secret whose bits differ from what // every WireGuard tool considers the effective key. This is red-proof (c)'s real anchor. func TestEnsureKey_StoredKeyIsClamped(t *testing.T) { for i := 0; i < 8; i++ { // several fresh keys — random bytes are unclamped ~7/8 of the time dir := t.TempDir() if _, _, err := EnsureKey(dir); err != nil { t.Fatal(err) } raw, err := os.ReadFile(KeyFilePath(dir)) if err != nil { t.Fatal(err) } priv, err := decodeKey(raw) if err != nil { t.Fatal(err) } if priv[0]&7 != 0 || priv[31]&128 != 0 || priv[31]&64 != 64 { t.Fatalf("stored key is not clamped: byte0=%08b byte31=%08b", priv[0], priv[31]) } } } func TestEnsureKey_CorruptFileRefused(t *testing.T) { dir := t.TempDir() os.MkdirAll(filepath.Join(dir, "wg"), 0o700) if err := os.WriteFile(KeyFilePath(dir), []byte("not-a-key\n"), 0o600); err != nil { t.Fatal(err) } _, _, err := EnsureKey(dir) if err == nil { t.Fatal("corrupt key file accepted (or overwritten) — must be refused") } // The corrupt file must still be there — never overwritten. raw, _ := os.ReadFile(KeyFilePath(dir)) if string(raw) != "not-a-key\n" { t.Errorf("corrupt key file was modified: %q", raw) } } func TestReadPrivateKeyB64_RoundTrip(t *testing.T) { dir := t.TempDir() if _, _, err := EnsureKey(dir); err != nil { t.Fatal(err) } b64, err := readPrivateKeyB64(dir) if err != nil { t.Fatal(err) } if raw, _ := base64.StdEncoding.DecodeString(b64); len(raw) != 32 { t.Errorf("private key b64 decodes to %d bytes", len(raw)) } }