Hardcoded Cryptographic Keys and Salts

Critical Risk Cryptographic Security
cryptographic-keysencryption-keyshardcoded-secretssaltsinitialization-vectorscryptographic-constantskey-managementsecrets-exposure

What it is

A critical security vulnerability where encryption keys, cryptographic salts, initialization vectors (IVs), or other cryptographic secrets are hardcoded directly in source code. This exposes the cryptographic foundation of security systems, allowing attackers to decrypt data, forge signatures, and bypass authentication mechanisms.

# VULNERABLE: Multiple hardcoded cryptographic secrets
import hashlib
import hmac
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import base64
import time

class VulnerableEncryptionService:
    # NEVER hardcode cryptographic secrets!
    MASTER_KEY = b'ThisIsMyMasterKey1234567890123456'  # 32 bytes for AES-256
    SALT_CONSTANT = b'fixed_salt_that_never_changes_32'   # Fixed salt
    HMAC_SECRET = b'hmac_secret_key_for_authentication_'   # HMAC key
    IV_CONSTANT = b'1234567890123456'  # Fixed IV (16 bytes)
    
    # Hardcoded Fernet key
    FERNET_KEY = b'ZmDfcTF7_60GrrY167zsiPd67pEvs0aGOv2oasOM1Pg='  # Base64 Fernet key
    
    def __init__(self):
        self.fernet = Fernet(self.FERNET_KEY)
    
    def encrypt_user_data(self, user_id, sensitive_data):
        """Encrypt user data with hardcoded keys"""
        # Using fixed salt for key derivation
        key = hashlib.pbkdf2_hmac('sha256', str(user_id).encode(), self.SALT_CONSTANT, 100000)
        
        # Using fixed IV (deterministic encryption!)
        cipher = Cipher(algorithms.AES(key), modes.CBC(self.IV_CONSTANT), backend=default_backend())
        encryptor = cipher.encryptor()
        
        # Pad data manually (vulnerable to padding attacks)
        padding_length = 16 - (len(sensitive_data) % 16)
        padded_data = sensitive_data.encode() + bytes([padding_length] * padding_length)
        
        encrypted = encryptor.update(padded_data) + encryptor.finalize()
        
        # Create HMAC with hardcoded secret
        mac = hmac.new(self.HMAC_SECRET, encrypted, hashlib.sha256).digest()
        
        return base64.b64encode(encrypted + mac).decode()
    
    def encrypt_with_fernet(self, data):
        """Simple encryption with hardcoded Fernet key"""
        return self.fernet.encrypt(data.encode()).decode()
    
    def generate_api_token(self, user_id):
        """Generate API token with hardcoded secret"""
        timestamp = str(int(time.time()))
        token_data = f"{user_id}:{timestamp}"
        
        # Hardcoded signing key
        signature = hmac.new(
            b'api_token_signing_key_never_change_this',
            token_data.encode(),
            hashlib.sha256
        ).hexdigest()
        
        return f"{base64.b64encode(token_data.encode()).decode()}.{signature}"
    
    def encrypt_database_field(self, table_name, field_value):
        """Encrypt database field with table-specific hardcoded key"""
        # Different hardcoded keys per table (still vulnerable!)
        table_keys = {
            'users': b'users_table_encryption_key_123456789012',
            'payments': b'payments_table_key_abcdefghijklmnop',
            'sessions': b'sessions_table_key_0987654321098765'
        }
        
        key = table_keys.get(table_name, self.MASTER_KEY)
        
        # Fixed IV per table
        table_ivs = {
            'users': b'users_iv_1234567',
            'payments': b'payments_iv_abc',
            'sessions': b'sessions_iv_xyz'
        }
        
        iv = table_ivs.get(table_name, self.IV_CONSTANT)
        
        cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
        encryptor = cipher.encryptor()
        
        # Simple padding
        padded = field_value.encode() + b'\x00' * (16 - len(field_value) % 16)
        return base64.b64encode(encryptor.update(padded) + encryptor.finalize()).decode()
# SECURE: Proper cryptographic key management
import hashlib
import hmac
import os
import secrets
import boto3
import json
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.fernet import Fernet
import base64
import time
import logging

class SecureEncryptionService:
    def __init__(self, environment='production'):
        self.environment = environment
        self.secrets_client = boto3.client('secretsmanager')
        self.key_cache = {}  # Implement proper TTL in production
        self.logger = logging.getLogger(__name__)
        
        # Validate environment configuration
        self.validate_environment()
    
    def validate_environment(self):
        """Ensure all required environment variables are set"""
        required_vars = [
            'AWS_REGION',
            'KEY_MANAGEMENT_SECRET_NAME',
            'ENCRYPTION_KEY_NAMESPACE'
        ]
        
        missing = [var for var in required_vars if not os.getenv(var)]
        if missing:
            raise ValueError(f"Missing required environment variables: {missing}")
    
    def get_encryption_key(self, key_name, key_type='symmetric'):
        """Retrieve encryption key from AWS Secrets Manager"""
        cache_key = f"{key_name}:{key_type}"
        
        if cache_key in self.key_cache:
            return self.key_cache[cache_key]
        
        try:
            secret_name = f"{os.getenv('ENCRYPTION_KEY_NAMESPACE')}/{key_name}"
            response = self.secrets_client.get_secret_value(SecretId=secret_name)
            
            secret_data = json.loads(response['SecretString'])
            key_data = secret_data[key_type]
            
            # Cache the key (implement TTL in production)
            self.key_cache[cache_key] = base64.b64decode(key_data)
            
            return self.key_cache[cache_key]
            
        except Exception as e:
            self.logger.error(f"Failed to retrieve key {key_name}: {str(e)}")
            raise
    
    def generate_random_salt(self, length=32):
        """Generate cryptographically secure random salt"""
        return secrets.token_bytes(length)
    
    def encrypt_user_data(self, user_id, sensitive_data):
        """Encrypt user data with proper key management"""
        try:
            # Get user-specific encryption key from secure storage
            master_key = self.get_encryption_key('user-data-encryption')
            
            # Generate random salt for each encryption
            salt = self.generate_random_salt(32)
            
            # Derive user-specific key using PBKDF2
            kdf = PBKDF2HMAC(
                algorithm=hashes.SHA256(),
                length=32,
                salt=salt,
                iterations=100000,
                backend=default_backend()
            )
            
            user_key_material = master_key + str(user_id).encode()
            derived_key = kdf.derive(user_key_material)
            
            # Use AES-GCM for authenticated encryption
            aesgcm = AESGCM(derived_key)
            nonce = secrets.token_bytes(12)  # 96-bit nonce
            
            ciphertext = aesgcm.encrypt(nonce, sensitive_data.encode(), None)
            
            # Combine salt, nonce, and ciphertext
            encrypted_data = salt + nonce + ciphertext
            
            return base64.b64encode(encrypted_data).decode()
            
        except Exception as e:
            self.logger.error(f"Encryption failed for user {user_id}: {str(e)}")
            raise
    
    def decrypt_user_data(self, user_id, encrypted_data):
        """Decrypt user data"""
        try:
            encrypted_bytes = base64.b64decode(encrypted_data)
            
            # Extract components
            salt = encrypted_bytes[:32]
            nonce = encrypted_bytes[32:44]
            ciphertext = encrypted_bytes[44:]
            
            # Get master key and derive user key
            master_key = self.get_encryption_key('user-data-encryption')
            
            kdf = PBKDF2HMAC(
                algorithm=hashes.SHA256(),
                length=32,
                salt=salt,
                iterations=100000,
                backend=default_backend()
            )
            
            user_key_material = master_key + str(user_id).encode()
            derived_key = kdf.derive(user_key_material)
            
            # Decrypt and verify
            aesgcm = AESGCM(derived_key)
            plaintext = aesgcm.decrypt(nonce, ciphertext, None)
            
            return plaintext.decode()
            
        except Exception as e:
            self.logger.error(f"Decryption failed for user {user_id}: {str(e)}")
            raise
    
    def generate_api_token(self, user_id):
        """Generate API token with proper key management"""
        try:
            # Get signing key from secure storage
            signing_key = self.get_encryption_key('api-token-signing')
            
            timestamp = str(int(time.time()))
            nonce = secrets.token_hex(16)
            token_data = f"{user_id}:{timestamp}:{nonce}"
            
            # Create HMAC signature
            signature = hmac.new(
                signing_key,
                token_data.encode(),
                hashlib.sha256
            ).hexdigest()
            
            return f"{base64.b64encode(token_data.encode()).decode()}.{signature}"
            
        except Exception as e:
            self.logger.error(f"Token generation failed for user {user_id}: {str(e)}")
            raise
    
    def encrypt_database_field(self, table_name, field_value):
        """Encrypt database field with table-specific keys"""
        try:
            # Get table-specific encryption key
            table_key = self.get_encryption_key(f'table-{table_name}-encryption')
            
            # Generate random nonce for each encryption
            nonce = secrets.token_bytes(12)
            
            # Use AES-GCM for authenticated encryption
            aesgcm = AESGCM(table_key)
            ciphertext = aesgcm.encrypt(nonce, field_value.encode(), None)
            
            # Combine nonce and ciphertext
            encrypted_data = nonce + ciphertext
            
            return base64.b64encode(encrypted_data).decode()
            
        except Exception as e:
            self.logger.error(f"Database field encryption failed for table {table_name}: {str(e)}")
            raise
    
    def rotate_keys(self):
        """Implement key rotation (integrate with your key management system)"""
        self.logger.info("Key rotation should be handled by your secret management system")
        # Clear cache to force key refresh
        self.key_cache.clear()

💡 Why This Fix Works

The vulnerable implementation hardcodes all cryptographic keys, salts, and IVs directly in source code, uses fixed salts that eliminate security benefits, and employs deterministic encryption. The secure version uses AWS Secrets Manager for key storage, generates random salts and nonces, implements proper key derivation, and uses authenticated encryption (AES-GCM).

// Swift iOS - VULNERABLE: Hardcoded cryptographic secrets in mobile app
import Foundation
import CryptoKit
import CommonCrypto

class VulnerableMobileCrypto {
    // NEVER hardcode secrets in mobile apps - they can be reverse engineered!
    private let hardcodedKey = "MobileAppSecretKey123456789012345"  // AES-256 key
    private let fixedSalt = "FixedSaltForAllUsers1234567890123"     // Fixed salt
    private let apiSecret = "sk_mobile_1234567890abcdef"           // API secret
    private let encryptionIV = "1234567890123456"                  // Fixed IV
    
    // Hardcoded certificate pinning keys
    private let pinnedCertificateHash = "sha256:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
    
    func encryptUserData(_ data: String) -> String? {
        let keyData = Data(hardcodedKey.utf8)
        let dataToEncrypt = Data(data.utf8)
        let ivData = Data(encryptionIV.utf8)
        
        var encryptedData = Data(count: dataToEncrypt.count + kCCBlockSizeAES128)
        var bytesEncrypted: size_t = 0
        
        let status = keyData.withUnsafeBytes { keyBytes in
            dataToEncrypt.withUnsafeBytes { dataBytes in
                ivData.withUnsafeBytes { ivBytes in
                    encryptedData.withUnsafeMutableBytes { encryptedBytes in
                        CCCrypt(
                            CCOperation(kCCEncrypt),
                            CCAlgorithm(kCCAlgorithmAES),
                            CCOptions(kCCOptionPKCS7Padding),
                            keyBytes.baseAddress, keyData.count,
                            ivBytes.baseAddress,  // Fixed IV - vulnerable!
                            dataBytes.baseAddress, dataToEncrypt.count,
                            encryptedBytes.baseAddress, encryptedData.count,
                            &bytesEncrypted
                        )
                    }
                }
            }
        }
        
        guard status == kCCSuccess else { return nil }
        encryptedData.removeSubrange(bytesEncrypted...)
        
        return encryptedData.base64EncodedString()
    }
    
    func hashPassword(_ password: String) -> String {
        // Using fixed salt for all users - vulnerable to rainbow tables!
        let saltedPassword = password + fixedSalt
        let inputData = Data(saltedPassword.utf8)
        let hashed = SHA256.hash(data: inputData)
        return Data(hashed).base64EncodedString()
    }
    
    func generateApiSignature(for data: String) -> String {
        // Using hardcoded API secret
        let key = SymmetricKey(data: Data(apiSecret.utf8))
        let signature = HMAC<SHA256>.authenticationCode(for: Data(data.utf8), using: key)
        return Data(signature).base64EncodedString()
    }
    
    // Hardcoded OAuth client secrets (extremely dangerous!)
    func getOAuthClientSecret() -> String {
        return "oauth_client_secret_that_should_not_be_here"
    }
}
// Swift iOS - SECURE: Proper mobile cryptography without hardcoded secrets
import Foundation
import CryptoKit
import Security
import CommonCrypto

class SecureMobileCrypto {
    private let keychain = Keychain()
    private let serverConfig: ServerConfiguration
    
    init(serverConfig: ServerConfiguration) {
        self.serverConfig = serverConfig
    }
    
    // Generate device-specific encryption key
    private func getOrCreateDeviceKey() throws -> Data {
        let keyTag = "com.app.device.encryption.key"
        
        // Try to retrieve existing key from keychain
        if let existingKey = keychain.getData(keyTag) {
            return existingKey
        }
        
        // Generate new device-specific key
        var randomBytes = Data(count: 32)  // 256-bit key
        let result = randomBytes.withUnsafeMutableBytes { bytes in
            SecRandomCopyBytes(kSecRandomDefault, 32, bytes.baseAddress!)
        }
        
        guard result == errSecSuccess else {
            throw CryptoError.keyGenerationFailed
        }
        
        // Store in keychain
        keychain.setData(randomBytes, forKey: keyTag)
        
        return randomBytes
    }
    
    func encryptUserData(_ data: String) throws -> EncryptedData {
        let deviceKey = try getOrCreateDeviceKey()
        let dataToEncrypt = Data(data.utf8)
        
        // Generate random salt and IV for each encryption
        var salt = Data(count: 32)
        var iv = Data(count: 16)
        
        _ = salt.withUnsafeMutableBytes { SecRandomCopyBytes(kSecRandomDefault, 32, $0.baseAddress!) }
        _ = iv.withUnsafeMutableBytes { SecRandomCopyBytes(kSecRandomDefault, 16, $0.baseAddress!) }
        
        // Derive encryption key using PBKDF2
        let derivedKey = try deriveKey(from: deviceKey, salt: salt)
        
        // Encrypt using AES-GCM for authenticated encryption
        let sealedBox = try AES.GCM.seal(dataToEncrypt, using: SymmetricKey(data: derivedKey))
        
        return EncryptedData(
            ciphertext: sealedBox.ciphertext,
            nonce: sealedBox.nonce,
            tag: sealedBox.tag,
            salt: salt
        )
    }
    
    func decryptUserData(_ encryptedData: EncryptedData) throws -> String {
        let deviceKey = try getOrCreateDeviceKey()
        
        // Derive the same key using stored salt
        let derivedKey = try deriveKey(from: deviceKey, salt: encryptedData.salt)
        
        // Reconstruct sealed box and decrypt
        let sealedBox = try AES.GCM.SealedBox(
            nonce: encryptedData.nonce,
            ciphertext: encryptedData.ciphertext,
            tag: encryptedData.tag
        )
        
        let decryptedData = try AES.GCM.open(sealedBox, using: SymmetricKey(data: derivedKey))
        
        guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
            throw CryptoError.decryptionFailed
        }
        
        return decryptedString
    }
    
    private func deriveKey(from masterKey: Data, salt: Data) throws -> Data {
        var derivedKey = Data(count: 32)
        
        let result = derivedKey.withUnsafeMutableBytes { derivedKeyBytes in
            salt.withUnsafeBytes { saltBytes in
                masterKey.withUnsafeBytes { masterKeyBytes in
                    CCKeyDerivationPBKDF(
                        CCPBKDFAlgorithm(kCCPBKDF2),
                        masterKeyBytes.baseAddress, masterKey.count,
                        saltBytes.baseAddress, salt.count,
                        CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256),
                        100000,  // High iteration count
                        derivedKeyBytes.baseAddress, 32
                    )
                }
            }
        }
        
        guard result == kCCSuccess else {
            throw CryptoError.keyDerivationFailed
        }
        
        return derivedKey
    }
    
    func hashPassword(_ password: String) throws -> HashedPassword {
        // Generate random salt for each password
        var salt = Data(count: 32)
        _ = salt.withUnsafeMutableBytes { SecRandomCopyBytes(kSecRandomDefault, 32, $0.baseAddress!) }
        
        let saltedPassword = password + salt.base64EncodedString()
        let inputData = Data(saltedPassword.utf8)
        let hashed = SHA256.hash(data: inputData)
        
        return HashedPassword(
            hash: Data(hashed),
            salt: salt,
            algorithm: "SHA256+Salt"
        )
    }
    
    func generateApiSignature(for data: String) async throws -> String {
        // Get API signing key from server (never store in app)
        let signingKey = try await fetchApiSigningKey()
        
        let key = SymmetricKey(data: signingKey)
        let signature = HMAC<SHA256>.authenticationCode(for: Data(data.utf8), using: key)
        
        return Data(signature).base64EncodedString()
    }
    
    private func fetchApiSigningKey() async throws -> Data {
        // Implement secure key exchange with server
        // Use device certificate or OAuth for authentication
        let request = URLRequest(url: serverConfig.keyExchangeURL)
        // ... implement secure key exchange
        throw CryptoError.notImplemented
    }
    
    // OAuth implementation without client secrets
    func performOAuthFlow() async throws -> OAuthToken {
        // Use PKCE (Proof Key for Code Exchange) for mobile OAuth
        // Never store client secrets in mobile apps
        let codeVerifier = generateCodeVerifier()
        let codeChallenge = generateCodeChallenge(from: codeVerifier)
        
        // Implement PKCE OAuth flow
        // This eliminates the need for client secrets
        throw CryptoError.notImplemented
    }
    
    private func generateCodeVerifier() -> String {
        var bytes = Data(count: 32)
        _ = bytes.withUnsafeMutableBytes { SecRandomCopyBytes(kSecRandomDefault, 32, $0.baseAddress!) }
        return bytes.base64URLEncodedString()
    }
    
    private func generateCodeChallenge(from verifier: String) -> String {
        let challenge = SHA256.hash(data: Data(verifier.utf8))
        return Data(challenge).base64URLEncodedString()
    }
}

// Supporting data structures
struct EncryptedData {
    let ciphertext: Data
    let nonce: AES.GCM.Nonce
    let tag: Data
    let salt: Data
}

struct HashedPassword {
    let hash: Data
    let salt: Data
    let algorithm: String
}

struct ServerConfiguration {
    let keyExchangeURL: URL
    let baseURL: URL
}

enum CryptoError: Error {
    case keyGenerationFailed
    case keyDerivationFailed
    case decryptionFailed
    case notImplemented
}

💡 Why This Fix Works

The vulnerable implementation hardcodes encryption keys, salts, API secrets, and OAuth credentials directly in the mobile app where they can be easily extracted through reverse engineering. The secure version uses device keychain storage, generates random salts and nonces, implements proper key derivation, uses authenticated encryption, and follows PKCE OAuth flow to eliminate client secret requirements.

Why it happens

Developers embed encryption keys directly in application source code for convenience during development or due to misunderstanding of proper key management. These keys remain in the codebase and version control, making all encrypted data vulnerable to anyone with code access.

Root causes

Hardcoded Encryption Keys in Source Code

Developers embed encryption keys directly in application source code for convenience during development or due to misunderstanding of proper key management. These keys remain in the codebase and version control, making all encrypted data vulnerable to anyone with code access.

Preview example – JAVA
// Java - VULNERABLE: Hardcoded AES encryption key
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class DataEncryption {
    // NEVER hardcode encryption keys!
    private static final String HARDCODED_KEY = "MySecretKey12345"; // 128-bit key
    private static final String AES_KEY_256 = "MyVerySecretKey1234567890123456"; // 256-bit
    
    public String encryptData(String plaintext) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(AES_KEY_256.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        
        byte[] encrypted = cipher.doFinal(plaintext.getBytes());
        return Base64.getEncoder().encodeToString(encrypted);
    }
}

Fixed Cryptographic Salts and IVs

Using fixed or hardcoded salts for password hashing or static initialization vectors for encryption. This eliminates the security benefits of salting and allows rainbow table attacks against password hashes or pattern recognition in encrypted data.

Preview example – PYTHON
// Python - VULNERABLE: Fixed salts and IVs
import hashlib
import hmac
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import base64

class VulnerableCrypto:
    # NEVER use fixed salts!
    FIXED_SALT = b'fixed_salt_123456789012345678901234'  # Always the same
    FIXED_IV = b'1234567890123456'  # Static IV for AES
    MASTER_KEY = b'master_key_that_should_not_be_here!!'  # Hardcoded key
    
    def hash_password(self, password):
        # Using fixed salt defeats the purpose of salting
        return hashlib.pbkdf2_hmac('sha256', password.encode(), self.FIXED_SALT, 100000)
    
    def generate_hmac(self, data):
        # Hardcoded HMAC key
        return hmac.new(self.MASTER_KEY, data.encode(), hashlib.sha256).hexdigest()
    
    def encrypt_with_fixed_iv(self, data):
        # Using static IV makes encryption deterministic
        from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
        cipher = Cipher(algorithms.AES(self.MASTER_KEY[:32]), modes.CBC(self.FIXED_IV))
        encryptor = cipher.encryptor()
        # This will always produce the same ciphertext for the same plaintext!
        return encryptor.update(data.encode()) + encryptor.finalize()

JWT Signing Keys in Configuration Files

JSON Web Token (JWT) signing secrets stored directly in configuration files, environment files committed to version control, or hardcoded in application logic. This allows attackers to forge valid JWTs and bypass authentication entirely.

Preview example – JAVASCRIPT
// Node.js - VULNERABLE: Hardcoded JWT secrets
const jwt = require('jsonwebtoken');
const express = require('express');

// NEVER hardcode JWT secrets!
const JWT_SECRET = 'my_super_secret_jwt_key_123456789';
const REFRESH_SECRET = 'refresh_token_secret_key_987654321';

class AuthService {
    generateToken(userId, role) {
        const payload = {
            userId: userId,
            role: role,
            iat: Date.now()
        };
        
        // Using hardcoded secret for JWT signing
        return jwt.sign(payload, JWT_SECRET, { expiresIn: '1h' });
    }
    
    generateRefreshToken(userId) {
        return jwt.sign({ userId }, REFRESH_SECRET, { expiresIn: '7d' });
    }
    
    verifyToken(token) {
        try {
            return jwt.verify(token, JWT_SECRET);
        } catch (error) {
            return null;
        }
    }
    
    // API key hardcoded for external service authentication
    getExternalApiKey() {
        return 'sk-1234567890abcdef'; // NEVER hardcode API keys!
    }
}

Database and Application Configuration Keys

Cryptographic keys stored in configuration files, database connection strings, or application settings that are committed to version control or deployed with the application. This includes database encryption keys, SSL/TLS private keys, and API secrets.

Preview example – YAML
# application.yml - VULNERABLE: Hardcoded cryptographic configuration
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: admin
    password: admin123
    # Database encryption key hardcoded
    encryption-key: "AES256:my_database_encryption_key_12345"
    
app:
  security:
    # JWT secrets in configuration
    jwt:
      secret: "hardcoded_jwt_secret_key_that_should_not_be_here"
      refresh-secret: "hardcoded_refresh_secret_key_123456789"
    
    # Encryption configuration
    encryption:
      master-key: "master_encryption_key_32_characters!"
      iv-salt: "static_iv_salt_16_chars"
      
    # External API keys
    external:
      stripe-secret: "sk_live_51234567890abcdefghijklmnop"
      sendgrid-api-key: "SG.1234567890abcdefghijklmnopqrstuvwxyz"
      
ssl:
  key-store-password: "keystore_password_123"
  trust-store-password: "truststore_password_456"

Fixes

1

Implement Environment-Based Key Management

Store all cryptographic keys, secrets, and salts in environment variables or secure configuration systems. Never commit these values to version control. Use different keys for different environments (development, staging, production) and implement proper key rotation procedures.

View implementation – JAVA
// Java - SECURE: Environment-based key management
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

public class SecureDataEncryption {
    private final SecretKeySpec keySpec;
    private final SecureRandom secureRandom;
    
    public SecureDataEncryption() {
        // Load key from environment variable
        String keyString = System.getenv("AES_ENCRYPTION_KEY");
        if (keyString == null || keyString.length() != 32) {
            throw new IllegalStateException("AES_ENCRYPTION_KEY environment variable must be 32 characters");
        }
        
        this.keySpec = new SecretKeySpec(keyString.getBytes(), "AES");
        this.secureRandom = new SecureRandom();
    }
    
    public EncryptionResult encryptData(String plaintext) throws Exception {
        // Generate random IV for each encryption
        byte[] iv = new byte[16];
        secureRandom.nextBytes(iv);
        
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv));
        
        byte[] encrypted = cipher.doFinal(plaintext.getBytes());
        
        return new EncryptionResult(encrypted, iv);
    }
    
    public static class EncryptionResult {
        public final byte[] ciphertext;
        public final byte[] iv;
        
        public EncryptionResult(byte[] ciphertext, byte[] iv) {
            this.ciphertext = ciphertext;
            this.iv = iv;
        }
    }
}
2

Use Dedicated Secret Management Systems

Implement enterprise-grade secret management solutions like AWS Secrets Manager, Azure Key Vault, HashiCorp Vault, or Kubernetes Secrets. These systems provide encryption at rest, access controls, audit logging, automatic rotation, and centralized secret management.

View implementation – PYTHON
// Python - SECURE: Using AWS Secrets Manager
import boto3
import json
import os
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.fernet import Fernet
import secrets

class SecureCryptoManager:
    def __init__(self):
        self.secrets_client = boto3.client('secretsmanager')
        self.cache = {}  # Simple cache for secrets (implement TTL in production)
    
    def get_secret(self, secret_name):
        """Retrieve secret from AWS Secrets Manager with caching"""
        if secret_name in self.cache:
            return self.cache[secret_name]
        
        try:
            response = self.secrets_client.get_secret_value(SecretId=secret_name)
            secret_value = json.loads(response['SecretString'])
            self.cache[secret_name] = secret_value
            return secret_value
        except Exception as e:
            raise Exception(f"Failed to retrieve secret {secret_name}: {str(e)}")
    
    def generate_random_salt(self, length=32):
        """Generate cryptographically secure random salt"""
        return secrets.token_bytes(length)
    
    def hash_password(self, password, salt=None):
        """Hash password with random salt using PBKDF2"""
        if salt is None:
            salt = self.generate_random_salt()
        
        # Get key derivation parameters from secrets manager
        kdf_config = self.get_secret('password-hashing-config')
        
        kdf = PBKDF2HMAC(
            algorithm=hashes.SHA256(),
            length=32,
            salt=salt,
            iterations=kdf_config['iterations'],  # e.g., 100000
            backend=default_backend()
        )
        
        key = kdf.derive(password.encode())
        return {
            'hash': key,
            'salt': salt,
            'iterations': kdf_config['iterations']
        }
    
    def get_encryption_key(self, key_name):
        """Get encryption key from secrets manager"""
        secret = self.get_secret(f'encryption-keys/{key_name}')
        return secret['key'].encode()
    
    def encrypt_data(self, data, key_name):
        """Encrypt data using key from secrets manager"""
        key = self.get_encryption_key(key_name)
        f = Fernet(key)
        return f.encrypt(data.encode())
    
    def decrypt_data(self, encrypted_data, key_name):
        """Decrypt data using key from secrets manager"""
        key = self.get_encryption_key(key_name)
        f = Fernet(key)
        return f.decrypt(encrypted_data).decode()
3

Implement Secure JWT Token Management

Use environment variables or secret management systems for JWT signing keys. Implement key rotation, use strong signing algorithms (RS256 or ES256), and never expose signing keys to client-side code. Consider using asymmetric keys for better security.

View implementation – JAVASCRIPT
// Node.js - SECURE: Proper JWT secret management
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const fs = require('fs');

class SecureAuthService {
    constructor() {
        this.validateEnvironment();
        this.loadKeys();
    }
    
    validateEnvironment() {
        const requiredEnvVars = [
            'JWT_PRIVATE_KEY_PATH',
            'JWT_PUBLIC_KEY_PATH',
            'JWT_KEY_ID',
            'JWT_ISSUER'
        ];
        
        const missing = requiredEnvVars.filter(env => !process.env[env]);
        if (missing.length > 0) {
            throw new Error(`Missing environment variables: ${missing.join(', ')}`);
        }
    }
    
    loadKeys() {
        try {
            // Use asymmetric keys (RS256) for better security
            this.privateKey = fs.readFileSync(process.env.JWT_PRIVATE_KEY_PATH, 'utf8');
            this.publicKey = fs.readFileSync(process.env.JWT_PUBLIC_KEY_PATH, 'utf8');
            this.keyId = process.env.JWT_KEY_ID;
            this.issuer = process.env.JWT_ISSUER;
        } catch (error) {
            throw new Error(`Failed to load JWT keys: ${error.message}`);
        }
    }
    
    generateToken(userId, role, expiresIn = '1h') {
        const payload = {
            sub: userId,
            role: role,
            iss: this.issuer,
            aud: process.env.JWT_AUDIENCE || 'api',
            jti: this.generateJti() // Unique token ID
        };
        
        const options = {
            algorithm: 'RS256',
            expiresIn: expiresIn,
            keyid: this.keyId,
            issuer: this.issuer
        };
        
        return jwt.sign(payload, this.privateKey, options);
    }
    
    verifyToken(token) {
        const options = {
            algorithms: ['RS256'],
            issuer: this.issuer,
            audience: process.env.JWT_AUDIENCE || 'api'
        };
        
        try {
            return jwt.verify(token, this.publicKey, options);
        } catch (error) {
            throw new Error(`Token verification failed: ${error.message}`);
        }
    }
    
    generateJti() {
        // Generate unique token identifier
        return crypto.randomBytes(16).toString('hex');
    }
    
    // Key rotation support
    rotateKeys() {
        // Implement key rotation logic
        // 1. Generate new key pair
        // 2. Update key storage
        // 3. Gradually phase out old keys
        console.log('Key rotation should be handled by your secret management system');
    }
}
4

Secure Configuration Management

Separate configuration from code using external configuration sources. Use placeholder values in configuration files and inject real secrets at runtime. Implement configuration validation and never commit sensitive configuration to version control.

View implementation – YAML
# application.yml - SECURE: Using environment variable placeholders
spring:
  datasource:
    url: ${DATABASE_URL}
    username: ${DATABASE_USERNAME}
    password: ${DATABASE_PASSWORD}
    
app:
  security:
    jwt:
      # Reference to external key management
      private-key-path: ${JWT_PRIVATE_KEY_PATH}
      public-key-path: ${JWT_PUBLIC_KEY_PATH}
      key-id: ${JWT_KEY_ID}
      issuer: ${JWT_ISSUER}
    
    encryption:
      # Keys managed externally
      key-management-service: ${KEY_MANAGEMENT_SERVICE_URL}
      key-namespace: ${ENCRYPTION_KEY_NAMESPACE}
      
    external:
      # API keys from environment or secret manager
      stripe-secret: ${STRIPE_SECRET_KEY}
      sendgrid-api-key: ${SENDGRID_API_KEY}
      
ssl:
  key-store-path: ${SSL_KEYSTORE_PATH}
  key-store-password: ${SSL_KEYSTORE_PASSWORD}
  trust-store-path: ${SSL_TRUSTSTORE_PATH}
  trust-store-password: ${SSL_TRUSTSTORE_PASSWORD}

---
# Java Configuration Class - SECURE
@Configuration
@Validated
public class SecurityConfig {
    
    @Value("${app.security.jwt.private-key-path}")
    @NotBlank
    private String jwtPrivateKeyPath;
    
    @Value("${app.security.jwt.public-key-path}")
    @NotBlank
    private String jwtPublicKeyPath;
    
    @Value("${app.security.encryption.key-management-service}")
    @NotBlank
    private String keyManagementServiceUrl;
    
    @PostConstruct
    public void validateConfiguration() {
        // Validate that all required files exist
        if (!Files.exists(Paths.get(jwtPrivateKeyPath))) {
            throw new IllegalStateException("JWT private key file not found: " + jwtPrivateKeyPath);
        }
        
        if (!Files.exists(Paths.get(jwtPublicKeyPath))) {
            throw new IllegalStateException("JWT public key file not found: " + jwtPublicKeyPath);
        }
    }
}

Detect This Vulnerability in Your Code

Sourcery automatically identifies hardcoded cryptographic keys and salts and many other security issues in your codebase.