Credential Security
This guide provides best practices for managing secrets, API keys, and sensitive configurations within Cyne AI to ensure security and operational efficiency.
Core Concepts
Environment Variables
Cyne AI uses a hierarchical system for environment variables:
Character-specific secrets (highest priority).
Environment variables defined in
.env
files.Default values (lowest priority).
Secret Types
Common secrets managed in Cyne AI:
# API Keys
OPENAI_API_KEY=sk-your-openai-key
# Client Authentication
DISCORD_API_TOKEN=your-discord-token
TELEGRAM_BOT_TOKEN=your-telegram-token
# Solana Wallet Credentials
SOLANA_PRIVATE_KEY=example-private-key
SOLANA_PUBLIC_KEY=example-public-key
Implementation Guide
Basic Setup
Create a
.env
file from the provided template:cp .env.example .env
Configure environment variable discovery in your code:
import { config } from "dotenv"; config(); // Load environment variables
Character-Specific Secrets
Define secrets directly in character files for modular configuration:
{
"name": "TradingAgent",
"settings": {
"secrets": {
"OPENAI_API_KEY": "character-specific-key",
"SOLANA_PRIVATE_KEY": "character-specific-wallet"
}
}
}
Access secrets in your code:
const apiKey = runtime.getSetting("OPENAI_API_KEY");
Secure Storage
Wallet Management
Handle Solana wallet credentials securely:
class WalletManager {
private async initializeWallet(runtime: IAgentRuntime) {
const privateKey = runtime.getSetting("SOLANA_PRIVATE_KEY");
if (!privateKey) {
throw new Error("Wallet private key not configured");
}
// Validate and initialize the wallet
const keyBuffer = Buffer.from(privateKey, "base64");
if (keyBuffer.length !== 64) {
throw new Error("Invalid key format");
}
return new Wallet(privateKey);
}
}
Encryption for Secrets
Encrypt sensitive secrets before storage:
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
class SecretEncryption {
static async encrypt(value: string, key: Buffer): Promise<string> {
const iv = randomBytes(16);
const cipher = createCipheriv("aes-256-gcm", key, iv);
let encrypted = cipher.update(value, "utf8", "hex");
encrypted += cipher.final("hex");
return JSON.stringify({
iv: iv.toString("hex"),
encrypted,
tag: cipher.getAuthTag().toString("hex")
});
}
static async decrypt(encrypted: string, key: Buffer): Promise<string> {
const { iv, encrypted: encryptedData, tag } = JSON.parse(encrypted);
const decipher = createDecipheriv("aes-256-gcm", key, Buffer.from(iv, "hex"));
decipher.setAuthTag(Buffer.from(tag, "hex"));
let decrypted = decipher.update(encryptedData, "hex", "utf8");
decrypted += decipher.final("utf8");
return decrypted;
}
}
Best Practices
1. Environment Segregation
Use separate .env
files for different environments:
.env.development
– Development settings.env.staging
– Staging environment.env.production
– Production environment
2. Secret Validation
Ensure required secrets are defined:
async function validateSecrets(character: Character): Promise<void> {
const required = ["OPENAI_API_KEY", "SOLANA_PRIVATE_KEY"];
const missing = required.filter((key) => !character.settings.secrets[key]);
if (missing.length > 0) {
throw new Error(`Missing required secrets: ${missing.join(", ")}`);
}
}
3. Git Security
Exclude sensitive files from version control by adding the following to .gitignore
:
.env
characters/**/secrets.json
4. Secret Rotation
Regularly rotate secrets to enhance security:
class SecretRotation {
private static readonly SECRET_LIFETIME = 90 * 24 * 60 * 60 * 1000; // 90 days
async shouldRotateSecret(secretName: string): Promise<boolean> {
const lastRotation = await this.getLastRotation(secretName);
return Date.now() - lastRotation > SecretRotation.SECRET_LIFETIME;
}
async rotateSecret(secretName: string): Promise<void> {
// Logic for secret rotation
const newSecret = await this.generateNewSecret();
await this.updateSecret(secretName, newSecret);
}
}
Troubleshooting
Common Issues
Missing Secrets Ensure required environment variables or character-specific secrets are defined:
if (!process.env.OPENAI_API_KEY) { throw new Error("OpenAI API key is missing."); }
Invalid Secret Format Validate the format of critical secrets like API keys:
function validateApiKey(key: string): boolean { return key.startsWith("sk-") && key.length > 20; }
Secret Loading Errors Handle errors gracefully during secret loading:
try { await loadSecrets(); } catch (error) { console.error("Error loading secrets:", error.message); }
Security Considerations
1. API Keys Handling
Use strong validation logic for keys.
Rotate keys periodically to reduce risks.
2. Access Control
Restrict access to sensitive secrets using a controlled list.
Log unauthorized access attempts for monitoring.
3. Encryption at Rest
Encrypt all sensitive data stored on disk.
Use AES-256-GCM encryption for strong security.
Related Resources
Configuration Guide: General setup instructions.
Local Development Guide: Best practices for local environments.
Infrastructure Guide: Secure deployment practices.
By following these guidelines, you can manage secrets effectively and securely within the Cyne AI framework, ensuring robust and secure operations.
Last updated