# 🛡️ RANGERBLOCK SECURITY INTEGRATION PLAN v2.0 ## Project Codename: "SHEPHERD PROTOCOL" ### Unified Identity, Registration & App Sync System --- ## REVISION NOTES (v2.0) - Added: ranger-chat-lite ↔ RangerPlex bidirectional sync - Added: On-chain identity registration - Added: Settings migration (lite → full app) - Added: First-app security considerations (comprehensive) - Added: Missing security layers David didn't know to ask for --- ## 1. EXECUTIVE SUMMARY ### The Vision ``` User Journey Option A (Chat First): ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Downloads │────>│ Identity │────>│ Later adds │ │ Chat Lite │ │ Created + │ │ RangerPlex │ │ (free/easy) │ │ On-Chain │ │ (full app) │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ └────────────────────┘ SEAMLESS SYNC! (settings, history, keys) User Journey Option B (RangerPlex First): ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Downloads │────>│ Full │────>│ Chat Lite │ │ RangerPlex │ │ Identity │ │ auto-links │ │ (power user)│ │ On-Chain │ │ to existing │ └─────────────┘ └─────────────┘ └─────────────┘ ``` ### Key Principles 1. **Identity is PORTABLE** - One identity, all apps 2. **Blockchain is TRUTH** - On-chain registration = verified 3. **Local is FALLBACK** - Works offline, syncs when connected 4. **Upgrade is SEAMLESS** - Lite → Full with zero friction 5. **Security is INVISIBLE** - Users don't see complexity --- ## 2. ON-CHAIN IDENTITY REGISTRATION ### Why On-Chain? - **Proof of existence** - Timestamp when identity created - **Immutable record** - Can't be faked retroactively - **Cross-app verification** - Any app can verify identity - **Recovery mechanism** - Blockchain = backup ### Identity Block Structure ```javascript { type: 'IDENTITY_REGISTRATION', version: '1.0.0', payload: { // Public data (visible on chain) publicKey: 'RSA-2048 public key (PEM)', hardwareIdHash: 'SHA-256 of hardware ID (not raw ID!)', nickname: 'IrishRanger', appOrigin: 'ranger-chat-lite', // Which app created this capabilities: ['chat', 'voice', 'files'], // Timestamps createdAt: '2024-12-03T12:00:00.000Z', registeredOnChain: '2024-12-03T12:00:05.000Z', // Signature signature: 'self-signed with private key' }, metadata: { blockHeight: 12345, previousHash: 'abc123...', nonce: 42 } } ``` ### Registration Flow ``` ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ CLIENT │ │ RELAY/HUB │ │ BLOCKCHAIN │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ │ 1. Generate identity │ │ │ locally first │ │ │ │ │ │ 2. Connect to relay │ │ ├───────────────────────>│ │ │ │ │ │ 3. Submit identity │ │ │ registration block │ │ ├───────────────────────>│ │ │ │ │ │ │ 4. Validate & mine │ │ ├───────────────────────>│ │ │ │ │ │ 5. Block confirmed │ │ │<───────────────────────┤ │ │ │ │ 6. Registration │ │ │ confirmed + block # │ │ │<───────────────────────┤ │ │ │ │ │ 7. Store block # as │ │ │ proof of identity │ │ │ │ │ ``` --- ## 3. APP SYNC ARCHITECTURE ### Shared Identity Storage **Location**: `~/.rangerblock/` (cross-app shared folder) ``` ~/.rangerblock/ ├── identity/ │ ├── master_identity.json # THE identity (shared) │ ├── hardware_fingerprint.json # Device binding │ ├── chain_registration.json # On-chain proof │ └── sync_state.json # Last sync timestamp │ ├── keys/ │ ├── master_private_key.pem # RSA-2048 (NEVER leaves device) │ ├── master_public_key.pem # Shared with network │ └── session_keys/ # Per-session encryption keys │ ├── apps/ │ ├── ranger-chat-lite/ │ │ ├── settings.json # App-specific settings │ │ ├── chat_history.json # Message history │ │ └── contacts.json # Saved contacts │ │ │ └── rangerplex/ │ ├── settings.json │ ├── modules.json # Enabled modules │ └── workspace.json # UI state │ ├── sync/ │ ├── pending_sync.json # Changes to sync │ ├── conflict_log.json # Sync conflicts │ └── last_sync.json # Sync metadata │ └── security/ ├── trusted_devices.json # Other devices with same identity ├── revocation_list.json # Compromised keys └── audit_log.json # Security events ``` ### App Detection & Sync ```javascript // When ranger-chat-lite starts: class AppSyncManager { async detectRangerPlex() { const paths = [ '~/.rangerplex', // Linux/macOS '~/Library/Application Support/RangerPlex', // macOS '%APPDATA%/RangerPlex' // Windows ]; for (const path of paths) { if (await fs.exists(path)) { return { installed: true, path }; } } return { installed: false }; } async syncWithRangerPlex() { const rangerplex = await this.detectRangerPlex(); if (rangerplex.installed) { // RangerPlex exists - sync to shared identity await this.mergeIdentities(); await this.syncSettings(); await this.notifyUser('Synced with RangerPlex!'); } else { // First app - create shared identity await this.createSharedIdentity(); } } } ``` ### Settings Migration (Lite → Full) ```javascript // When RangerPlex detects existing Chat Lite identity: async function migrateFromChatLite() { const chatLiteData = await loadChatLiteData(); if (chatLiteData) { // Import user's existing identity await importIdentity(chatLiteData.identity); // Import chat history await importChatHistory(chatLiteData.messages); // Import contacts await importContacts(chatLiteData.contacts); // Import preferences await importPreferences(chatLiteData.settings); // Notify user showWelcome(` Welcome to RangerPlex! We found your Chat Lite identity: • Username: ${chatLiteData.identity.nickname} • Messages: ${chatLiteData.messages.length} • Contacts: ${chatLiteData.contacts.length} Everything has been imported automatically! `); } } ``` --- ## 4. SECURITY CONSIDERATIONS (FIRST APP CHECKLIST) ### Things You Didn't Know to Ask For: #### A. Input Validation (CRITICAL) ```javascript // NEVER trust user input! function sanitizeNickname(input) { // Remove dangerous characters const clean = input .replace(/[<>\"\'\\\/]/g, '') // No HTML/script injection .replace(/[\x00-\x1F]/g, '') // No control characters .trim() .substring(0, 32); // Max length // Check against banned patterns const banned = ['admin', 'system', 'ranger', 'commander']; if (banned.some(b => clean.toLowerCase().includes(b))) { throw new Error('Reserved nickname'); } return clean; } // Validate ALL WebSocket messages function validateMessage(data) { try { const msg = JSON.parse(data); // Check required fields if (!msg.type || typeof msg.type !== 'string') { throw new Error('Invalid message type'); } // Check payload size (prevent DoS) if (JSON.stringify(msg).length > 65536) { throw new Error('Message too large'); } // Check for injection attempts if (containsInjection(msg)) { throw new Error('Injection detected'); } return msg; } catch (e) { logSecurityEvent('INVALID_MESSAGE', { error: e.message, data }); return null; } } ``` #### B. Rate Limiting (PREVENTS ABUSE) ```javascript class RateLimiter { constructor() { this.limits = { messages: { max: 10, window: 10000 }, // 10 msgs per 10s connections: { max: 3, window: 60000 }, // 3 connects per min registrations: { max: 1, window: 86400000 } // 1 reg per day per IP }; this.counters = new Map(); } check(type, identifier) { const key = `${type}:${identifier}`; const now = Date.now(); const limit = this.limits[type]; if (!this.counters.has(key)) { this.counters.set(key, []); } const timestamps = this.counters.get(key) .filter(t => now - t < limit.window); if (timestamps.length >= limit.max) { return { allowed: false, retryAfter: limit.window - (now - timestamps[0]) }; } timestamps.push(now); this.counters.set(key, timestamps); return { allowed: true }; } } ``` #### C. Secure Key Storage (DON'T STORE PLAIN!) ```javascript const crypto = require('crypto'); const os = require('os'); class SecureKeyStorage { // Derive encryption key from hardware + user password deriveStorageKey(password) { const hardwareId = this.getHardwareId(); const salt = crypto.createHash('sha256') .update(hardwareId + os.userInfo().username) .digest(); return crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256'); } // Encrypt private key before storage encryptPrivateKey(privateKeyPem, password) { const key = this.deriveStorageKey(password); const iv = crypto.randomBytes(16); const cipher = crypto.createCipheriv('aes-256-gcm', key, iv); let encrypted = cipher.update(privateKeyPem, 'utf8', 'base64'); encrypted += cipher.final('base64'); return { encrypted, iv: iv.toString('base64'), authTag: cipher.getAuthTag().toString('base64') }; } // Decrypt on use decryptPrivateKey(encryptedData, password) { const key = this.deriveStorageKey(password); const decipher = crypto.createDecipheriv( 'aes-256-gcm', key, Buffer.from(encryptedData.iv, 'base64') ); decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'base64')); let decrypted = decipher.update(encryptedData.encrypted, 'base64', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; } } ``` #### D. Session Security ```javascript class SessionManager { generateSessionToken(userId, hardwareId) { const payload = { userId, hardwareId, issuedAt: Date.now(), expiresAt: Date.now() + (24 * 60 * 60 * 1000), // 24 hours nonce: crypto.randomBytes(16).toString('hex') }; // Sign the token const signature = this.sign(JSON.stringify(payload)); return Buffer.from(JSON.stringify({ payload, signature })) .toString('base64'); } validateSessionToken(token, expectedHardwareId) { try { const { payload, signature } = JSON.parse( Buffer.from(token, 'base64').toString() ); // Check expiry if (Date.now() > payload.expiresAt) { return { valid: false, reason: 'expired' }; } // Check hardware binding if (payload.hardwareId !== expectedHardwareId) { return { valid: false, reason: 'hardware_mismatch' }; } // Verify signature if (!this.verify(JSON.stringify(payload), signature)) { return { valid: false, reason: 'invalid_signature' }; } return { valid: true, payload }; } catch (e) { return { valid: false, reason: 'malformed' }; } } } ``` #### E. Audit Logging (LEGAL PROTECTION) ```javascript class AuditLogger { constructor(dbPath) { this.db = new Database(dbPath); this.initSchema(); } log(event) { const entry = { timestamp: new Date().toISOString(), eventType: event.type, userId: event.userId || null, hardwareId: event.hardwareId || null, ipAddress: event.ip || null, action: event.action, details: JSON.stringify(event.details || {}), severity: event.severity || 'INFO' }; this.db.insert('audit_log', entry); // Alert Commander for high severity if (event.severity === 'CRITICAL') { this.alertCommander(entry); } } // Required events to log: // - User registration // - Login attempts (success/fail) // - Message sends (metadata only, not content!) // - File transfers (metadata) // - Admin actions // - Kill switch triggers // - Suspicious activity } ``` #### F. Error Handling (DON'T LEAK INFO) ```javascript // BAD - leaks internal details app.use((err, req, res, next) => { res.status(500).json({ error: err.message, stack: err.stack, // NEVER expose stack trace! query: req.query // NEVER echo back user input! }); }); // GOOD - generic errors app.use((err, req, res, next) => { const errorId = crypto.randomBytes(8).toString('hex'); // Log full error internally logger.error({ errorId, error: err.message, stack: err.stack, request: sanitize(req) }); // Return generic message to user res.status(500).json({ error: 'An error occurred', errorId: errorId, // User can report this ID support: 'Contact support with this error ID' }); }); ``` #### G. Content Security (PREVENT ABUSE) ```javascript class ContentFilter { constructor() { // Load filters this.illegalPatterns = [ /(?:^|\s)csam(?:\s|$)/i, // Child abuse material /(?:^|\s)bomb(?:\s+making)?(?:\s|$)/i, // etc - comprehensive list ]; this.spamPatterns = [ /(.)\1{10,}/, // Repeated characters /(https?:\/\/[^\s]+\s*){5,}/, // Too many URLs ]; } check(content) { // Check for illegal content for (const pattern of this.illegalPatterns) { if (pattern.test(content)) { return { allowed: false, reason: 'ILLEGAL_CONTENT', action: 'BLOCK_AND_REPORT' }; } } // Check for spam for (const pattern of this.spamPatterns) { if (pattern.test(content)) { return { allowed: false, reason: 'SPAM_DETECTED', action: 'BLOCK' }; } } return { allowed: true }; } } ``` #### H. TLS/WSS Configuration (ENCRYPT IN TRANSIT) ```javascript const https = require('https'); const fs = require('fs'); // For production - use proper certificates! const server = https.createServer({ key: fs.readFileSync('server-key.pem'), cert: fs.readFileSync('server-cert.pem'), // Security settings minVersion: 'TLSv1.2', // Minimum TLS version ciphers: [ 'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-ECDSA-AES256-GCM-SHA384', 'ECDHE-RSA-AES256-GCM-SHA384' ].join(':'), honorCipherOrder: true }); // WebSocket over TLS const wss = new WebSocket.Server({ server }); ``` --- ## 5. IMPLEMENTATION PHASES (REVISED) ### Phase 1: Shared Identity Library (THIS WEEK) **Files to Create**: ``` /rangerblock/lib/ ├── identity-service.cjs # Core identity (ported from TS) ├── crypto-utils.cjs # RSA, signing, encryption ├── storage-utils.cjs # Cross-platform storage ├── hardware-id.cjs # Hardware fingerprinting ├── sync-manager.cjs # App sync logic └── chain-registration.cjs # On-chain identity ``` ### Phase 2: Update ranger-chat-lite - Move identity to `~/.rangerblock/` - Add RangerPlex detection - Add on-chain registration - Enable RSA signing ### Phase 3: Auth Server + Just-Chat Updates - Build server-only/auth-server.cjs - Update blockchain-chat.cjs - Update voice-chat.cjs ### Phase 4: Kill Switch Integration - Add Rain Protocol listeners - Add Commander verification - Test shutdown procedures ### Phase 5: RangerPlex Integration - Detect Chat Lite identity - Migrate settings - Unified dashboard --- ## 6. QUICK REFERENCE ### App Paths | App | Identity Location | |-----|-------------------| | ranger-chat-lite | `~/.rangerblock/` (shared) | | RangerPlex | `~/.rangerblock/` (shared) | | blockchain-chat.cjs | `~/.rangerblock/` (shared) | | voice-chat.cjs | `~/.rangerblock/` (shared) | ### API Methods | Method | Purpose | |--------|---------| | `getOrCreateIdentity()` | Get or create shared identity | | `registerOnChain()` | Register identity on blockchain | | `syncWithApps()` | Sync settings across apps | | `validateIdentity()` | Verify identity is valid | | `migrateFromApp()` | Import from other app | --- ## 7. SUMMARY OF CHANGES (v2.0) 1. **On-Chain Registration**: Every identity gets registered on the blockchain 2. **App Sync**: ranger-chat-lite ↔ RangerPlex automatic sync 3. **Settings Migration**: Seamless upgrade from Lite to Full 4. **Shared Storage**: `~/.rangerblock/` used by ALL apps 5. **Security Additions**: - Input validation - Rate limiting - Encrypted key storage - Session security - Audit logging - Error handling (no info leaks) - Content filtering - TLS/WSS configuration --- **Document Classification**: COMMANDER EYES ONLY **Version**: 2.0 **Created**: December 3, 2024 **Author**: Ranger (AIR9cd99c4515aeb3f6) **For**: David Keane (IR240474) 🎖️ Rangers lead the way!