-
Notifications
You must be signed in to change notification settings - Fork 0
State Persistence - File I/O and keypair generation #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
State Persistence - File I/O and keypair generation #37
Conversation
Part 3 of the Foundation stage for objects-node daemon. ## Changes Adds state type definitions for persistent node state: - NodeState - Persistent state with node keypair and optional identity - Uses SecretKey from objects-transport (Iroh Ed25519 key) - Optional IdentityInfo for registered OBJECTS identities - IdentityInfo - RFC-001 identity linking: - Identity ID (obj_ + base58 hash) - Registered handle - 8-byte nonce for ID derivation - Signer type (Passkey or Wallet) ## Security Comprehensive documentation on security requirements: - State files must use 600 permissions (owner read/write only) - Node key must be kept secure and never committed to version control - Supports anonymous mode (no identity) for nodes that don't publish assets ## Testing - Serialization round-trip tests - Identity persistence tests - Both Passkey and Wallet signer types validated Part of the Foundation stage (3/4). Builds on: #35. Next: State Persistence (#37). Pull Request: #40
500bcd3 to
0891b8f
Compare
0891b8f to
dd27ab9
Compare
2fcb887 to
4daee81
Compare
Code ReviewSecurity Issue: TOCTOU Race Condition in File PermissionsLocation: Issue: The file containing the private key is written using According to Rust's documentation for Suggested fix: use std::os::unix::fs::OpenOptionsExt;
use std::io::Write;
let contents = serde_json::to_string_pretty(self)?;
let mut file = std::fs::OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.mode(0o600) // Set permissions atomically at creation
.open(path)?;
file.write_all(contents.as_bytes())?;This eliminates the race window entirely by setting permissions atomically when the file is created. |
dd27ab9 to
ff4a6dc
Compare
399db79 to
6650f30
Compare
cd3fc68 to
5f315cd
Compare
6650f30 to
531e040
Compare
Code ReviewFound 1 security issue that needs to be addressed. See inline comment on bins/objects-node/src/state.rs for details about a race condition that exposes the private key during file creation. |
|
Test comment - checking inline comment capability |
Inline Comment for bins/objects-node/src/state.rs:104Security Issue: Race condition exposes private key The Problem: See: protocol/bins/objects-node/src/state.rs Lines 103 to 114 in 5f315cd
Fix: Use
This ensures the file is created with |
Code Review SummaryIssues Found: 1 I reviewed this PR for bugs and CLAUDE.md compliance and found 1 high-severity security issue: Security Issue - Race Condition in File PermissionsLocation: The CLAUDE.md Compliance: ✓ No violations found |
531e040 to
2376222
Compare
5f315cd to
c2da686
Compare
b5896a6 to
9857c26
Compare
Part 4 of the Foundation stage for objects-node daemon. ## Changes Implements state persistence with secure file I/O: - StateError enum with proper error handling (IO, Parse, Permission errors) - load_or_create() - Load from file or generate new keypair if missing - load() and save() - JSON file I/O with secure permissions - generate_new() - Cryptographically secure keypair generation using rand::rng() - ensure_permissions() - Parent directory creation and validation - set_secure_permissions() - Unix file permission enforcement (600) with verification ## Security - State files created with 600 permissions (owner read/write only) - Permissions verified after setting (prevents silent failures on NFS/FUSE) - File deleted if permission verification fails (prevents key exposure) - Non-Unix platforms: warning logged (users notified keys not protected) - Parent directories created recursively as needed - Validation prevents writing to invalid paths - Uses cryptographically secure random number generation ## Encapsulation - NodeState fields are private with accessor methods - Prevents external code from bypassing validation - IdentityInfo fields remain private with getters ## Observability - Tracing instrumentation on load(), save(), load_or_create() - Logging at key decision points (file creation, permission setting) ## Race Condition Fixes - Use create_new() for atomic file creation in load_or_create() - Prevents TOCTOU where multiple processes create state simultaneously ## Testing Comprehensive test coverage (19 tests): - File creation and loading - Round-trip serialization with and without identity - Unix file permission verification (600) - Permission restoration (fixes wrong permissions on save) - Parent directory creation - Error cases: missing files, corrupted JSON, empty files, invalid paths - Validates uses IdentityId and Handle types (not raw strings) ## Dependencies - Added rand to main dependencies for secure key generation - Removed duplicate rand from dev-dependencies
c2da686 to
387f081
Compare
- Implement atomic write pattern (temp-file-then-rename) in save() - Fix silent file deletion failure with proper error logging - Add race condition permission verification in load_or_create() - Upgrade Windows security warning from WARN to ERROR level - Add missing error context logging for load failures - Add tests: idempotency, permissions on create, identity persistence - Update documentation for permission timing and behavior
Part 4 of the Foundation stage for objects-node daemon.
Changes
Implements state persistence with secure file I/O:
StateErrorenum with proper error handling (IO, Parse, Permission errors)load_or_create()- Load from file or generate new keypair if missingload()andsave()- JSON file I/O with secure permissionsgenerate_new()- Cryptographically secure keypair generation usingrand::rng()ensure_permissions()- Parent directory creation and validationSecurity
Testing
Comprehensive test coverage:
Dependencies
randto main dependencies for secure key generationPart of the Foundation stage (4/4). Builds on: #51.
Foundation stage complete! Config and state management fully implemented with 22 passing tests.