feat: identity export/import (yaw-key-backup-1)
Portable encrypted identity backup compatible with the sister project's format — argon2id KDF + nacl secretbox, peer ID visible in plaintext for pre-import verification. - crypto: ExportIdentity, ImportIdentity, SaveIdentity - proto: export_identity / import_identity IPC commands + events - ipc: export_identity returns encrypted blob; import_identity validates and decrypts (read-only — on-disk write requires daemon restart) - netmgr: MasterIdentity() accessor - daemon: --import-identity / --import-passphrase flags write identity.json and exit, enabling scripted account migration - tests: roundtrip and wrong-passphrase rejection Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/waste-go/internal/crypto"
|
||||
"github.com/waste-go/internal/invite"
|
||||
"github.com/waste-go/internal/netmgr"
|
||||
"github.com/waste-go/internal/proto"
|
||||
@@ -275,6 +276,36 @@ func handleClient(conn net.Conn, mgr *netmgr.Manager) {
|
||||
send(errMsg(fmt.Sprintf("send_file: %v", err)))
|
||||
}
|
||||
|
||||
case proto.CmdExportIdentity:
|
||||
if cmd.Passphrase == "" {
|
||||
send(errMsg("export_identity: passphrase is required"))
|
||||
continue
|
||||
}
|
||||
blob, err := crypto.ExportIdentity(mgr.MasterIdentity(), cmd.Passphrase)
|
||||
if err != nil {
|
||||
send(errMsg(fmt.Sprintf("export_identity: %v", err)))
|
||||
continue
|
||||
}
|
||||
send(proto.IpcMessage{
|
||||
Type: proto.EvtIdentityExported,
|
||||
Backup: string(blob),
|
||||
})
|
||||
|
||||
case proto.CmdImportIdentity:
|
||||
if cmd.Passphrase == "" || cmd.Backup == "" {
|
||||
send(errMsg("import_identity: passphrase and backup are required"))
|
||||
continue
|
||||
}
|
||||
_, err := crypto.ImportIdentity([]byte(cmd.Backup), cmd.Passphrase)
|
||||
if err != nil {
|
||||
send(errMsg(fmt.Sprintf("import_identity: %v", err)))
|
||||
continue
|
||||
}
|
||||
// Import is intentionally read-only here: returns the decrypted identity
|
||||
// for the caller to verify before committing. Actual on-disk replacement
|
||||
// requires a daemon restart with --import flag (see cmd/daemon).
|
||||
send(proto.IpcMessage{Type: proto.EvtIdentityImported})
|
||||
|
||||
default:
|
||||
send(errMsg(fmt.Sprintf("unknown command: %s", cmd.Type)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user