mirror of
https://github.com/hanzoai/drive.git
synced 2026-10-30 18:38:28 +00:00
Replaces the deployment-identity stand-in. A master held by an HSM (luxfi/hsm
PasswordProvider: aws/gcp/azure/zymbit/yubihsm/pkcs11 in prod, env/file for dev)
is HKDF-derived to a wrap key; the deployment's ML-KEM-768+X25519 age identity is
ChaCha20-Poly1305-sealed under it at {DataDir}/identity.sealed. The master never
leaves the HSM; the PQ secret is never stored in clear; restore needs the HSM.
Provisioning is ML-DSA-attested (luxfi/hsm MLDSASigner).
mount.go: resolveIdentity uses the Custodian when DRIVE_HSM_PROVIDER is set.
Test proves: sealed (not plaintext) at rest, right master recovers the same
identity, wrong master rejected. Closes the #1 SOC 2 key-custody code gap.
Co-authored-by: Hanzo Dev <[email protected]>
53 lines
1.8 KiB
Go
53 lines
1.8 KiB
Go
package drive_test
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/hanzoai/drive"
|
|
"github.com/luxfi/age"
|
|
)
|
|
|
|
func idStr(t *testing.T, id age.Identity) string {
|
|
hi, ok := id.(*age.HybridIdentity)
|
|
if !ok { t.Fatalf("identity is %T, want *age.HybridIdentity", id) }
|
|
return hi.String()
|
|
}
|
|
|
|
func TestHSMRootedIdentityCustody(t *testing.T) {
|
|
ctx := context.Background()
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "identity.sealed")
|
|
os.Setenv("DRIVE_TEST_MASTER", "super-secret-hsm-master-0xfeed")
|
|
cfg := map[string]string{"env_var": "DRIVE_TEST_MASTER"}
|
|
|
|
c1, err := drive.NewCustodian("env", "drive-master", cfg)
|
|
if err != nil { t.Fatalf("custodian: %v", err) }
|
|
id1, r1, err := c1.LoadOrCreate(ctx, path)
|
|
if err != nil { t.Fatalf("load/create: %v", err) }
|
|
if id1 == nil || r1 == nil { t.Fatal("nil identity/recipient") }
|
|
|
|
// sealed blob exists and is NOT the raw key
|
|
sealed, err := os.ReadFile(path)
|
|
if err != nil { t.Fatalf("no sealed blob: %v", err) }
|
|
if string(sealed) == idStr(t, id1) || len(sealed) < 32 {
|
|
t.Fatal("identity not sealed (plaintext at rest)")
|
|
}
|
|
|
|
// same HSM master → recovers the SAME identity (durable restore via HSM)
|
|
c2, _ := drive.NewCustodian("env", "drive-master", cfg)
|
|
id2, _, err := c2.LoadOrCreate(ctx, path)
|
|
if err != nil { t.Fatalf("reopen: %v", err) }
|
|
if idStr(t, id1) != idStr(t, id2) { t.Fatal("HSM master did not recover the same identity") }
|
|
|
|
// WRONG master → cannot unseal (custody enforced by the HSM root)
|
|
os.Setenv("DRIVE_TEST_MASTER", "attacker-guess")
|
|
c3, _ := drive.NewCustodian("env", "drive-master", cfg)
|
|
if _, _, err := c3.LoadOrCreate(ctx, path); err == nil {
|
|
t.Fatal("wrong HSM master opened the identity — custody NOT enforced")
|
|
}
|
|
t.Log("HSM-rooted custody: identity sealed under HSM master, recovered with right master, rejected with wrong (CC6.1)")
|
|
}
|