Files

84 lines
2.3 KiB
Go

package service
import (
"bytes"
"crypto/ecdh"
"encoding/base64"
"strings"
"testing"
)
// The panel generates Reality keys in-process now (no xray binary on a
// control-plane-only master). These tests pin the wire format to what
// `xray x25519` prints — base64 RawURLEncoding of the raw 32-byte keys —
// and prove the pair is a genuine X25519 pair by re-deriving the public
// key from the private key and by an ECDH agreement check.
func TestGenerateX25519KeyPair_MatchesXrayFormatAndCurve(t *testing.T) {
privB64, pubB64, err := generateX25519KeyPair()
if err != nil {
t.Fatalf("generateX25519KeyPair: %v", err)
}
for name, k := range map[string]string{"private": privB64, "public": pubB64} {
if len(k) != 43 || strings.ContainsAny(k, "+/=") {
t.Fatalf("%s key %q is not 43-char raw base64url", name, k)
}
raw, err := base64.RawURLEncoding.DecodeString(k)
if err != nil {
t.Fatalf("%s key does not decode as raw base64url: %v", name, err)
}
if len(raw) != 32 {
t.Fatalf("%s key decodes to %d bytes, want 32", name, len(raw))
}
}
privRaw, _ := base64.RawURLEncoding.DecodeString(privB64)
pubRaw, _ := base64.RawURLEncoding.DecodeString(pubB64)
priv, err := ecdh.X25519().NewPrivateKey(privRaw)
if err != nil {
t.Fatalf("NewPrivateKey: %v", err)
}
if got := priv.PublicKey().Bytes(); !bytes.Equal(got, pubRaw) {
t.Fatalf("public key does not correspond to private key:\n got %x\nwant %x", got, pubRaw)
}
}
func TestGenerateX25519KeyPair_ECDHagreement(t *testing.T) {
privAB64, pubAB64, err := generateX25519KeyPair()
if err != nil {
t.Fatal(err)
}
privBB64, pubBB64, err := generateX25519KeyPair()
if err != nil {
t.Fatal(err)
}
if privAB64 == privBB64 || pubAB64 == pubBB64 {
t.Fatal("two generations produced identical keys")
}
decode := func(s string) []byte {
raw, err := base64.RawURLEncoding.DecodeString(s)
if err != nil {
t.Fatal(err)
}
return raw
}
privA, _ := ecdh.X25519().NewPrivateKey(decode(privAB64))
privB, _ := ecdh.X25519().NewPrivateKey(decode(privBB64))
pubA, _ := ecdh.X25519().NewPublicKey(decode(pubAB64))
pubB, _ := ecdh.X25519().NewPublicKey(decode(pubBB64))
secretAB, err := privA.ECDH(pubB)
if err != nil {
t.Fatal(err)
}
secretBA, err := privB.ECDH(pubA)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(secretAB, secretBA) {
t.Fatal("ECDH shared secrets differ")
}
}