NextMyDay/internal/core/auth/sealer_test.go
Claus Lohmar 76a4a6950c feat(auth): add WebAuthn, TOTP and the enroll/login flow (SPEC-004/006)
- webauthn: the passkey ceremony service (a fake in tests)
- totp: the TOTP authenticator; the secret is AEAD-sealed at rest (A9)
- sealer: the AEAD TOTP sealer
- identities/sessions/credentials: the GUID state machine
- flow: the enroll/login screens + the passkey nudge (pre-session
  double-submit CSRF — A15), rendered inside the shell
2026-10-14 10:53:53 +00:00

64 lines
1.6 KiB
Go

package auth_test
import (
"bytes"
"errors"
"testing"
"git.lohmar.co.uk/cclohmar/NextMyDay/internal/core/auth"
)
func TestAEADSealerRoundTrip(t *testing.T) {
key := bytes.Repeat([]byte{0x42}, auth.KeySize)
sealer, err := auth.NewAEADSealer(key)
if err != nil {
t.Fatalf("NewAEADSealer: %v", err)
}
plaintext := []byte("JBSWY3DPEHPK3PXP")
sealed, err := sealer.Seal(plaintext)
if err != nil {
t.Fatalf("Seal: %v", err)
}
if bytes.Contains(sealed, plaintext) {
t.Fatal("ciphertext contains the plaintext")
}
opened, err := sealer.Open(sealed)
if err != nil {
t.Fatalf("Open: %v", err)
}
if !bytes.Equal(opened, plaintext) {
t.Errorf("Open = %q, want %q", opened, plaintext)
}
// A fresh nonce means sealing twice yields different ciphertext.
sealed2, err := sealer.Seal(plaintext)
if err != nil {
t.Fatalf("Seal (2): %v", err)
}
if bytes.Equal(sealed, sealed2) {
t.Error("two seals of the same plaintext are identical (nonce not fresh)")
}
}
func TestAEADSealerRejectsWrongKeySize(t *testing.T) {
if _, err := auth.NewAEADSealer(make([]byte, 16)); err == nil {
t.Error("NewAEADSealer(16 bytes) = nil error, want error")
}
}
func TestAEADSealerRejectsTamperedCiphertext(t *testing.T) {
sealer, err := auth.NewAEADSealer(bytes.Repeat([]byte{1}, auth.KeySize))
if err != nil {
t.Fatalf("NewAEADSealer: %v", err)
}
sealed, err := sealer.Seal([]byte("secret"))
if err != nil {
t.Fatalf("Seal: %v", err)
}
sealed[len(sealed)-1] ^= 0xff // flip a tag bit
if _, err := sealer.Open(sealed); !errors.Is(err, auth.ErrInvalidCiphertext) {
t.Errorf("Open(tampered) = %v, want ErrInvalidCiphertext", err)
}
}