/credential-code

credential-code

Primary LanguageSwiftMIT LicenseMIT

🔐 Credential Code

Transform plain text credentials into encrypted code at build time. Never commit secrets again.

Swift Platform License Languages

Why Credential Code?

Stop hardcoding secrets. Credential Code encrypts your credentials at build time, generating source code with encrypted data that's safe to commit. Your secrets are only decrypted in memory at runtime.

graph LR
    A[credentials.json<br/>plain text] -->|credential-code<br/>generate| B[Encrypted Code<br/>safe to commit]
    B -->|Your App<br/>runtime| C[Decrypted<br/>in memory]
    
    style A fill:#ffcccc
    style B fill:#ccffcc
    style C fill:#ccccff
Loading

⚠️ IMPORTANT: Security Limitations

This tool is NOT suitable for open source projects. The encryption key is embedded in the generated code (even in obfuscated form), which means anyone with access to the code can decrypt the credentials. Use this tool only for:

  • Private/proprietary applications
  • Internal company projects
  • Closed-source mobile apps
  • Server applications with restricted access

✨ Key Benefits

  • 🚫 No secrets in source code - Credentials never appear as strings in your binaries
  • 🔄 Build-time encryption - Source code uses embedded keys, no external dependencies
  • 🌍 Multi-language support - Works with Swift, Kotlin, Java, Python, and C++
  • 🛡️ Type-safe access - No magic strings, just compile-time checked enums
  • 📦 Zero dependencies - Generated code uses only standard crypto libraries
  • 🔀 Dual output formats - Self-contained code for apps, .creds files for runtime config

📚 Documentation

See the Documentation Index for comprehensive guides and resources.

🚀 Quick Start

1. Install

# Build from source
git clone https://github.com/yourusername/credential-code.git
cd credential-code
swift build -c release
sudo cp .build/release/credential-code /usr/local/bin/

2. Initialize Your Project

cd your-project
credential-code init

3. Add Your Credentials

Edit .credential-code/credentials.json:

{
  "API_KEY": "sk-1234567890abcdef",
  "DATABASE_URL": "postgres://user:pass@localhost/db"
}

4. Generate Encrypted Code

credential-code generate
# This creates:
# - Generated/Credentials.swift (self-contained with embedded key)
# - Generated/credentials.creds (requires external key file)
# - .credential-code/encryption-key.txt (key for .creds file only)

5. Use in Your App

// Direct usage - no key loading needed!
if let apiKey = Credentials.decrypt(.API_KEY) {
    // Use your API key
}

📚 Full Documentation

Supported Languages

Language File Required Libraries Key Mode
Swift Credentials.swift CryptoKit (built-in) Embedded by default, external available
Kotlin Credentials.kt javax.crypto (built-in) Embedded by default, external available
Java Credentials.java javax.crypto (built-in) Embedded by default, external available
Python credentials.py cryptography Embedded by default, external available
C++ credentials.cpp OpenSSL Embedded by default, external available

Note: All languages generate self-contained code with embedded keys by default. All languages support external key mode with the --external-key flag for enhanced security.

Usage

Initialize

Create the credential storage structure in your project:

credential-code init

This creates:

  • .credential-code/ directory
  • credentials.json with example structure
  • Updates .gitignore to exclude credentials

Add Credentials

Edit .credential-code/credentials.json:

{
  "STRIPE_KEY": "sk_test_...",
  "AWS_SECRET": "aws_secret_key_...",
  "JWT_SECRET": "your-256-bit-secret"
}

Naming Convention: Use UPPER_SNAKE_CASE for credential keys.

Generate Code

Generate encrypted code for your target language:

# Default: Swift with external key + .creds file
credential-code generate
# Creates: 
# - Generated/Credentials.swift
# - Generated/credentials.creds
# - .credential-code/encryption-key.txt

# Other languages (also generate .creds by default)
credential-code generate --language kotlin
credential-code generate --language java --output src/main/java/Creds.java

# Without .creds file
credential-code generate --no-generate-creds

By default, credential-code now generates:

  • Code file: Language-specific encrypted credentials (e.g., Generated/Credentials.swift)
  • .creds file: JSON format for backend/runtime use (Generated/credentials.creds)
  • External key: Stored in .credential-code/encryption-key.txt (base64 format)
  • Key reuse: If the key file exists, it's reused (consistent encryption across builds)
  • Easy copying: Key is displayed when first generated for manual backup

Key Management Options

Default: External Key File

# Generate with external key (default)
credential-code generate

# Specify custom key file path
credential-code generate --key-file path/to/key.txt

Option 1: Embedded Key (Legacy)

# Generate with embedded key (old behavior)
credential-code generate --embedded-key

Option 2: Source Code Key

# Generate with external key as source code
credential-code generate --external-key-source

# Specify custom output path
credential-code generate --external-key-source --key-source-output Keys/MyKey.swift

📖 See the complete External Key Usage Guide for detailed instructions

Backend/Runtime Configuration (.creds files)

.creds files are now generated by default alongside code files:

# Default: generates both code and .creds
credential-code generate

# Custom .creds output path
credential-code generate --creds-output backend/prod.creds

# Disable .creds generation (code only)
credential-code generate --no-generate-creds

The .creds file can be loaded at runtime by any backend service:

// Node.js example
const key = fs.readFileSync('encryption-key.txt', 'utf8');
const creds = JSON.parse(fs.readFileSync('credentials.creds'));
const apiKey = decrypt(creds, key, 'API_KEY');

📖 See the Two Use Cases Guide for detailed examples

Language Examples

Swift Example

import Foundation

// Default mode (embedded key) - no setup needed!
if let apiKey = Credentials.decrypt(.API_KEY) {
    let headers = ["Authorization": "Bearer \(apiKey)"]
    // Make API request...
}

// Use cached decryption for frequently accessed credentials
let dbUrl = Credentials.decryptCached(.DATABASE_URL)

// External key mode (requires --external-key flag during generation)
// First, load the key
try Credentials.loadKey(from: ".credential-code/encryption-key.txt")
// Then access credentials
let apiKey = try Credentials.get(.API_KEY)

Kotlin Example

// Default mode (embedded key) - no setup needed!
val apiKey = Credentials.decrypt(CredentialKey.API_KEY)
apiKey?.let { key ->
    val headers = mapOf("Authorization" to "Bearer $key")
    // Make API request...
}

// With caching
val dbUrl = Credentials.decryptCached(CredentialKey.DATABASE_URL)

// External key mode (requires --external-key flag during generation)
// First, load the key
Credentials.loadKey(".credential-code/encryption-key.txt")
// Then access credentials
val apiKey = Credentials.get(CredentialKey.API_KEY)

Java Example

// Default mode (embedded key) - no setup needed!
String apiKey = Credentials.decrypt(CredentialKey.API_KEY);
if (apiKey != null) {
    Map<String, String> headers = Map.of("Authorization", "Bearer " + apiKey);
    // Make API request...
}

// External key mode (requires --external-key flag during generation)
// First, load the key
Credentials.loadKey(".credential-code/encryption-key.txt");
// Then access credentials
String apiKey = Credentials.get(CredentialKey.API_KEY);

Python Example

from credentials import Credentials, CredentialKey

# Default mode (embedded key) - no setup needed!
api_key = Credentials.decrypt(CredentialKey.API_KEY)
if api_key:
    headers = {"Authorization": f"Bearer {api_key}"}
    # Make API request...

# With caching
db_url = Credentials.decrypt_cached(CredentialKey.DATABASE_URL)

# External key mode (requires --external-key flag during generation)
# First, load the key
Credentials.load_key(".credential-code/encryption-key.txt")
# Then access credentials
api_key = Credentials.get(CredentialKey.API_KEY)

C++ Example

#include "credentials.h"

// Default mode (embedded key) - no setup needed!
auto apiKey = Credentials::decrypt(CredentialKey::API_KEY);
if (apiKey.has_value()) {
    std::string authHeader = "Bearer " + apiKey.value();
    // Make API request...
}

// External key mode (requires --external-key flag during generation)
// First, load the key
Credentials::loadKey(".credential-code/encryption-key.txt");
// Then access credentials
std::string apiKey = Credentials::get(CredentialKey::API_KEY);

Demo

Run the comprehensive demo to see all languages in action:

./demo.sh

The demo:

  • Creates a sample project with test credentials
  • Generates encrypted code for all languages
  • Runs working examples
  • Shows the complete workflow

Dual Use Example

See the example-dual-use/ directory for a complete example showing both approaches:

cd example-dual-use
./demo.sh

This demonstrates:

  • Compiled approach: Credentials embedded in Swift binary
  • Runtime approach: Credentials loaded from .creds file in Node.js
  • Both methods decrypt the same credentials using the same key

Security

How It Works

  1. Development: Store credentials as plain text in .credential-code/credentials.json
  2. Build Time: Generate code with encrypted credentials using a random key
  3. Runtime: Credentials are decrypted only in memory when accessed
  4. Version Control: Only encrypted code is committed, never plain credentials

Security Features

  • AES-256-GCM encryption with authenticated encryption
  • External keys by default - Keys stored separately from code
  • Key persistence - Same key reused across builds (when file exists)
  • No string literals - Credentials never appear as plain text in binaries
  • Memory-only decryption - Decrypted values exist only during use
  • Multiple key formats - Plain text, JSON, or source code

Best Practices

DO:

  • Add .credential-code/ to .gitignore
  • Generate fresh code for production builds
  • Use different credentials for each environment
  • Rotate credentials regularly

DON'T:

  • Commit .credential-code/ directory
  • Share credential files between developers
  • Log decrypted credential values
  • Store decrypted values longer than necessary
  • Use this for open source projects - Anyone with access to the code can decrypt credentials

Installation

Requirements

  • Development: macOS 12.0+, Swift 5.5+
  • Runtime: Depends on target language
    • Swift: macOS 11.0+, iOS 14.0+
    • Python: Python 3.7+, cryptography package
    • Java/Kotlin: Java 8+
    • C++: C++17, OpenSSL

Build from Source

# Clone repository
git clone https://github.com/yourusername/credential-code.git
cd credential-code

# Build release version
swift build -c release

# Install to /usr/local/bin
sudo cp .build/release/credential-code /usr/local/bin/

# Verify installation
credential-code --version

Advanced Usage

CI/CD Integration

# GitHub Actions example
- name: Generate Credentials
  run: |
    echo '${{ secrets.CREDENTIALS_JSON }}' > .credential-code/credentials.json
    credential-code generate --language swift

Multiple Environments

# Development
credential-code generate --output Generated/Credentials.dev.swift

# Production  
credential-code generate --output Generated/Credentials.prod.swift

Custom Output Paths

# Specify custom output location
credential-code generate \
  --language python \
  --output src/config/secure_credentials.py

External Key Management

External keys are now the default for better security:

# Generate with default external key
credential-code generate
# Key saved to: .credential-code/encryption-key.txt

# Use custom key location
credential-code generate --key-file keys/prod.key

# Store key in environment variable (CI/CD)
export CREDENTIAL_KEY=$(cat .credential-code/encryption-key.txt)

Key Storage Options:

  • Environment Variables: Best for CI/CD and containerized deployments
  • Secret Management Systems: AWS Secrets Manager, HashiCorp Vault, etc.
  • Secure File Storage: Encrypted volumes, HSMs
  • Configuration Management: Kubernetes Secrets, Docker Secrets

Example: AWS Secrets Manager Integration

# Store key in AWS Secrets Manager
aws secretsmanager create-secret \
  --name prod/credential-key \
  --secret-string file://keys/prod.key

# Retrieve at runtime
KEY=$(aws secretsmanager get-secret-value \
  --secret-id prod/credential-key \
  --query SecretString --output text)

Working with .creds Files

For runtime decryption of .creds files, we provide utility libraries for multiple languages:

# Swift
let decryptor = try CredentialDecryptor(keyPath: ".credential-code/encryption-key.txt")
let credentials = try decryptor.loadCredentials(from: "Generated/credentials.creds")

# Python
from credential_code_utility import CredentialDecryptor
decryptor = CredentialDecryptor('.credential-code/encryption-key.txt')
credentials = decryptor.load_credentials('Generated/credentials.creds')

# JavaScript
const { CredentialDecryptor } = require('credential-code-utility');
const decryptor = new CredentialDecryptor('.credential-code/encryption-key.txt');
const credentials = decryptor.loadCredentials('Generated/credentials.creds');

# Java
CredentialDecryptor decryptor = new CredentialDecryptor(Paths.get(".credential-code/encryption-key.txt"));
Map<String, String> credentials = decryptor.loadCredentials("Generated/credentials.creds");

See the utilities/ directory for ready-to-use decryption libraries with full documentation for each language.

Troubleshooting

Common Issues

"Not initialized" error

# Run init in your project root
credential-code init

"Invalid key format" error

  • Use UPPER_SNAKE_CASE for keys
  • Only letters, numbers, and underscores

Python "No module named 'cryptography'"

pip install cryptography

Contributing

We welcome contributions! See CONTRIBUTING.md for guidelines.

Development Setup

# Clone repo
git clone https://github.com/yourusername/credential-code.git
cd credential-code

# Open in Xcode
open Package.swift

# Run tests
swift test

Roadmap

  • Package manager support (Homebrew, apt, etc.)
  • GUI application
  • VS Code extension
  • Additional languages (Go, Rust, Ruby)
  • Cloud key management integration
  • Credential rotation automation

License

MIT License - see LICENSE for details.

Acknowledgments

Built with Swift Argument Parser and love for secure coding practices.


Made with ❤️ by developers who forgot to remove their API keys one too many times