File size: 12,395 Bytes
ef6eb55 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | # 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
|