Co-authored-by: clawbot <clawbot@eeqj.de> Reviewed-on: #24 Reviewed-by: clawbot <clawbot@noreply.example.org> Co-authored-by: sneak <sneak@sneak.berlin> Co-committed-by: sneak <sneak@sneak.berlin>
164 lines
3.7 KiB
Go
164 lines
3.7 KiB
Go
//go:build darwin
|
|
// +build darwin
|
|
|
|
package macse
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
)
|
|
|
|
const testKeyLabel = "berlin.sneak.app.secret.test.se-key"
|
|
|
|
// testKeyHash stores the hash of the created test key for cleanup.
|
|
var testKeyHash string //nolint:gochecknoglobals
|
|
|
|
// skipIfNoSecureEnclave skips the test if SE access is unavailable.
|
|
func skipIfNoSecureEnclave(t *testing.T) {
|
|
t.Helper()
|
|
|
|
probeLabel := "berlin.sneak.app.secret.test.se-probe"
|
|
_, hash, err := CreateKey(probeLabel)
|
|
if err != nil {
|
|
t.Skipf("Secure Enclave unavailable (skipping): %v", err)
|
|
}
|
|
|
|
if hash != "" {
|
|
_ = DeleteKey(hash)
|
|
}
|
|
}
|
|
|
|
func TestCreateAndDeleteKey(t *testing.T) {
|
|
skipIfNoSecureEnclave(t)
|
|
|
|
if testKeyHash != "" {
|
|
_ = DeleteKey(testKeyHash)
|
|
}
|
|
|
|
pubKey, hash, err := CreateKey(testKeyLabel)
|
|
if err != nil {
|
|
t.Fatalf("CreateKey failed: %v", err)
|
|
}
|
|
|
|
testKeyHash = hash
|
|
t.Logf("Created key with hash: %s", hash)
|
|
|
|
// Verify valid uncompressed P-256 public key
|
|
if len(pubKey) != p256UncompressedKeySize {
|
|
t.Fatalf("expected public key length %d, got %d", p256UncompressedKeySize, len(pubKey))
|
|
}
|
|
|
|
if pubKey[0] != 0x04 {
|
|
t.Fatalf("expected uncompressed point prefix 0x04, got 0x%02x", pubKey[0])
|
|
}
|
|
|
|
if hash == "" {
|
|
t.Fatal("expected non-empty hash")
|
|
}
|
|
|
|
// Delete the key
|
|
if err := DeleteKey(hash); err != nil {
|
|
t.Fatalf("DeleteKey failed: %v", err)
|
|
}
|
|
|
|
testKeyHash = ""
|
|
t.Log("Key created, verified, and deleted successfully")
|
|
}
|
|
|
|
func TestEncryptDecryptRoundTrip(t *testing.T) {
|
|
skipIfNoSecureEnclave(t)
|
|
|
|
_, hash, err := CreateKey(testKeyLabel)
|
|
if err != nil {
|
|
t.Fatalf("CreateKey failed: %v", err)
|
|
}
|
|
|
|
testKeyHash = hash
|
|
|
|
defer func() {
|
|
if testKeyHash != "" {
|
|
_ = DeleteKey(testKeyHash)
|
|
testKeyHash = ""
|
|
}
|
|
}()
|
|
|
|
// Test data simulating an age private key
|
|
plaintext := []byte("AGE-SECRET-KEY-1QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ")
|
|
|
|
// Encrypt
|
|
ciphertext, err := Encrypt(testKeyLabel, plaintext)
|
|
if err != nil {
|
|
t.Fatalf("Encrypt failed: %v", err)
|
|
}
|
|
|
|
t.Logf("Plaintext: %d bytes, Ciphertext: %d bytes", len(plaintext), len(ciphertext))
|
|
|
|
if bytes.Equal(ciphertext, plaintext) {
|
|
t.Fatal("ciphertext should differ from plaintext")
|
|
}
|
|
|
|
// Decrypt
|
|
decrypted, err := Decrypt(testKeyLabel, ciphertext)
|
|
if err != nil {
|
|
t.Fatalf("Decrypt failed: %v", err)
|
|
}
|
|
|
|
if !bytes.Equal(decrypted, plaintext) {
|
|
t.Fatalf("decrypted data does not match original plaintext")
|
|
}
|
|
|
|
t.Log("ECIES encrypt/decrypt round-trip successful")
|
|
}
|
|
|
|
func TestEncryptProducesDifferentCiphertexts(t *testing.T) {
|
|
skipIfNoSecureEnclave(t)
|
|
|
|
_, hash, err := CreateKey(testKeyLabel)
|
|
if err != nil {
|
|
t.Fatalf("CreateKey failed: %v", err)
|
|
}
|
|
|
|
testKeyHash = hash
|
|
|
|
defer func() {
|
|
if testKeyHash != "" {
|
|
_ = DeleteKey(testKeyHash)
|
|
testKeyHash = ""
|
|
}
|
|
}()
|
|
|
|
plaintext := []byte("test-secret-data")
|
|
|
|
ct1, err := Encrypt(testKeyLabel, plaintext)
|
|
if err != nil {
|
|
t.Fatalf("first Encrypt failed: %v", err)
|
|
}
|
|
|
|
ct2, err := Encrypt(testKeyLabel, plaintext)
|
|
if err != nil {
|
|
t.Fatalf("second Encrypt failed: %v", err)
|
|
}
|
|
|
|
// ECIES uses a random ephemeral key each time, so ciphertexts should differ
|
|
if bytes.Equal(ct1, ct2) {
|
|
t.Fatal("two encryptions of same plaintext should produce different ciphertexts")
|
|
}
|
|
|
|
// Both should decrypt to the same plaintext
|
|
dec1, err := Decrypt(testKeyLabel, ct1)
|
|
if err != nil {
|
|
t.Fatalf("first Decrypt failed: %v", err)
|
|
}
|
|
|
|
dec2, err := Decrypt(testKeyLabel, ct2)
|
|
if err != nil {
|
|
t.Fatalf("second Decrypt failed: %v", err)
|
|
}
|
|
|
|
if !bytes.Equal(dec1, plaintext) || !bytes.Equal(dec2, plaintext) {
|
|
t.Fatal("both ciphertexts should decrypt to original plaintext")
|
|
}
|
|
|
|
t.Log("ECIES correctly produces different ciphertexts that decrypt to same plaintext")
|
|
}
|