Files
mpc/pkg/integrity/verify_fuzz_test.go
zeekay 3dece63ca2 security: fix 15 custody audit findings, add regression + fuzz tests
Fixes all findings from the Blue Team defensive security review of the
 →  custody architecture transition.

HIGH:
- S-1: Implement P-256 ECDH + AES-256-GCM encryption of passkey backup shards
- W-2: Reject unparseable WebAuthn public keys (was silently skipping verification)
- O-1: Add Ed25519 binary signature verification package (pkg/integrity)

MEDIUM:
- W-1: Validate attestation is a real P-256 curve point, not raw attestation object
- W-3: Add origin validation to all WebAuthn flows (register, verify, trade approve)
- N-2: Remove plaintext TCP fallback from MPC node transport (TLS mandatory)
- K-1: Fail-closed on empty/whitespace orgID (prevents cross-tenant key leakage)
- A-1: Make AuditEntry immutable (Update/Delete return error)
- A-2: Add MPC-level signing audit log (wallet, message hash, intent, trigger)
- O-3: Invalidate backup shards after key reshare (stale shares are useless)
- O-2: Reject env/file password providers in production (require cloud HSM)

LOW:
- T-1: Add error handling + MarkSignFailed to signing goroutine
- T-2: Verify caller authorization in handleTradeSubmit
- K-2: Secret erasure stub now calls runtime.GC() instead of no-op
- N-1: Add VerifyConnection callback to reject peers without TLS certs

Tests: 69 unit + 7 fuzz targets, ~900K fuzz executions, 19/19 packages green.
Makefile: add -tags json1 for SQLite JSON function support in ORM tests.
2025-12-28 01:00:12 -08:00

63 lines
1.6 KiB
Go

package integrity
import (
"crypto/ed25519"
"crypto/rand"
"encoding/hex"
"os"
"path/filepath"
"testing"
)
func FuzzVerifyFile(f *testing.F) {
// Generate a real key pair for seeding
pub, priv, _ := ed25519.GenerateKey(rand.Reader)
f.Add([]byte("valid binary content"), []byte(hex.EncodeToString(ed25519.Sign(priv, []byte("valid binary content")))))
f.Add([]byte(""), []byte(""))
f.Add([]byte("content"), []byte("not-hex"))
f.Add([]byte("content"), []byte("deadbeef"))
f.Fuzz(func(t *testing.T, content []byte, sigBytes []byte) {
dir := t.TempDir()
binPath := filepath.Join(dir, "test-binary")
os.WriteFile(binPath, content, 0644)
os.WriteFile(binPath+".sig", sigBytes, 0644)
SetTrustedKeys([]string{hex.EncodeToString(pub)})
// Must not panic regardless of input
err := VerifyFile(binPath)
// If verification passes, the signature must actually be valid
if err == nil {
// Double-check: manually verify
sigHex := string(sigBytes)
sig, decErr := hex.DecodeString(sigHex)
if decErr != nil || len(sig) != ed25519.SignatureSize {
t.Fatal("verification passed but signature is malformed")
}
}
})
}
func FuzzSetTrustedKeys(f *testing.F) {
f.Add("deadbeef")
f.Add("")
f.Add("not-hex!")
pub, _, _ := ed25519.GenerateKey(rand.Reader)
f.Add(hex.EncodeToString(pub))
f.Fuzz(func(t *testing.T, keyHex string) {
// Must not panic
err := SetTrustedKeys([]string{keyHex})
if err == nil {
// Valid key: must be exactly 32 bytes
decoded, _ := hex.DecodeString(keyHex)
if len(decoded) != ed25519.PublicKeySize {
t.Fatalf("accepted key of length %d (expected %d)", len(decoded), ed25519.PublicKeySize)
}
}
})
}