v0.108.0: hub-verified escrow auto-confirm on current-password hash match (SLICE 3)
EscrowAutoConfirmer flips pending->escrowed ONLY when sha256(local repo password) matches the ACK's restic_pw_sha256 (blob-presence alone never confirms — red-proofed). Mismatch warns once per hash naming the ceremony; never un-confirms; wipes the staged secret on flip. Pinned cross-repo hash vector; manual confirm deprecated to a legacy-blob fallback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -3,6 +3,7 @@ package backup
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -188,6 +189,26 @@ func (m *Manager) ApplyOffsiteTarget(ctx context.Context, tgt *settings.OffboxTa
|
||||
return nil
|
||||
}
|
||||
|
||||
// HashResticPassword is the CANONICAL hasher for the offsite repo password (SLICE 3 hub-verified escrow
|
||||
// auto-confirm): sha256 hex of the TRIMMED password string — the SAME convention as the agent's
|
||||
// escrow.HashResticPassword (both sides TrimSpace their file reads; pinned by the SAME cross-repo test
|
||||
// vector in felhom-agent). The hash of a 256-bit random secret is non-reversible and non-brute-forceable —
|
||||
// safe to log/compare; the PASSWORD itself is never logged.
|
||||
func HashResticPassword(pw string) string {
|
||||
sum := sha256.Sum256([]byte(strings.TrimSpace(pw)))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
// OffboxRepoPasswordHash returns the canonical hash of the local repo password (false when no password
|
||||
// file exists — nothing to match; the auto-confirm check skips).
|
||||
func (m *Manager) OffboxRepoPasswordHash() (string, bool) {
|
||||
pw, err := os.ReadFile(m.offboxPwPath())
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
return HashResticPassword(string(pw)), true
|
||||
}
|
||||
|
||||
// PushOffboxPasswordForEscrow reads the 0600 repo password and hands it to `stage` (the agent push), so
|
||||
// the web/handler caller never sees the value — used by the enable flow to escrow-stage the offsite key.
|
||||
func (m *Manager) PushOffboxPasswordForEscrow(ctx context.Context, stage func(ctx context.Context, pw string) error) error {
|
||||
|
||||
Reference in New Issue
Block a user