How FreeLLMAPI Encrypts API Keys: AES-256-GCM Implementation Explained
FreeLLMAPI uses AES-256-GCM encryption with a 256-bit key derived from the ENCRYPTION_KEY environment variable to protect all stored API keys and proxy URLs.
The open-source FreeLLMAPI project implements military-grade symmetric encryption for sensitive credential storage. According to the tashfeenahmed/freellmapi source code, every API key undergoes authenticated encryption before persistence, combining confidentiality with integrity verification through Galois/Counter Mode.
AES-256-GCM Encryption in FreeLLMAPI
The encryption layer resides in server/src/lib/crypto.ts, which exports encrypt and decrypt functions built on Node.js's native crypto module.
Encryption Algorithm Details
The implementation follows NIST-recommended parameters for GCM:
- Algorithm: AES-256-GCM
- Key size: 256 bits (32 bytes)
- IV size: 128 bits (16 bytes), randomly generated per encryption
- Authentication tag: 128 bits (16 bytes), fixed length
The encrypt function constructs a cipher instance using:
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
The resulting ciphertext, IV, and authentication tag are stored across three columns in the SQLite api_keys table: encrypted_key, iv, and auth_tag.
Decryption and Integrity Verification
The decrypt function enforces a fixed 16-byte GCM tag length to prevent tag-truncation attacks. It reconstructs the decipher from stored components and validates the authentication tag before returning plaintext:
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(authTag);
Key Management Architecture
Production Key Source
In production environments, the 32-byte encryption key is derived from the ENCRYPTION_KEY environment variable. This variable must contain a 64-character hexadecimal string representing 32 bytes of key material.
Development Fallback
Non-production deployments automatically generate a cryptographically secure fallback key if ENCRYPTION_KEY is unset. This key is persisted to a file named .encryption-key adjacent to the SQLite database, enabling consistent encryption across development restarts without manual configuration.
Practical Code Examples
Encrypting and Storing an API Key
import { encrypt, decrypt } from './lib/crypto.js';
// Encrypt a raw API key before storing it
const rawKey = 'sk-xxxxxxxxxxxxxxxxxxxx';
const { encrypted, iv, authTag } = encrypt(rawKey);
// Store `encrypted`, `iv`, and `authTag` in the `api_keys` table
db.prepare(`
INSERT INTO api_keys (encrypted_key, iv, auth_tag, provider)
VALUES (?, ?, ?, ?)
`).run(encrypted, iv, authTag, 'openai');
Retrieving and Decrypting for Use
// Later, retrieve and decrypt
const stored = db.prepare(`
SELECT encrypted_key, iv, auth_tag
FROM api_keys
WHERE id = ?
`).get(keyId);
const apiKey = decrypt(stored.encrypted_key, stored.iv, stored.auth_tag);
console.log(apiKey); // => 'sk-xxxxxxxxxxxxxxxxxxxx'
Key Files in the Encryption Implementation
| File | Purpose |
|---|---|
server/src/lib/crypto.ts |
Core encryption/decryption utilities, key initialization, and masking logic |
server/src/routes/keys.ts |
API endpoint that receives raw keys, encrypts via encrypt, and persists them |
server/src/routes/media.ts |
Demonstrates retrieval and decryption of stored keys for downstream LLM requests |
server/src/lib/key-proxy.js |
Encrypts proxy URLs using the identical AES-256-GCM routine |
Summary
- FreeLLMAPI uses AES-256-GCM for authenticated encryption of all API keys and proxy URLs
- The implementation in
server/src/lib/crypto.tsenforces 256-bit keys, random 16-byte IVs, and 16-byte authentication tags - Production deployments require the
ENCRYPTION_KEYenvironment variable as a 64-character hex string - Development environments auto-generate fallback keys stored in
.encryption-key - Three-part storage (ciphertext, IV, auth tag) enables secure decryption with integrity verification
Frequently Asked Questions
What encryption algorithm does FreeLLMAPI use for API keys?
FreeLLMAPI uses AES-256-GCM. This is an authenticated encryption mode that provides both confidentiality and integrity verification, implemented in server/src/lib/crypto.ts using Node.js native crypto primitives.
How is the encryption key managed in FreeLLMAPI?
Production deployments supply a 256-bit key via the ENCRYPTION_KEY environment variable as 64 hexadecimal characters. In development, FreeLLMAPI automatically generates and persists a secure fallback key to a .encryption-key file beside the database.
Where does FreeLLMAPI store encrypted API keys?
Encrypted API keys are stored in an SQLite database table named api_keys with three columns: encrypted_key (ciphertext), iv (16-byte initialization vector), and auth_tag (16-byte GCM authentication tag).
Does FreeLLMAPI encrypt anything besides API keys?
Yes. The same AES-256-GCM implementation in server/src/lib/crypto.ts is reused for proxy URL encryption, as seen in server/src/lib/key-proxy.js, ensuring consistent protection for all sensitive configuration data.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →