Aethel Bot OSS repository!
aethel.xyz
bot
fun
ai
discord
discord-bot
aethel
1import crypto from 'crypto';
2import { API_KEY_ENCRYPTION_SECRET } from '../config';
3
4const ENCRYPTION_KEY = API_KEY_ENCRYPTION_SECRET;
5const ALGORITHM = 'aes-256-gcm';
6
7const getEncryptionKey = (): Buffer => {
8 if (ENCRYPTION_KEY.length !== 32) {
9 throw new Error('ENCRYPTION_KEY must be exactly 32 characters long');
10 }
11 return Buffer.from(ENCRYPTION_KEY, 'utf8');
12};
13
14/**
15 * Encrypts a string using AES-256-GCM
16 * @param text The text to encrypt
17 * @returns Base64 encoded encrypted data with IV and auth tag
18 */
19export const encryptApiKey = (text: string): string => {
20 try {
21 const key = getEncryptionKey();
22 const iv = crypto.randomBytes(16);
23
24 const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
25 cipher.setAAD(Buffer.from('aethel-api-key', 'utf8'));
26
27 let encrypted = cipher.update(text, 'utf8', 'hex');
28 encrypted += cipher.final('hex');
29
30 const authTag = cipher.getAuthTag();
31
32 const combined = Buffer.concat([iv, authTag, Buffer.from(encrypted, 'hex')]);
33
34 return combined.toString('base64');
35 } catch {
36 throw new Error('Failed to encrypt API key');
37 }
38};
39
40/**
41 * Decrypts a string that was encrypted with encryptApiKey
42 * @param encryptedData Base64 encoded encrypted data
43 * @returns The decrypted text
44 */
45export const decryptApiKey = (encryptedData: string): string => {
46 try {
47 const key = getEncryptionKey();
48 const combined = Buffer.from(encryptedData, 'base64');
49
50 const extractedIv = combined.subarray(0, 16);
51 const authTag = combined.subarray(16, 32);
52 const encrypted = combined.subarray(32);
53
54 const decipher = crypto.createDecipheriv(ALGORITHM, key, extractedIv);
55 decipher.setAAD(Buffer.from('aethel-api-key', 'utf8'));
56 decipher.setAuthTag(authTag);
57
58 let decrypted = decipher.update(encrypted, undefined, 'utf8');
59 decrypted += decipher.final('utf8');
60
61 return decrypted;
62 } catch {
63 throw new Error('Failed to decrypt API key');
64 }
65};
66
67/**
68 * Generates a secure random encryption key
69 * @returns A 32-character random string suitable for use as ENCRYPTION_KEY
70 */
71export const generateEncryptionKey = (): string => {
72 return crypto.randomBytes(32).toString('base64').substring(0, 32);
73};
74
75/**
76 * Validates that an encryption key is properly formatted
77 * @param key The key to validate
78 * @returns True if the key is valid
79 */
80export const validateEncryptionKey = (key: string): boolean => {
81 return typeof key === 'string' && key.length === 32;
82};