Inadequate Encryption Strength

Description

Inadequate Encryption Strength occurs when software uses a cryptographic algorithm or key length that is insufficient to protect data according to current security standards. This includes using deprecated algorithms (DES, MD5, SHA1 for security), keys that are too short (512-bit RSA, 64-bit symmetric), or encryption modes that are vulnerable (ECB mode). Even when encryption is present, weak encryption provides a false sense of security as it can be broken with modern computing resources.

Risk

Weak encryption can be broken by attackers with moderate resources. DES keys can be brute-forced in hours. MD5 and SHA1 collisions can be generated practically. 512-bit or 1024-bit RSA keys can be factored. ECB mode reveals patterns in data. As computing power increases, encryption that was once adequate becomes vulnerable. Nation-state actors and well-funded criminal organizations can break weak encryption that protects high-value targets.

Solution

Use AES-256 for symmetric encryption. Use RSA-2048 minimum (RSA-4096 for long-term security) or ECDSA/EdDSA with appropriate curves. Use SHA-256 or SHA-3 for hashing, Argon2/bcrypt/scrypt for passwords. Avoid MD5, SHA1, DES, 3DES, RC4, and Blowfish. Use GCM or CCM mode, never ECB. Follow NIST guidelines and industry best practices. Regularly review and update cryptographic implementations as standards evolve.

Common Consequences

ImpactDetails
ConfidentialityScope: Data Exposure

Weak encryption can be broken, exposing encrypted data to attackers.
IntegrityScope: Forgery

Weak hashing allows attackers to create collisions and forge signatures.
AuthenticationScope: Impersonation

Weak key sizes allow key recovery, enabling impersonation.

Example Code + Solution Code

Vulnerable Code

# VULNERABLE: DES encryption (56-bit key)
from Crypto.Cipher import DES

def encrypt_weak(data, key):
    cipher = DES.new(key[:8], DES.MODE_ECB)  # DES with ECB mode!
    return cipher.encrypt(pad(data))

# VULNERABLE: MD5 for password hashing
import hashlib

def hash_password_weak(password):
    return hashlib.md5(password.encode()).hexdigest()  # MD5!

# VULNERABLE: Short RSA key
from Crypto.PublicKey import RSA

def generate_weak_key():
    return RSA.generate(512)  # Way too short!

# VULNERABLE: SHA1 for signatures
def sign_data_weak(data, key):
    h = SHA.new(data)  # SHA1 is deprecated
    signature = pkcs1_15.new(key).sign(h)
    return signature

# VULNERABLE: Weak PRNG
import random

def generate_token_weak():
    return random.randint(0, 999999)  # Predictable!
// VULNERABLE: DES encryption
public class WeakCrypto {

    public byte[] encryptWeak(byte[] data, byte[] key) throws Exception {
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");  // DES + ECB!
        SecretKeySpec keySpec = new SecretKeySpec(key, "DES");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        return cipher.doFinal(data);
    }

    // VULNERABLE: MD5 hashing
    public String hashPasswordWeak(String password) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] hash = md.digest(password.getBytes());
        return bytesToHex(hash);
    }

    // VULNERABLE: Short RSA key
    public KeyPair generateWeakKeyPair() throws Exception {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(1024);  // Too short for modern security
        return keyGen.generateKeyPair();
    }

    // VULNERABLE: RC4 encryption
    public byte[] encryptRC4(byte[] data, byte[] key) throws Exception {
        Cipher cipher = Cipher.getInstance("RC4");  // RC4 is broken
        SecretKeySpec keySpec = new SecretKeySpec(key, "RC4");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        return cipher.doFinal(data);
    }
}
// VULNERABLE: Weak crypto in Node.js
const crypto = require('crypto');

// DES encryption
function encryptWeakDES(data, key) {
    const cipher = crypto.createCipheriv('des', key.slice(0, 8), Buffer.alloc(8));
    return cipher.update(data) + cipher.final();
}

// MD5 hashing
function hashWeakMD5(data) {
    return crypto.createHash('md5').update(data).digest('hex');
}

// Short key generation
function generateWeakKey() {
    return crypto.randomBytes(8);  // 64-bit key
}

// RC4
function encryptWeakRC4(data, key) {
    const cipher = crypto.createCipheriv('rc4', key, '');
    return cipher.update(data) + cipher.final();
}

Fixed Code

# SAFE: AES-256-GCM encryption
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.backends import default_backend
import os
import argon2

def encrypt_strong(data, key):
    # Generate random nonce
    nonce = os.urandom(12)
    aesgcm = AESGCM(key)  # 256-bit key
    ciphertext = aesgcm.encrypt(nonce, data, None)
    return nonce + ciphertext

def decrypt_strong(encrypted, key):
    nonce = encrypted[:12]
    ciphertext = encrypted[12:]
    aesgcm = AESGCM(key)
    return aesgcm.decrypt(nonce, ciphertext, None)

# SAFE: Argon2 for password hashing
def hash_password_strong(password):
    ph = argon2.PasswordHasher(
        time_cost=3,
        memory_cost=65536,
        parallelism=4
    )
    return ph.hash(password)

def verify_password_strong(hash, password):
    ph = argon2.PasswordHasher()
    try:
        ph.verify(hash, password)
        return True
    except:
        return False

# SAFE: Strong RSA key
from cryptography.hazmat.primitives.asymmetric import rsa

def generate_strong_key():
    return rsa.generate_private_key(
        public_exponent=65537,
        key_size=4096,  # Strong key size
        backend=default_backend()
    )

# SAFE: SHA-256 for signatures
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

def sign_data_strong(data, private_key):
    signature = private_key.sign(
        data,
        padding.PSS(
            mgf=padding.MGF1(hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH
        ),
        hashes.SHA256()  # SHA-256
    )
    return signature

# SAFE: Secure random
def generate_token_strong():
    return os.urandom(32).hex()  # 256-bit cryptographically secure
// SAFE: AES-256-GCM
public class StrongCrypto {

    private static final int GCM_IV_LENGTH = 12;
    private static final int GCM_TAG_LENGTH = 128;
    private static final int AES_KEY_SIZE = 256;

    public byte[] encryptStrong(byte[] data, SecretKey key) throws Exception {
        byte[] iv = new byte[GCM_IV_LENGTH];
        SecureRandom random = SecureRandom.getInstanceStrong();
        random.nextBytes(iv);

        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec parameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);

        byte[] ciphertext = cipher.doFinal(data);

        // Prepend IV
        byte[] result = new byte[iv.length + ciphertext.length];
        System.arraycopy(iv, 0, result, 0, iv.length);
        System.arraycopy(ciphertext, 0, result, iv.length, ciphertext.length);

        return result;
    }

    // SAFE: Argon2 for passwords
    public String hashPasswordStrong(String password) {
        Argon2PasswordEncoder encoder = new Argon2PasswordEncoder(
            16,     // salt length
            32,     // hash length
            1,      // parallelism
            65536,  // memory (64 MB)
            3       // iterations
        );
        return encoder.encode(password);
    }

    // SAFE: Strong RSA
    public KeyPair generateStrongKeyPair() throws Exception {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(4096, SecureRandom.getInstanceStrong());
        return keyGen.generateKeyPair();
    }

    // SAFE: ECDSA with P-256
    public KeyPair generateECKeyPair() throws Exception {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
        ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1");
        keyGen.initialize(ecSpec, SecureRandom.getInstanceStrong());
        return keyGen.generateKeyPair();
    }

    // SAFE: Generate strong AES key
    public SecretKey generateAESKey() throws Exception {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(AES_KEY_SIZE, SecureRandom.getInstanceStrong());
        return keyGen.generateKey();
    }
}
// SAFE: Strong crypto in Node.js
const crypto = require('crypto');
const argon2 = require('argon2');

// AES-256-GCM
function encryptStrong(data, key) {
    const iv = crypto.randomBytes(12);  // 96-bit IV for GCM
    const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);

    let encrypted = cipher.update(data);
    encrypted = Buffer.concat([encrypted, cipher.final()]);

    const authTag = cipher.getAuthTag();

    // Return IV + authTag + ciphertext
    return Buffer.concat([iv, authTag, encrypted]);
}

function decryptStrong(encrypted, key) {
    const iv = encrypted.slice(0, 12);
    const authTag = encrypted.slice(12, 28);
    const ciphertext = encrypted.slice(28);

    const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
    decipher.setAuthTag(authTag);

    let decrypted = decipher.update(ciphertext);
    decrypted = Buffer.concat([decrypted, decipher.final()]);

    return decrypted;
}

// Argon2 for passwords
async function hashPasswordStrong(password) {
    return await argon2.hash(password, {
        type: argon2.argon2id,
        memoryCost: 65536,
        timeCost: 3,
        parallelism: 4
    });
}

async function verifyPasswordStrong(hash, password) {
    return await argon2.verify(hash, password);
}

// Strong key generation
function generateStrongKey() {
    return crypto.randomBytes(32);  // 256-bit key
}

// SHA-256
function hashStrong(data) {
    return crypto.createHash('sha256').update(data).digest('hex');
}

Exploited in the Wild

DROWN Attack (2016)

The DROWN attack exploited servers still supporting SSLv2 with weak export-grade cryptography, allowing decryption of TLS connections. 33% of all HTTPS servers were vulnerable.

FREAK Attack (2015)

FREAK exploited weak export-grade RSA keys (512-bit) to break TLS connections. Clients could be forced to use weak cryptography through man-in-the-middle attacks.

SHA1 Collision (2017)

Google demonstrated the first practical SHA1 collision attack, creating two different PDFs with the same SHA1 hash, effectively breaking SHA1 for security purposes.


Tools to test/exploit

  • testssl.sh — comprehensive TLS/SSL testing.

  • Hashcat — password hash cracking to test strength.

  • OpenSSL — analyze cryptographic configurations.

  • Nmap — with ssl-enum-ciphers script.


CVE Examples


References

  1. MITRE. "CWE-326: Inadequate Encryption Strength." https://cwe.mitre.org/data/definitions/326.html

  2. NIST. "Transitioning the Use of Cryptographic Algorithms and Key Lengths." https://csrc.nist.gov/publications/detail/sp/800-131a/rev-2/final