# Sovereign Node Key — Production Authorization & Integrity This document explains what the Sovereign Node Key system is, what it proves, and how to use it safely. ## Overview A **Sovereign Node Key** is a production authorization credential consisting of: 1. **Node identity** — Ed25519 keypair uniquely identifying a provisioned node 2. **Authorization record** — Operator-signed proof that this node is authorized for protected operations 3. **Repository commitment** — SHA-256 hash of repository state at key generation time 4. **Prior-art timestamp** — Tamper-evident record of when this work existed 5. **Signer identity** — Public key for signature verification ## What It Proves ### Node Authorization (NEW) ✓ The PAX-Coder authority has provisioned and authorized this node ✓ The authorization is cryptographically bound to this node's public key ✓ The authorization is operator-signed and cannot be self-created ✓ Protected operations require a valid authorization record ✓ Unauthorized, revoked, or expired nodes are denied ### Integrity ✓ The repository has not been tampered with since the key was generated ✓ Every file's hash is recorded in `manifest.json` ✓ The manifest itself is committed in `prior_art.json` ### Timestamp ✓ This code existed at a specific UTC time ✓ The git commit hash is cryptographically tied to that moment ✓ The prior-art timestamp is tamper-evident (local or Bitcoin-anchored) ### Authenticity ✓ Outputs signed with this key were produced by the holder of `.node_sk` ✓ The public key (`node_pk.pem`) can verify any signature ✓ No one else can sign with this key (assuming the private key remains private) ### Non-Repudiation ✓ The signer cannot later deny having created the signature ✓ The signature proves possession of the private key at the time of signing ## What It Does NOT Prove (Alone) ### Node Authorization (Without Authorization Record) ✗ Node identity alone does not grant authorization ✗ A valid signature does not grant authorization ✗ Possession of a node key does not grant authorization **Authorization requires:** valid operator-signed authorization record + ACTIVE status + valid lifetime + non-revoked status ### Legal Ownership ✗ Does the signer own the work? ✗ Can the signer license it? ✗ Are there copyright claims? **Not embedded in the crypto.** Use separate legal instruments (licenses, trust deeds, copyright notices). ### Work Quality ✗ Is the code correct? ✗ Does it do what it claims? ✗ Is it actually proven? **Not proven by this system.** Use formal verification, testing, and code review. ### Blockchain Confirmation ✗ Is this anchored to Bitcoin? ✗ Is the timestamp immutable? ✗ Can this be reversed? **Not unless explicitly anchored.** The timestamp is local; see `prior_art.json` status for Bitcoin confirmation status. ## Security Properties ### Confidentiality - The private key MUST remain private - If compromised, all signatures are worthless - Rotate the key immediately if compromise is suspected ### Integrity - The public key is safe to share - The manifest and prior-art record must not be modified after commitment - Verification scripts detect tampering ### Authenticity - Only the private-key holder can create valid signatures - The public key proves who signed ### Accountability - The public key is permanently associated with all outputs - There is no anonymous signing ## Private Key Management ### Never Do This ✗ Commit `.node_sk` to git ✗ Upload `.node_sk` to GitHub ✗ Email or message the private key ✗ Store in plaintext in cloud storage ✗ Share the private key with anyone ✗ Use weak file permissions (must be 400) ✗ Keep the private key in a public directory ### Do This Instead ✓ Generate the key with `./generate_node_key.sh` ✓ File permissions are set to 400 automatically ✓ Keep in a secure local directory (e.g., `~/.pax-node-keys/`) ✓ Backup encrypted (e.g., to a YubiKey, hardware wallet, or encrypted USB) ✓ Rotate periodically (e.g., annually) ✓ Use environment variables when signing (never hardcode the key) Example secure usage: ```bash export PAX_NODE_KEY=$(cat ~/.pax-node-keys/node_sk | xxd -p | tr -d '\n') openssl dgst -sha256 -sign ~/.pax-node-keys/node_sk output.ptx unset PAX_NODE_KEY # Clear from environment after use ``` ## Verification Procedure ### For Your Own Outputs Verify that all cryptographic artifacts are consistent: ```bash cd sovereign ./verify_node_key.sh ``` Checks: - Public files exist and are valid JSON - Private key has correct permissions (400) - Git commit is in repository history - Repository commitment hash is correct - No private key material leaked to git ### For Someone Else's Outputs 1. **Get the public key** From their `node.json`: ```json "public_key_hex": "..." ``` 2. **Get the prior-art record** From their `prior_art.json`: ```json { "git_commit": "...", "repository_sha256": "...", "created_at_utc": "..." } ``` 3. **Verify the signature** ```bash openssl dgst -sha256 -verify <(echo "PUBLIC_KEY_HEX" | xxd -r -p) \ -signature output.sig output.ptx ``` 4. **Check the timestamp** The `created_at_utc` field is when they claimed the key was generated The `git_commit` is the repository state at that time Compare both to independent sources 5. **Spot-check the manifest** Pick a few files from `manifest.json` and verify: ```bash sha256sum file1 file2 file3 # Should match values in manifest ``` ## Trust Boundaries ### Trust Assumption: Private Key is Private If the private key is compromised, all signatures are worthless. The security model collapses. ### Trust Assumption: Public Key is Authentic If you receive the public key through an insecure channel, you cannot trust the signatures. Use a secure channel (e.g., GitHub, verified fingerprints, institutional databases). ### Trust Assumption: Git History is Honest The system assumes git commits are immutable. If the repository is force-pushed or the git history is rewritten, the timestamps are no longer reliable. ### Weaker Assumption: Clocks are Roughly Synchronized Timestamps are local UTC. No assumption is made about perfect clock accuracy; only that times are roughly correct. ## Attack Scenarios ### Scenario 1: Private Key Compromise **If someone steals the private key:** - They can sign fake outputs - All signatures become untrustworthy - Immediate rotation is required **Mitigation:** - Keep private key offline when not in use - Use hardware security modules (YubiKey, etc.) - Monitor signature usage for anomalies - Rotate the key if compromise is suspected ### Scenario 2: Repository Tampering **If git history is rewritten:** - Repository commitment hash no longer matches - `verify_node_key.sh` will detect the mismatch - The prior-art record is still valid (git commit hash is immutable once broadcast) **Mitigation:** - Repository should use branch protection and signing requirements - Keep clones as offline backups - Publish git commits to multiple sources (GitHub, git server, etc.) ### Scenario 3: Timestamp Forgery **If someone falsifies the timestamp:** - The `created_at_utc` field in `node.json` is under their control - Only verifiable via external sources (blockchain, timestamping service) - The git commit hash is the real proof (git commits are immutable once broadcast) **Mitigation:** - Anchor the prior-art record to Bitcoin or a timestamping service (see OpenTimestamps) - The unanchored timestamp is only as trustworthy as the git history - `status` field in `prior_art.json` indicates confirmation level ### Scenario 4: Man-in-the-Middle Attack **If someone intercepts the public key:** - You cannot trust signatures verified with the intercepted key - You may be verifying signatures from an attacker, not the real signer **Mitigation:** - Retrieve the public key from an authenticated source (GitHub, institutional database) - Verify fingerprints over multiple channels - Use HTTPS with certificate pinning - Compare public key fingerprints across independent sources ## Rotation ### When to Rotate - Annually (as part of security hygiene) - Immediately if compromise is suspected - When the key holder leaves the organization - After a security audit recommends rotation ### How to Rotate 1. Generate a new key: `./sovereign/generate_node_key_v2.sh` 2. Create a rotation record that includes: - Old node ID - New node ID - Reason for rotation - Timestamp - Signature by the old key (proving continuity) 3. Commit new key files + rotation record 4. Keep old private key in secure archive (do not delete) 5. Announce the rotation (e.g., update documentation) ### Rotation Record Example ```json { "old_node_id": "pax-coder-1234567890", "new_node_id": "pax-coder-1234567999", "old_public_key": "...", "new_public_key": "...", "rotation_timestamp": "2026-08-18T00:00:00Z", "reason": "scheduled annual rotation", "signed_by_old_key": "..." } ``` ## Disaster Recovery ### If Private Key is Lost 1. Create a key-loss record (signed by the new key) 2. Rotate to a new key 3. Document the loss (for audit trail) 4. Disable the old key if possible ### If Private Key is Stolen 1. Assume all signatures are compromised 2. Rotate immediately to a new key 3. Verify no unauthorized signatures exist 4. Publish a security notice 5. Update all dependent systems ### If Repository is Corrupted 1. Verify against a known-good clone 2. Check the git commit hash in prior-art records 3. If mismatch, investigate the corruption 4. Restore from backup if necessary ## CI/CD Integration Add these checks to your CI/CD pipeline: ### Secret Scanning ```yaml - name: Scan for private key material run: | if git grep -l "PRIVATE\|BEGIN.*KEY\|-----END" -- sovereign/ \ | grep -v "\.md\|\.txt"; then echo "ERROR: Private key material detected in tracked files" exit 1 fi ``` ### Integrity Verification ```yaml - name: Verify node key integrity run: | cd sovereign bash verify_node_key.sh ``` ### Manifest Validation ```yaml - name: Validate manifest JSON run: | jq . sovereign/manifest.json sovereign/node.json sovereign/verification.json ``` ### Permissions Check ```yaml - name: Ensure .node_sk is not tracked run: | if git ls-files | grep "\.node_sk"; then echo "ERROR: .node_sk should not be tracked by git" exit 1 fi ``` ## Questions & Answers **Q: Is this blockchain-based?** A: No. The timestamps are local. Optional: anchor to Bitcoin via OpenTimestamps for immutability. **Q: Can I use RSA instead of Ed25519?** A: Yes, but Ed25519 is smaller, faster, and more secure. RSA requires larger keys. **Q: What if multiple people have the same private key?** A: Don't share the private key. Generate separate keys for each person; they'll have different node IDs. **Q: Can I sign outputs retroactively?** A: Yes, but the signature will reflect the current date, not the date the code was written. **Q: What about privacy?** A: The node ID and public key are publicly visible. If you want to hide your identity, use a different node identity for different projects. **Q: Can I revoke a key?** A: Yes, through key rotation. Mark the old key as revoked in the rotation record. The old signatures remain valid (you can't revoke history). ## References - **Ed25519:** [EdDSA signature scheme](https://en.wikipedia.org/wiki/EdDSA) - **SHA-256:** [NIST FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf) - **OpenTimestamps:** [Timestamp with Bitcoin](https://opentimestamps.org/) - **GitHub Security:** [Commit signature verification](https://docs.github.com/en/authentication/managing-commit-signature-verification) --- **Last updated:** 2026-08-18 **System version:** 1.0.0 **License:** BSL-1.1 / AGPL-3.0 / MPL-2.0