package cryptokit import ( "bytes" "crypto/ed25519" "crypto/rand" "crypto/rsa" "encoding/base64" "encoding/pem" "os" "os/exec" "testing" "filippo.io/age" "golang.org/x/crypto/ssh" ) func TestEd25519SignVerifyAcceptsSeedEncoding(t *testing.T) { public, private, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } message := []byte("Aegis cryptographic test") signature, err := SignEd25519(message, base64.StdEncoding.EncodeToString(private.Seed())) if err != nil { t.Fatal(err) } if err := VerifyEd25519(message, signature, base64.StdEncoding.EncodeToString(public)); err != nil { t.Fatal(err) } if err := VerifyEd25519([]byte("tampered"), signature, base64.StdEncoding.EncodeToString(public)); err == nil { t.Fatal("tampered message verified") } } func TestEd25519PublicKeyAndFingerprint(t *testing.T) { public, private, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } derived, err := Ed25519PublicKey(base64.StdEncoding.EncodeToString(private.Seed())) if err != nil { t.Fatal(err) } if derived != base64.StdEncoding.EncodeToString(public) { t.Fatalf("derived public key = %q, want %q", derived, base64.StdEncoding.EncodeToString(public)) } fingerprint, err := Ed25519PublicKeyFingerprint(derived) if err != nil { t.Fatal(err) } if len(fingerprint) != len("sha256:")+64 || fingerprint[:len("sha256:")] != "sha256:" { t.Fatalf("unexpected fingerprint %q", fingerprint) } } func TestAgeRoundTrip(t *testing.T) { identity, err := age.GenerateX25519Identity() if err != nil { t.Fatal(err) } ciphertext, err := EncryptAge([]byte("age test"), identity.Recipient().String()) if err != nil { t.Fatal(err) } plaintext, err := DecryptAge(ciphertext, identity.String()) if err != nil { t.Fatal(err) } if string(plaintext) != "age test" { t.Fatalf("unexpected plaintext %q", plaintext) } } func TestAgeSSHCompatibility(t *testing.T) { testKey := func(private any) { signer, err := ssh.NewSignerFromKey(private) if err != nil { t.Fatal(err) } privatePEM, err := ssh.MarshalPrivateKey(private, "") if err != nil { t.Fatal(err) } ciphertext, err := EncryptAge([]byte("age SSH test"), string(ssh.MarshalAuthorizedKey(signer.PublicKey()))) if err != nil { t.Fatal(err) } plaintext, err := DecryptAge(ciphertext, string(pem.EncodeToMemory(privatePEM))) if err != nil { t.Fatal(err) } if string(plaintext) != "age SSH test" { t.Fatalf("unexpected plaintext %q", plaintext) } } _, edPrivate, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } testKey(edPrivate) rsaPrivate, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { t.Fatal(err) } testKey(rsaPrivate) } func TestOpenPGPRoundTripWithUserKeyMaterial(t *testing.T) { gpg, err := exec.LookPath("gpg") if err != nil { t.Skip("gpg is not installed") } home := t.TempDir() if err := os.Chmod(home, 0o700); err != nil { t.Fatal(err) } run := func(args []string, input []byte) ([]byte, error) { cmd := exec.Command(gpg, append([]string{"--batch", "--no-tty", "--no-options", "--homedir", home}, args...)...) cmd.Stdin = bytes.NewReader(input) return cmd.Output() } if _, err := run([]string{"--pinentry-mode", "loopback", "--passphrase", "", "--quick-generate-key", "Aegis Test ", "rsa2048", "sign", "1d"}, nil); err != nil { t.Skipf("gpg cannot create an ephemeral test key: %v", err) } if _, err := run([]string{"--pinentry-mode", "loopback", "--passphrase", "", "--quick-add-key", "aegis@example.invalid", "rsa2048", "encrypt", "1d"}, nil); err != nil { t.Skipf("gpg cannot create an ephemeral encryption subkey: %v", err) } publicKey, err := run([]string{"--armor", "--export", "aegis@example.invalid"}, nil) if err != nil { t.Fatal(err) } privateKey, err := run([]string{"--armor", "--export-secret-keys", "aegis@example.invalid"}, nil) if err != nil { t.Fatal(err) } message := []byte("OpenPGP compatibility test") signature, err := SignOpenPGPDetached(message, string(privateKey)) if err != nil { t.Fatal(err) } if err := VerifyOpenPGPDetached(message, signature, string(publicKey)); err != nil { t.Fatal(err) } ciphertext, err := EncryptOpenPGP(message, string(publicKey), string(privateKey)) if err != nil { t.Fatal(err) } plaintext, err := DecryptOpenPGP([]byte(ciphertext), string(privateKey)) if err != nil { t.Fatal(err) } if string(plaintext) != string(message) { t.Fatalf("unexpected plaintext %q", plaintext) } }