Legacy System Compatibility
Applications use DES to maintain compatibility with legacy systems that only support older encryption standards, without considering the security implications.
The Data Encryption Standard (DES) is a deprecated and insecure symmetric encryption algorithm with a 56-bit key size that can be broken through brute force attacks in hours. Using DES exposes encrypted data to unauthorized access, violating confidentiality and potentially enabling data theft or tampering.
# VULNERABLE: Using insecure DES encryption
from Crypto.Cipher import DES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
import base64
import hashlib
# VULNERABLE: DES cipher implementation
class VulnerableDESEncryption:
def __init__(self, password):
# VULNERABLE: DES only supports 8-byte keys
self.key = hashlib.md5(password.encode()).digest()[:8]
def encrypt(self, plaintext):
# VULNERABLE: DES cipher with weak 56-bit effective key
cipher = DES.new(self.key, DES.MODE_CBC)
# Pad plaintext to 8-byte blocks
padded_text = pad(plaintext.encode(), DES.block_size)
# VULNERABLE: DES encryption is easily breakable
ciphertext = cipher.encrypt(padded_text)
# Return IV + ciphertext
return base64.b64encode(cipher.iv + ciphertext).decode()
def decrypt(self, encrypted_data):
encrypted_bytes = base64.b64decode(encrypted_data)
# Extract IV and ciphertext
iv = encrypted_bytes[:DES.block_size]
ciphertext = encrypted_bytes[DES.block_size:]
# VULNERABLE: DES decryption
cipher = DES.new(self.key, DES.MODE_CBC, iv=iv)
padded_plaintext = cipher.decrypt(ciphertext)
# Remove padding
return unpad(padded_plaintext, DES.block_size).decode()
# VULNERABLE: Using DES for file encryption
def vulnerable_encrypt_file(filename, password):
des_crypto = VulnerableDESEncryption(password)
with open(filename, 'r') as file:
content = file.read()
# VULNERABLE: DES encryption of file content
encrypted_content = des_crypto.encrypt(content)
with open(filename + '.des', 'w') as encrypted_file:
encrypted_file.write(encrypted_content)
print(f"File encrypted with DES: {filename}.des")
# VULNERABLE: DES for sensitive data storage
class VulnerableUserData:
def __init__(self, master_password):
self.des_crypto = VulnerableDESEncryption(master_password)
def store_credit_card(self, card_number, cvv, expiry):
# VULNERABLE: DES encryption of sensitive financial data
encrypted_card = self.des_crypto.encrypt(card_number)
encrypted_cvv = self.des_crypto.encrypt(cvv)
encrypted_expiry = self.des_crypto.encrypt(expiry)
return {
'card_number': encrypted_card,
'cvv': encrypted_cvv,
'expiry': encrypted_expiry
}
def retrieve_credit_card(self, encrypted_data):
# VULNERABLE: DES decryption
card_number = self.des_crypto.decrypt(encrypted_data['card_number'])
cvv = self.des_crypto.decrypt(encrypted_data['cvv'])
expiry = self.des_crypto.decrypt(encrypted_data['expiry'])
return {
'card_number': card_number,
'cvv': cvv,
'expiry': expiry
}
# VULNERABLE: DES in network communication
def vulnerable_secure_communication(message, shared_key):
# VULNERABLE: DES for encrypting network traffic
des_key = hashlib.sha1(shared_key.encode()).digest()[:8]
cipher = DES.new(des_key, DES.MODE_ECB) # VULNERABLE: ECB mode too
padded_message = pad(message.encode(), DES.block_size)
encrypted_message = cipher.encrypt(padded_message)
return base64.b64encode(encrypted_message).decode()
# VULNERABLE: DES for database encryption
import sqlite3
class VulnerableDatabase:
def __init__(self, db_path, encryption_key):
self.conn = sqlite3.connect(db_path)
self.des_crypto = VulnerableDESEncryption(encryption_key)
def store_user_secret(self, user_id, secret):
# VULNERABLE: DES encryption of user secrets
encrypted_secret = self.des_crypto.encrypt(secret)
cursor = self.conn.cursor()
cursor.execute(
"INSERT INTO user_secrets (user_id, encrypted_secret) VALUES (?, ?)",
(user_id, encrypted_secret)
)
self.conn.commit()
def get_user_secret(self, user_id):
cursor = self.conn.cursor()
cursor.execute(
"SELECT encrypted_secret FROM user_secrets WHERE user_id = ?",
(user_id,)
)
result = cursor.fetchone()
if result:
# VULNERABLE: DES decryption
return self.des_crypto.decrypt(result[0])
return None
# VULNERABLE: Example usage
if __name__ == "__main__":
# VULNERABLE: DES encryption examples
password = "mypassword123"
# File encryption
vulnerable_encrypt_file("sensitive_data.txt", password)
# User data encryption
user_data = VulnerableUserData(password)
encrypted_card = user_data.store_credit_card(
"4532-1234-5678-9012",
"123",
"12/25"
)
# Network communication
encrypted_msg = vulnerable_secure_communication(
"Secret meeting at midnight",
"shared_secret_key"
)
print("VULNERABLE: All data encrypted with weak DES algorithm!")# SECURE: Using strong AES encryption
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Hash import SHA256, HMAC
import base64
import os
import json
import secrets
# SECURE: AES encryption with proper key derivation
class SecureAESEncryption:
def __init__(self, password, salt=None):
# SECURE: Generate random salt if not provided
if salt is None:
self.salt = get_random_bytes(32)
else:
self.salt = salt
# SECURE: Use PBKDF2 for key derivation with strong parameters
self.key = PBKDF2(
password.encode(),
self.salt,
key_len=32, # AES-256 key
count=100000, # Strong iteration count
hmac_hash_module=SHA256
)
def encrypt(self, plaintext):
# SECURE: AES-256 in GCM mode (authenticated encryption)
cipher = AES.new(self.key, AES.MODE_GCM)
# SECURE: AES handles padding automatically in GCM mode
ciphertext, auth_tag = cipher.encrypt_and_digest(plaintext.encode())
# Return salt + nonce + auth_tag + ciphertext
encrypted_data = {
'salt': base64.b64encode(self.salt).decode(),
'nonce': base64.b64encode(cipher.nonce).decode(),
'auth_tag': base64.b64encode(auth_tag).decode(),
'ciphertext': base64.b64encode(ciphertext).decode()
}
return base64.b64encode(json.dumps(encrypted_data).encode()).decode()
def decrypt(self, encrypted_data):
# Parse encrypted data structure
data_dict = json.loads(base64.b64decode(encrypted_data).decode())
salt = base64.b64decode(data_dict['salt'])
nonce = base64.b64decode(data_dict['nonce'])
auth_tag = base64.b64decode(data_dict['auth_tag'])
ciphertext = base64.b64decode(data_dict['ciphertext'])
# Verify salt matches (for key derivation)
if salt != self.salt:
# Re-derive key with correct salt
temp_crypto = SecureAESEncryption(self.password, salt)
return temp_crypto._decrypt_with_key(nonce, auth_tag, ciphertext)
return self._decrypt_with_key(nonce, auth_tag, ciphertext)
def _decrypt_with_key(self, nonce, auth_tag, ciphertext):
# SECURE: AES-256 GCM decryption with authentication
cipher = AES.new(self.key, AES.MODE_GCM, nonce=nonce)
try:
# SECURE: Verify authenticity before decryption
plaintext = cipher.decrypt_and_verify(ciphertext, auth_tag)
return plaintext.decode()
except ValueError as e:
raise ValueError("Authentication failed - data may be tampered") from e
# SECURE: File encryption with AES
def secure_encrypt_file(filename, password):
aes_crypto = SecureAESEncryption(password)
try:
with open(filename, 'r', encoding='utf-8') as file:
content = file.read()
except UnicodeDecodeError:
# Handle binary files
with open(filename, 'rb') as file:
content = base64.b64encode(file.read()).decode()
# SECURE: AES-256-GCM encryption
encrypted_content = aes_crypto.encrypt(content)
encrypted_filename = filename + '.aes'
with open(encrypted_filename, 'w') as encrypted_file:
encrypted_file.write(encrypted_content)
# SECURE: Securely overwrite original file
secure_delete_file(filename)
print(f"File securely encrypted with AES-256: {encrypted_filename}")
return encrypted_filename
def secure_decrypt_file(encrypted_filename, password, output_filename=None):
if not output_filename:
output_filename = encrypted_filename.replace('.aes', '')
with open(encrypted_filename, 'r') as file:
encrypted_content = file.read()
aes_crypto = SecureAESEncryption(password)
try:
decrypted_content = aes_crypto.decrypt(encrypted_content)
# Check if content was base64 encoded (binary file)
try:
binary_content = base64.b64decode(decrypted_content)
with open(output_filename, 'wb') as file:
file.write(binary_content)
except:
# Text file
with open(output_filename, 'w', encoding='utf-8') as file:
file.write(decrypted_content)
print(f"File decrypted successfully: {output_filename}")
return output_filename
except ValueError as e:
print(f"Decryption failed: {e}")
return None
# SECURE: User data encryption with AES
class SecureUserData:
def __init__(self, master_password):
self.master_password = master_password
def store_credit_card(self, card_number, cvv, expiry):
# SECURE: Separate encryption for each field with unique salts
card_crypto = SecureAESEncryption(self.master_password)
cvv_crypto = SecureAESEncryption(self.master_password)
expiry_crypto = SecureAESEncryption(self.master_password)
encrypted_data = {
'card_number': card_crypto.encrypt(card_number),
'cvv': cvv_crypto.encrypt(cvv),
'expiry': expiry_crypto.encrypt(expiry),
'timestamp': secrets.token_hex(16) # Prevent replay attacks
}
return encrypted_data
def retrieve_credit_card(self, encrypted_data):
try:
# SECURE: Separate decryption instances
card_crypto = SecureAESEncryption(self.master_password)
cvv_crypto = SecureAESEncryption(self.master_password)
expiry_crypto = SecureAESEncryption(self.master_password)
decrypted_data = {
'card_number': card_crypto.decrypt(encrypted_data['card_number']),
'cvv': cvv_crypto.decrypt(encrypted_data['cvv']),
'expiry': expiry_crypto.decrypt(encrypted_data['expiry'])
}
return decrypted_data
except (ValueError, KeyError) as e:
print(f"Failed to decrypt credit card data: {e}")
return None
# SECURE: Network communication with AES
class SecureNetworkCrypto:
def __init__(self, shared_secret):
self.shared_secret = shared_secret
def encrypt_message(self, message):
# SECURE: AES-256-GCM for network messages
crypto = SecureAESEncryption(self.shared_secret)
return crypto.encrypt(message)
def decrypt_message(self, encrypted_message):
crypto = SecureAESEncryption(self.shared_secret)
return crypto.decrypt(encrypted_message)
def create_secure_session_key(self):
# SECURE: Generate ephemeral session key
session_key = secrets.token_hex(32)
encrypted_session_key = self.encrypt_message(session_key)
return session_key, encrypted_session_key
# SECURE: Database encryption with AES
import sqlite3
import threading
class SecureDatabase:
def __init__(self, db_path, encryption_key):
self.db_path = db_path
self.encryption_key = encryption_key
self._local = threading.local()
# Initialize database schema
self._init_database()
def _get_connection(self):
if not hasattr(self._local, 'conn'):
self._local.conn = sqlite3.connect(self.db_path)
return self._local.conn
def _init_database(self):
conn = self._get_connection()
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS user_secrets (
user_id TEXT PRIMARY KEY,
encrypted_secret TEXT NOT NULL,
salt TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
def store_user_secret(self, user_id, secret):
# SECURE: AES-256 encryption with unique salt per entry
crypto = SecureAESEncryption(self.encryption_key)
encrypted_secret = crypto.encrypt(secret)
salt = base64.b64encode(crypto.salt).decode()
conn = self._get_connection()
cursor = conn.cursor()
cursor.execute('''
INSERT OR REPLACE INTO user_secrets
(user_id, encrypted_secret, salt, updated_at)
VALUES (?, ?, ?, CURRENT_TIMESTAMP)
''', (user_id, encrypted_secret, salt))
conn.commit()
def get_user_secret(self, user_id):
conn = self._get_connection()
cursor = conn.cursor()
cursor.execute(
"SELECT encrypted_secret, salt FROM user_secrets WHERE user_id = ?",
(user_id,)
)
result = cursor.fetchone()
if result:
encrypted_secret, salt_b64 = result
salt = base64.b64decode(salt_b64)
# SECURE: Use stored salt for decryption
crypto = SecureAESEncryption(self.encryption_key, salt)
try:
return crypto.decrypt(encrypted_secret)
except ValueError as e:
print(f"Failed to decrypt secret for user {user_id}: {e}")
return None
return None
def delete_user_secret(self, user_id):
conn = self._get_connection()
cursor = conn.cursor()
cursor.execute(
"DELETE FROM user_secrets WHERE user_id = ?",
(user_id,)
)
conn.commit()
return cursor.rowcount > 0
# SECURE: Utility functions
def secure_delete_file(filename):
"""Securely overwrite and delete a file"""
try:
file_size = os.path.getsize(filename)
# Overwrite with random data multiple times
with open(filename, 'r+b') as file:
for _ in range(3):
file.seek(0)
file.write(os.urandom(file_size))
file.flush()
os.fsync(file.fileno())
os.remove(filename)
except OSError as e:
print(f"Warning: Could not securely delete {filename}: {e}")
def generate_secure_password(length=32):
"""Generate a cryptographically secure random password"""
import string
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
return ''.join(secrets.choice(alphabet) for _ in range(length))
# SECURE: Example usage
if __name__ == "__main__":
# SECURE: AES encryption examples
password = generate_secure_password()
print(f"Generated secure password: {password}")
# File encryption with AES
if os.path.exists("sensitive_data.txt"):
encrypted_file = secure_encrypt_file("sensitive_data.txt", password)
decrypted_file = secure_decrypt_file(encrypted_file, password)
# User data encryption with AES
user_data = SecureUserData(password)
encrypted_card = user_data.store_credit_card(
"4532-1234-5678-9012",
"123",
"12/25"
)
decrypted_card = user_data.retrieve_credit_card(encrypted_card)
print(f"Decrypted card: {decrypted_card}")
# Network communication with AES
network_crypto = SecureNetworkCrypto("shared_secret_key_here")
session_key, encrypted_session_key = network_crypto.create_secure_session_key()
encrypted_msg = network_crypto.encrypt_message("Secret meeting at midnight")
decrypted_msg = network_crypto.decrypt_message(encrypted_msg)
print(f"Secure message: {decrypted_msg}")
# Database encryption with AES
db = SecureDatabase("secure_data.db", password)
db.store_user_secret("user123", "my_secret_api_key")
retrieved_secret = db.get_user_secret("user123")
print(f"Retrieved secret: {retrieved_secret}")
print("SECURE: All data encrypted with strong AES-256-GCM!")The vulnerable examples use the deprecated DES algorithm with its weak 56-bit effective key size, making encrypted data susceptible to brute force attacks. The secure alternatives implement AES-256-GCM authenticated encryption with proper key derivation using PBKDF2, unique salts for each encryption operation, and comprehensive security measures including secure file deletion and random password generation.
Applications use DES to maintain compatibility with legacy systems that only support older encryption standards, without considering the security implications.
Sourcery automatically identifies information disclosure from insecure des cipher algorithm usage and many other security issues in your codebase.