UNPKG

polyv-live-cli

Version:

CLI tool for managing PolyV live streaming services.

207 lines 8.32 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultAccountEncryption = exports.AccountEncryptionImpl = void 0; exports.createAccountEncryption = createAccountEncryption; const crypto = __importStar(require("crypto")); const os = __importStar(require("os")); const ENCRYPTION_CONFIG = { algorithm: 'aes-256-gcm', keyLength: 32, ivLength: 16, authTagLength: 16, keyDerivationIterations: 100000, saltString: 'polyv-cli-security-salt-v1.0' }; class AccountEncryptionImpl { constructor(masterKey) { const keyInfo = this.resolveEncryptionKey(masterKey); this.encryptionKey = keyInfo.key; this.keySource = keyInfo.source; } resolveEncryptionKey(providedKey) { let keyString; let source; if (providedKey) { keyString = providedKey; source = 'environment'; } else if (process.env['POLYV_MASTER_KEY']) { keyString = process.env['POLYV_MASTER_KEY']; source = 'environment'; } else { keyString = this.generateDefaultKey(); source = 'generated'; } if (!this.validateKey(keyString)) { throw new Error('Invalid encryption key. Key must be at least 16 characters long and contain mixed case letters and numbers.'); } return { key: this.deriveEncryptionKey(keyString), source }; } generateDefaultKey() { let username = 'unknown'; try { const userInfo = os.userInfo(); username = userInfo && userInfo.username ? userInfo.username : 'unknown'; } catch { username = 'unknown'; } const machineInfo = { hostname: os.hostname(), platform: os.platform(), arch: os.arch(), homedir: os.homedir(), username }; const hash = crypto.createHash('sha256'); hash.update(JSON.stringify(machineInfo)); hash.update('polyv-cli-default-key-v1.0'); return hash.digest('hex'); } deriveEncryptionKey(masterKey) { const salt = Buffer.from(ENCRYPTION_CONFIG.saltString, 'utf8'); return crypto.pbkdf2Sync(masterKey, salt, ENCRYPTION_CONFIG.keyDerivationIterations, ENCRYPTION_CONFIG.keyLength, 'sha256'); } encrypt(plaintext) { try { const iv = crypto.randomBytes(ENCRYPTION_CONFIG.ivLength); const cipher = crypto.createCipheriv(ENCRYPTION_CONFIG.algorithm, this.encryptionKey, iv); let encrypted = cipher.update(plaintext, 'utf8'); encrypted = Buffer.concat([encrypted, cipher.final()]); const authTag = cipher.getAuthTag(); return { algorithm: ENCRYPTION_CONFIG.algorithm, iv: iv.toString('base64'), authTag: authTag.toString('base64'), encrypted: encrypted.toString('base64') }; } catch (error) { throw new Error(`Failed to encrypt account secret. Please check your encryption key and try again. ` + `Error: ${error instanceof Error ? error.message : 'Unknown encryption error'}`); } } decrypt(encryptedData) { try { if (encryptedData.algorithm !== ENCRYPTION_CONFIG.algorithm) { throw new Error(`Unsupported encryption algorithm: ${encryptedData.algorithm}. Expected: ${ENCRYPTION_CONFIG.algorithm}`); } const iv = Buffer.from(encryptedData.iv, 'base64'); const authTag = Buffer.from(encryptedData.authTag, 'base64'); const encrypted = Buffer.from(encryptedData.encrypted, 'base64'); const decipher = crypto.createDecipheriv(ENCRYPTION_CONFIG.algorithm, this.encryptionKey, iv); decipher.setAuthTag(authTag); let decrypted = decipher.update(encrypted); decrypted = Buffer.concat([decrypted, decipher.final()]); return decrypted.toString('utf8'); } catch (error) { if (error instanceof Error) { const errorMessage = error.message.toLowerCase(); if (errorMessage.includes('bad decrypt') || errorMessage.includes('unsupported state or unable to authenticate data') || errorMessage.includes('invalid authentication tag') || errorMessage.includes('authentication failed')) { throw new Error('Failed to decrypt account secret. This may be due to:\n' + '1. Incorrect encryption key (check POLYV_MASTER_KEY environment variable)\n' + '2. Corrupted configuration file\n' + '3. Configuration file created with different key\n\n' + 'Try: polyv-live-cli config recover'); } } throw new Error(`Failed to decrypt account secret: ${error instanceof Error ? error.message : 'Unknown decryption error'}\n\n` + 'Try: polyv-live-cli config recover'); } } generateKey() { const randomBytes = crypto.randomBytes(32); return randomBytes.toString('hex'); } validateKey(key) { if (!key || typeof key !== 'string') { return false; } if (key.length < 16) { return false; } const hasLowerCase = /[a-z]/.test(key); const hasUpperOrNumber = /[A-Z0-9]/.test(key); return hasLowerCase && hasUpperOrNumber; } testEncryption(testData = 'test-secret-data-2024') { try { const encrypted = this.encrypt(testData); const decrypted = this.decrypt(encrypted); return decrypted === testData; } catch { return false; } } getKeySource() { return this.keySource; } validateEncryptedData(encryptedData) { if (!encryptedData || typeof encryptedData !== 'object') { return false; } const data = encryptedData; return (data['algorithm'] === ENCRYPTION_CONFIG.algorithm && typeof data['iv'] === 'string' && typeof data['authTag'] === 'string' && typeof data['encrypted'] === 'string' && data['iv'].length > 0 && data['authTag'].length > 0 && data['encrypted'].length > 0); } getEncryptionMetadata() { return { algorithm: ENCRYPTION_CONFIG.algorithm, keySource: this.keySource, version: '1.0' }; } } exports.AccountEncryptionImpl = AccountEncryptionImpl; function createAccountEncryption(masterKey) { return new AccountEncryptionImpl(masterKey); } exports.defaultAccountEncryption = createAccountEncryption(); //# sourceMappingURL=account-encryption.js.map