mirror of
https://github.com/luxfi/mpc.git
synced 2026-09-24 00:26:24 +00:00
Fixes all findings from the Blue Team defensive security review of the redacted → redacted 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.
105 lines
2.5 KiB
Go
105 lines
2.5 KiB
Go
package integrity
|
|
|
|
import (
|
|
"crypto/ed25519"
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestVerifyFile_ValidSignature(t *testing.T) {
|
|
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
dir := t.TempDir()
|
|
binPath := filepath.Join(dir, "mpcd")
|
|
content := []byte("binary-content-here")
|
|
if err := os.WriteFile(binPath, content, 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := SignFile(binPath, priv); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := SetTrustedKeys([]string{hex.EncodeToString(pub)}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := VerifyFile(binPath); err != nil {
|
|
t.Fatalf("valid signature rejected: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestVerifyFile_TamperedBinary(t *testing.T) {
|
|
pub, priv, _ := ed25519.GenerateKey(rand.Reader)
|
|
dir := t.TempDir()
|
|
binPath := filepath.Join(dir, "mpcd")
|
|
|
|
os.WriteFile(binPath, []byte("original"), 0644)
|
|
SignFile(binPath, priv)
|
|
|
|
// Tamper with the binary after signing
|
|
os.WriteFile(binPath, []byte("tampered"), 0644)
|
|
|
|
SetTrustedKeys([]string{hex.EncodeToString(pub)})
|
|
if err := VerifyFile(binPath); err == nil {
|
|
t.Fatal("tampered binary was accepted — O-1 regression")
|
|
}
|
|
}
|
|
|
|
func TestVerifyFile_WrongKey(t *testing.T) {
|
|
_, priv1, _ := ed25519.GenerateKey(rand.Reader)
|
|
pub2, _, _ := ed25519.GenerateKey(rand.Reader)
|
|
dir := t.TempDir()
|
|
binPath := filepath.Join(dir, "mpcd")
|
|
|
|
os.WriteFile(binPath, []byte("content"), 0644)
|
|
SignFile(binPath, priv1)
|
|
|
|
// Trust only key2, but signed with key1
|
|
SetTrustedKeys([]string{hex.EncodeToString(pub2)})
|
|
if err := VerifyFile(binPath); err == nil {
|
|
t.Fatal("signature from untrusted key was accepted")
|
|
}
|
|
}
|
|
|
|
func TestVerifyFile_NoSignatureFile(t *testing.T) {
|
|
pub, _, _ := ed25519.GenerateKey(rand.Reader)
|
|
dir := t.TempDir()
|
|
binPath := filepath.Join(dir, "mpcd")
|
|
os.WriteFile(binPath, []byte("content"), 0644)
|
|
|
|
SetTrustedKeys([]string{hex.EncodeToString(pub)})
|
|
if err := VerifyFile(binPath); err == nil {
|
|
t.Fatal("missing .sig file was not detected")
|
|
}
|
|
}
|
|
|
|
func TestVerifyFile_NoTrustedKeys(t *testing.T) {
|
|
TrustedSigningKeys = nil
|
|
if err := VerifyFile("/nonexistent"); err == nil {
|
|
t.Fatal("no trusted keys should fail")
|
|
}
|
|
}
|
|
|
|
func TestHashFile(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "test")
|
|
content := []byte("test-content")
|
|
os.WriteFile(path, content, 0644)
|
|
|
|
got, err := HashFile(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := sha256.Sum256(content)
|
|
if got != hex.EncodeToString(expected[:]) {
|
|
t.Fatalf("hash mismatch: got %s", got)
|
|
}
|
|
}
|