Encryption & Security Utilities
Overview
PadawanForge implements a comprehensive encryption and security system that provides secure data handling, token encryption, and cryptographic utilities. This system ensures sensitive data is properly protected throughout the application.
Architecture
Core Components
- EncryptionService: Centralized encryption/decryption utilities
- Token Encryption: Secure storage of API keys and tokens
- Algorithm Support: XOR and AES encryption methods
- Encoding Options: Base64 and hex encoding support
- Security Validation: Input sanitization and validation
Security Features
- Algorithm Flexibility: Support for multiple encryption algorithms
- Encoding Options: Multiple output encoding formats
- Error Handling: Graceful failure handling
- Development Safety: Fallback mechanisms for development environments
Implementation
EncryptionService Class
import { EncryptionService } from '@/lib/utils/encryption';
// Create encryption service with configuration
const encryptionService = new EncryptionService({
key: 'your-secret-key',
algorithm: 'xor', // or 'aes'
encoding: 'base64' // or 'hex'
});
// Encrypt sensitive data
const encrypted = encryptionService.encrypt('sensitive-data');
// Decrypt data
const decrypted = encryptionService.decrypt(encrypted);
Configuration Options
interface EncryptionConfig {
key: string; // Encryption key
algorithm?: 'xor' | 'aes'; // Encryption algorithm
encoding?: 'base64' | 'hex'; // Output encoding
}
Simple Encryption Utilities
import { simpleEncrypt, simpleDecrypt } from '@/lib/utils/encryption';
// Quick encryption for simple use cases
const encrypted = simpleEncrypt('data-to-encrypt');
const decrypted = simpleDecrypt(encrypted);
Usage Examples
API Token Encryption
import { EncryptionService } from '@/lib/utils/encryption';
class TokenManager {
private encryptionService: EncryptionService;
constructor(secretKey: string) {
this.encryptionService = new EncryptionService({
key: secretKey,
algorithm: 'xor',
encoding: 'base64'
});
}
// Encrypt API token for storage
encryptToken(token: string): string {
return this.encryptionService.encrypt(token);
}
// Decrypt API token for use
decryptToken(encryptedToken: string): string {
return this.encryptionService.decrypt(encryptedToken);
}
// Store encrypted token
async storeToken(userId: string, token: string): Promise<void> {
const encryptedToken = this.encryptToken(token);
await db.prepare(`
INSERT INTO user_tokens (user_id, encrypted_token, created_at)
VALUES (?, ?, CURRENT_TIMESTAMP)
`).bind(userId, encryptedToken).run();
}
// Retrieve and decrypt token
async getToken(userId: string): Promise<string | null> {
const result = await db.prepare(`
SELECT encrypted_token FROM user_tokens
WHERE user_id = ? AND active = true
`).bind(userId).first();
if (!result) return null;
return this.decryptToken(result.encrypted_token);
}
}
Bot Token Security
import { EncryptionService } from '@/lib/utils/encryption';
class BotTokenService {
private encryptionService: EncryptionService;
constructor() {
this.encryptionService = new EncryptionService({
key: process.env.BOT_TOKEN_ENCRYPTION_KEY || 'default-key',
algorithm: 'xor',
encoding: 'base64'
});
}
// Encrypt bot token before storing
private encryptToken(token: string): string {
return this.encryptionService.encrypt(token);
}
// Decrypt bot token for API calls
private decryptToken(encryptedToken: string): string {
return this.encryptionService.decrypt(encryptedToken);
}
// Store bot token securely
async storeBotToken(platform: string, token: string): Promise<void> {
const encryptedToken = this.encryptToken(token);
await db.prepare(`
INSERT INTO bot_tokens (platform, encrypted_token, created_at)
VALUES (?, ?, CURRENT_TIMESTAMP)
`).bind(platform, encryptedToken).run();
}
// Retrieve bot token for API calls
async getBotToken(platform: string): Promise<string | null> {
const result = await db.prepare(`
SELECT encrypted_token FROM bot_tokens
WHERE platform = ? AND active = true
`).bind(platform).first();
if (!result) return null;
return this.decryptToken(result.encrypted_token);
}
}
Configuration Encryption
import { EncryptionService } from '@/lib/utils/encryption';
class ConfigManager {
private encryptionService: EncryptionService;
constructor() {
this.encryptionService = new EncryptionService({
key: process.env.CONFIG_ENCRYPTION_KEY || 'config-key',
algorithm: 'xor',
encoding: 'base64'
});
}
// Encrypt sensitive configuration
encryptConfig(config: Record<string, any>): string {
const configString = JSON.stringify(config);
return this.encryptionService.encrypt(configString);
}
// Decrypt configuration
decryptConfig(encryptedConfig: string): Record<string, any> {
const decrypted = this.encryptionService.decrypt(encryptedConfig);
return JSON.parse(decrypted);
}
// Store encrypted configuration
async storeConfig(key: string, config: Record<string, any>): Promise<void> {
const encryptedConfig = this.encryptConfig(config);
await db.prepare(`
INSERT OR REPLACE INTO configurations (config_key, encrypted_value, updated_at)
VALUES (?, ?, CURRENT_TIMESTAMP)
`).bind(key, encryptedConfig).run();
}
// Retrieve and decrypt configuration
async getConfig(key: string): Promise<Record<string, any> | null> {
const result = await db.prepare(`
SELECT encrypted_value FROM configurations WHERE config_key = ?
`).bind(key).first();
if (!result) return null;
return this.decryptConfig(result.encrypted_value);
}
}
Security Best Practices
1. Key Management
// Use environment variables for encryption keys
const encryptionService = new EncryptionService({
key: process.env.ENCRYPTION_KEY || throw new Error('ENCRYPTION_KEY not set'),
algorithm: 'xor',
encoding: 'base64'
});
// Rotate keys periodically
class KeyRotationManager {
async rotateEncryptionKey(oldKey: string, newKey: string): Promise<void> {
const oldService = new EncryptionService({ key: oldKey });
const newService = new EncryptionService({ key: newKey });
// Re-encrypt all sensitive data with new key
const tokens = await db.prepare('SELECT * FROM encrypted_tokens').all();
for (const token of tokens.results) {
const decrypted = oldService.decrypt(token.encrypted_value);
const reEncrypted = newService.encrypt(decrypted);
await db.prepare(`
UPDATE encrypted_tokens
SET encrypted_value = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?
`).bind(reEncrypted, token.id).run();
}
}
}
2. Input Validation
// Validate encryption inputs
class SecureEncryptionService extends EncryptionService {
encrypt(text: string): string {
// Validate input
if (typeof text !== 'string') {
throw new Error('Input must be a string');
}
if (text.length === 0) {
throw new Error('Input cannot be empty');
}
// Check for maximum length to prevent DoS
if (text.length > 10000) {
throw new Error('Input too large for encryption');
}
return super.encrypt(text);
}
decrypt(encryptedText: string): string {
// Validate encrypted input
if (typeof encryptedText !== 'string') {
throw new Error('Encrypted input must be a string');
}
if (encryptedText.length === 0) {
throw new Error('Encrypted input cannot be empty');
}
return super.decrypt(encryptedText);
}
}
3. Error Handling
// Secure error handling
class SecureTokenManager {
private encryptionService: EncryptionService;
constructor(key: string) {
this.encryptionService = new EncryptionService({ key });
}
async decryptTokenSafely(encryptedToken: string): Promise<string | null> {
try {
return this.encryptionService.decrypt(encryptedToken);
} catch (error) {
// Log error but don't expose details
console.error('Token decryption failed:', error.message);
// Return null instead of throwing
return null;
}
}
async encryptTokenSafely(token: string): Promise<string | null> {
try {
return this.encryptionService.encrypt(token);
} catch (error) {
console.error('Token encryption failed:', error.message);
return null;
}
}
}
Algorithm Details
XOR Encryption
// Simple XOR encryption (for development/demo)
private xorEncrypt(text: string): string {
let result = '';
for (let i = 0; i < text.length; i++) {
result += String.fromCharCode(
text.charCodeAt(i) ^ this.config.key.charCodeAt(i % this.config.key.length)
);
}
if (this.config.encoding === 'base64') {
return btoa(result);
} else if (this.config.encoding === 'hex') {
return Array.from(result)
.map(c => c.charCodeAt(0).toString(16).padStart(2, '0'))
.join('');
}
return result;
}
private xorDecrypt(encryptedText: string): string {
let decoded: string;
if (this.config.encoding === 'base64') {
try {
decoded = atob(encryptedText);
} catch {
return '';
}
} else if (this.config.encoding === 'hex') {
try {
decoded = String.fromCharCode(
...encryptedText.match(/.{1,2}/g)!.map(byte => parseInt(byte, 16))
);
} catch {
return '';
}
} else {
decoded = encryptedText;
}
let result = '';
for (let i = 0; i < decoded.length; i++) {
result += String.fromCharCode(
decoded.charCodeAt(i) ^ this.config.key.charCodeAt(i % this.config.key.length)
);
}
return result;
}
AES Encryption (Future Implementation)
// AES encryption (placeholder for future implementation)
private async aesEncrypt(text: string): Promise<string> {
// Implementation would use Web Crypto API
// For now, fallback to XOR
console.warn('AES encryption not implemented, falling back to XOR');
return this.xorEncrypt(text);
}
private async aesDecrypt(encryptedText: string): Promise<string> {
// Implementation would use Web Crypto API
// For now, fallback to XOR
console.warn('AES decryption not implemented, falling back to XOR');
return this.xorDecrypt(encryptedText);
}
Integration Examples
Database Integration
// Secure database operations
class SecureDatabaseService {
private encryptionService: EncryptionService;
constructor() {
this.encryptionService = new EncryptionService({
key: process.env.DB_ENCRYPTION_KEY || 'db-key',
algorithm: 'xor',
encoding: 'base64'
});
}
// Store sensitive user data
async storeUserData(userId: string, sensitiveData: Record<string, any>): Promise<void> {
const encryptedData = this.encryptionService.encrypt(JSON.stringify(sensitiveData));
await db.prepare(`
INSERT OR REPLACE INTO user_sensitive_data (user_id, encrypted_data, updated_at)
VALUES (?, ?, CURRENT_TIMESTAMP)
`).bind(userId, encryptedData).run();
}
// Retrieve sensitive user data
async getUserData(userId: string): Promise<Record<string, any> | null> {
const result = await db.prepare(`
SELECT encrypted_data FROM user_sensitive_data WHERE user_id = ?
`).bind(userId).first();
if (!result) return null;
const decrypted = this.encryptionService.decrypt(result.encrypted_data);
return JSON.parse(decrypted);
}
}
API Integration
// Secure API token handling
class SecureAPIService {
private encryptionService: EncryptionService;
constructor() {
this.encryptionService = new EncryptionService({
key: process.env.API_ENCRYPTION_KEY || 'api-key',
algorithm: 'xor',
encoding: 'base64'
});
}
// Store API credentials securely
async storeAPICredentials(serviceName: string, credentials: {
apiKey: string;
secretKey?: string;
endpoint?: string;
}): Promise<void> {
const encryptedCredentials = this.encryptionService.encrypt(
JSON.stringify(credentials)
);
await db.prepare(`
INSERT OR REPLACE INTO api_credentials (service_name, encrypted_credentials, updated_at)
VALUES (?, ?, CURRENT_TIMESTAMP)
`).bind(serviceName, encryptedCredentials).run();
}
// Retrieve API credentials
async getAPICredentials(serviceName: string): Promise<{
apiKey: string;
secretKey?: string;
endpoint?: string;
} | null> {
const result = await db.prepare(`
SELECT encrypted_credentials FROM api_credentials WHERE service_name = ?
`).bind(serviceName).first();
if (!result) return null;
const decrypted = this.encryptionService.decrypt(result.encrypted_credentials);
return JSON.parse(decrypted);
}
}
Testing
Encryption Testing
describe('EncryptionService', () => {
let encryptionService: EncryptionService;
beforeEach(() => {
encryptionService = new EncryptionService({
key: 'test-key-123',
algorithm: 'xor',
encoding: 'base64'
});
});
it('should encrypt and decrypt data correctly', () => {
const originalData = 'sensitive-information';
const encrypted = encryptionService.encrypt(originalData);
const decrypted = encryptionService.decrypt(encrypted);
expect(decrypted).toBe(originalData);
expect(encrypted).not.toBe(originalData);
});
it('should handle empty strings', () => {
const encrypted = encryptionService.encrypt('');
const decrypted = encryptionService.decrypt(encrypted);
expect(decrypted).toBe('');
});
it('should handle special characters', () => {
const originalData = 'special-chars: !@#$%^&*()_+-=[]{}|;:,.<>?';
const encrypted = encryptionService.encrypt(originalData);
const decrypted = encryptionService.decrypt(encrypted);
expect(decrypted).toBe(originalData);
});
});
Security Testing
describe('Security Features', () => {
it('should not expose encryption key in output', () => {
const encryptionService = new EncryptionService({
key: 'secret-key',
algorithm: 'xor',
encoding: 'base64'
});
const encrypted = encryptionService.encrypt('test-data');
// Encrypted output should not contain the key
expect(encrypted).not.toContain('secret-key');
});
it('should handle invalid encrypted input gracefully', () => {
const encryptionService = new EncryptionService({
key: 'test-key',
algorithm: 'xor',
encoding: 'base64'
});
const result = encryptionService.decrypt('invalid-base64');
expect(result).toBe('');
});
});
This encryption and security system provides robust protection for sensitive data throughout the PadawanForge application.