package secrets import ( "sync" "testing" ) // resetForTest 清空惰性缓存的 AEAD,让后续调用按当前环境变量重新派生密钥。 func resetForTest() { gcmOnce = sync.Once{} gcm = nil gcmErr = nil } func TestEncryptDecryptRoundTrip(t *testing.T) { t.Setenv("SUNDYNIX_SECRET_KEY", "unit-test-key") resetForTest() plain := "sk-912cf85b16d04b22bcb95f4576423bfb" ct, err := Encrypt(plain) if err != nil { t.Fatalf("encrypt: %v", err) } if !IsEncrypted(ct) { t.Fatalf("expected ciphertext prefix, got %q", ct) } if ct == plain { t.Fatal("ciphertext must differ from plaintext") } got, err := Decrypt(ct) if err != nil { t.Fatalf("decrypt: %v", err) } if got != plain { t.Fatalf("round trip mismatch: got %q want %q", got, plain) } } func TestEncryptEmptyIsNoop(t *testing.T) { resetForTest() ct, err := Encrypt("") if err != nil || ct != "" { t.Fatalf("empty should stay empty: %q %v", ct, err) } } func TestDecryptLegacyPlaintextPassthrough(t *testing.T) { resetForTest() // 历史明文行无 enc: 前缀,应原样返回(平滑迁移)。 got, err := Decrypt("plain-legacy-key") if err != nil { t.Fatalf("legacy passthrough errored: %v", err) } if got != "plain-legacy-key" { t.Fatalf("legacy passthrough mismatch: %q", got) } } func TestNonceRandomized(t *testing.T) { t.Setenv("SUNDYNIX_SECRET_KEY", "unit-test-key") resetForTest() a, _ := Encrypt("same-input") b, _ := Encrypt("same-input") if a == b { t.Fatal("two encryptions of same input must differ (random nonce)") } } func TestWrongKeyFailsClosed(t *testing.T) { t.Setenv("SUNDYNIX_SECRET_KEY", "key-A") resetForTest() ct, _ := Encrypt("secret") t.Setenv("SUNDYNIX_SECRET_KEY", "key-B") resetForTest() if _, err := Decrypt(ct); err == nil { t.Fatal("decrypt with wrong key must error, not silently succeed") } }