- 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
64 lines
1.6 KiB
Go
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)
|
|
}
|
|
}
|