Add MEK rotation, per-engine DEKs, and v2 ciphertext format (audit #6, #22)

Implement a two-level key hierarchy: the MEK now wraps per-engine DEKs
stored in a new barrier_keys table, rather than encrypting all barrier
entries directly. A v2 ciphertext format (0x02) embeds the key ID so the
barrier can resolve which DEK to use on decryption. v1 ciphertext remains
supported for backward compatibility.

Key changes:
- crypto: EncryptV2/DecryptV2/ExtractKeyID for v2 ciphertext with key IDs
- barrier: key registry (CreateKey, RotateKey, ListKeys, MigrateToV2, ReWrapKeys)
- seal: RotateMEK re-wraps DEKs without re-encrypting data
- engine: Mount auto-creates per-engine DEK
- REST + gRPC: barrier/keys, barrier/rotate-mek, barrier/rotate-key, barrier/migrate
- proto: BarrierService (v1 + v2) with ListKeys, RotateMEK, RotateKey, Migrate
- db: migration v2 adds barrier_keys table

Also includes: security audit report, CSRF protection, engine design specs
(sshca, transit, user), path-bound AAD migration tool, policy engine
enhancements, and ARCHITECTURE.md updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-16 18:27:44 -07:00
parent ac4577f778
commit 64d921827e
44 changed files with 5184 additions and 90 deletions

View File

@@ -20,7 +20,7 @@ func TestOpenAndMigrate(t *testing.T) {
}
// Verify tables exist.
tables := []string{"seal_config", "barrier_entries", "schema_migrations"}
tables := []string{"seal_config", "barrier_entries", "schema_migrations", "barrier_keys"}
for _, table := range tables {
var name string
err := database.QueryRow(
@@ -38,7 +38,7 @@ func TestOpenAndMigrate(t *testing.T) {
// Check migration version.
var version int
_ = database.QueryRow("SELECT MAX(version) FROM schema_migrations").Scan(&version)
if version != 1 {
t.Errorf("migration version: got %d, want 1", version)
if version != 2 {
t.Errorf("migration version: got %d, want 2", version)
}
}

View File

@@ -30,6 +30,15 @@ var migrations = []string{
version INTEGER PRIMARY KEY,
applied_at DATETIME NOT NULL DEFAULT (datetime('now'))
);`,
// Version 2: barrier key registry for per-engine DEKs
`CREATE TABLE IF NOT EXISTS barrier_keys (
key_id TEXT PRIMARY KEY,
version INTEGER NOT NULL DEFAULT 1,
encrypted_dek BLOB NOT NULL,
created_at DATETIME NOT NULL DEFAULT (datetime('now')),
rotated_at DATETIME NOT NULL DEFAULT (datetime('now'))
);`,
}
// Migrate applies all pending migrations.