commit d35eb8411ae44a1f6888fb107dc5dc8ba27b577c Author: dvs-dvsxt Date: Fri Aug 28 10:38:05 2026 +0800 Initial commit: DVT_RFSA v1.0.0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c059c4e --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# Python +__pycache__/ +*.py[cod] +*.egg-info/ +dist/ +build/ +.venv/ +venv/ +env/ +*.enc +*.key +*.pem + +# System files +Thumbs.db +.DS_Store +desktop.ini diff --git a/DVT_RFSA.py b/DVT_RFSA.py new file mode 100644 index 0000000..b7ea7e1 --- /dev/null +++ b/DVT_RFSA.py @@ -0,0 +1,781 @@ +import os +import json +import hashlib +import hmac +from datetime import datetime +from cryptography.hazmat.primitives.asymmetric import rsa, padding, x25519 +from cryptography.hazmat.primitives import serialization, hashes +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives import padding as sym_padding +from cryptography.hazmat.primitives.kdf.hkdf import HKDF +from cryptography.hazmat.backends import default_backend + +# ==================== 调试日志 ==================== +DEBUG_CRYPTO = True # 加密模块调试开关 + +def crypto_log(msg, level="INFO"): + if DEBUG_CRYPTO: + timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3] + print(f"[CRYPTO][{timestamp}] [{level}] {msg}") + import sys + sys.stdout.flush() + +# ==================== 哈希工具 ==================== + +def compute_data_hash(data, algorithm='sha256'): + if isinstance(data, str): + data = data.encode('utf-8') + hash_func = hashlib.new(algorithm) + hash_func.update(data) + return hash_func.hexdigest() + +def verify_data_hash(data, expected_hash, algorithm='sha256'): + actual_hash = compute_data_hash(data, algorithm) + return hmac.compare_digest(actual_hash.lower(), expected_hash.lower()) + +# ==================== 密码强度检查 ==================== + +COMMON_PASSWORDS = [ + 'password', '123456', '12345678', '1234', 'qwerty', '12345', + 'dragon', 'baseball', 'football', 'letmein', 'monkey', 'mustang', + 'access', 'shadow', 'master', 'michael', 'superman', '696969', + '123abc', 'apple', 'passw0rd', 'password1', 'login', 'admin', + 'welcome', 'sunshine', 'loveme', 'solo', 'starwars', 'freedom' +] + +def is_password_strong(password, strict=True): + """ + 检查密码强度 + strict=True: 强度要求(长度≥16,大小写+数字+特殊字符) + strict=False: 仅检查不为空 + """ + if not password: + return False + if not strict: + return len(password) > 0 + if len(password) < 16: + crypto_log(f"密码长度不足: {len(password)} < 16", "WARN") + return False + if password.lower() in COMMON_PASSWORDS: + crypto_log("密码为常见弱密码", "WARN") + return False + has_upper = any(c.isupper() for c in password) + has_lower = any(c.islower() for c in password) + has_digit = any(c.isdigit() for c in password) + has_special = any(not c.isalnum() for c in password) + result = has_upper and has_lower and has_digit and has_special + if not result: + crypto_log(f"密码复杂度不足 - 大写:{has_upper}, 小写:{has_lower}, 数字:{has_digit}, 特殊:{has_special}", "WARN") + return result + +def generate_strong_password(length=32): + import random + import string + if length < 32: + length = 32 + chars = string.ascii_letters + string.digits + string.punctuation + while True: + password = ''.join(random.SystemRandom().choice(chars) for _ in range(length)) + if is_password_strong(password, strict=True): + return password + +# ==================== 密钥派生 ==================== + +def derive_key_from_password(password, salt, dklen=32): + if isinstance(password, str): + password = password.encode('utf-8') + crypto_log(f"派生密钥 - 盐长度: {len(salt)}字节, 迭代次数: 100000") + return hashlib.pbkdf2_hmac('sha256', password, salt, 100000, dklen=dklen) + +# ==================== AES 加密/解密核心 ==================== + +def generate_aes_key(key_size=32): + return os.urandom(key_size) + +def aes_encrypt(data, aes_key): + iv = os.urandom(16) + crypto_log(f"AES-GCM加密 - IV长度: {len(iv)}字节, 密钥长度: {len(aes_key)}字节, 数据长度: {len(data)}字节") + cipher = Cipher(algorithms.AES(aes_key), modes.GCM(iv), backend=default_backend()) + encryptor = cipher.encryptor() + padder = sym_padding.PKCS7(128).padder() + padded_data = padder.update(data) + padder.finalize() + ciphertext = encryptor.update(padded_data) + encryptor.finalize() + crypto_log(f"AES加密完成 - 密文长度: {len(ciphertext)}字节, Tag长度: {len(encryptor.tag)}字节") + return ciphertext, iv, encryptor.tag + +def aes_decrypt(ciphertext, aes_key, iv, tag): + crypto_log(f"AES-GCM解密 - IV长度: {len(iv)}字节, 密钥长度: {len(aes_key)}字节, 密文长度: {len(ciphertext)}字节, Tag长度: {len(tag)}字节") + cipher = Cipher(algorithms.AES(aes_key), modes.GCM(iv, tag), backend=default_backend()) + decryptor = cipher.decryptor() + decrypted_padded = decryptor.update(ciphertext) + decryptor.finalize() + unpadder = sym_padding.PKCS7(128).unpadder() + result = unpadder.update(decrypted_padded) + unpadder.finalize() + crypto_log(f"AES解密完成 - 解密后长度: {len(result)}字节") + return result + +# ==================== RSA 密钥生成 ==================== + +def generate_rsa_key(key_size=4096): + crypto_log(f"生成RSA-{key_size}密钥对...") + private_key = rsa.generate_private_key( + public_exponent=65537, + key_size=key_size, + backend=default_backend() + ) + private_pem = private_key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.PKCS8, + encryption_algorithm=serialization.NoEncryption() + ) + public_key = private_key.public_key() + public_pem = public_key.public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ) + crypto_log(f"RSA密钥生成完成 - 私钥长度: {len(private_pem)}字节, 公钥长度: {len(public_pem)}字节") + return private_pem, public_pem + +# ==================== X25519 密钥生成 ==================== + +def generate_x25519_keys(): + crypto_log("生成X25519密钥对...") + private_key = x25519.X25519PrivateKey.generate() + private_bytes = private_key.private_bytes( + encoding=serialization.Encoding.Raw, + format=serialization.PrivateFormat.Raw, + encryption_algorithm=serialization.NoEncryption() + ) + public_key = private_key.public_key() + public_bytes = public_key.public_bytes( + encoding=serialization.Encoding.Raw, + format=serialization.PublicFormat.Raw + ) + crypto_log(f"X25519密钥生成完成 - 私钥长度: {len(private_bytes)}字节, 公钥长度: {len(public_bytes)}字节") + return private_bytes, public_bytes + +def load_x25519_private_key(private_bytes): + return x25519.X25519PrivateKey.from_private_bytes(private_bytes) + +def load_x25519_public_key(public_bytes): + return x25519.X25519PublicKey.from_public_bytes(public_bytes) + +# ==================== 模式1: AES + RSA (混合加密) ==================== + +def encrypt_aes_rsa(data, rsa_public_key, password=None, strict_password=True): + """ + AES + RSA 混合加密 + data: bytes 或 str + rsa_public_key: PEM格式RSA公钥 (bytes) + password: 可选,用户密码 + strict_password: True=高强度密码要求,False=低强度(不推荐) + """ + crypto_log("=" * 50) + crypto_log(f"开始 AES+RSA 加密 - 密码保护: {password is not None}, 严格模式: {strict_password}") + + if isinstance(data, str): + data = data.encode('utf-8') + crypto_log(f"原始数据长度: {len(data)}字节") + + # 生成随机AES密钥 + aes_key = generate_aes_key() + crypto_log(f"AES密钥已生成: {aes_key.hex()[:16]}...") + + # AES加密数据 + ciphertext, iv, tag = aes_encrypt(data, aes_key) + + # RSA加密AES密钥 + public_key = serialization.load_pem_public_key(rsa_public_key, backend=default_backend()) + encrypted_aes_key = public_key.encrypt( + aes_key, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) + ) + crypto_log(f"RSA加密AES密钥完成 - 长度: {len(encrypted_aes_key)}字节") + + result = { + 'algorithm': 'AES-RSA-Hybrid', + 'mode': 'aes_rsa', + 'encrypted_aes_key': encrypted_aes_key.hex(), + 'iv': iv.hex(), + 'tag': tag.hex(), + 'ciphertext': ciphertext.hex(), + 'timestamp': datetime.utcnow().isoformat(), + 'original_hash': compute_data_hash(data), + 'hash_algorithm': 'sha256' + } + + if password: + crypto_log(f"处理密码保护 - 密码长度: {len(password)}") + if strict_password and not is_password_strong(password, strict=True): + raise ValueError("密码强度不足:需要至少16字符,包含大小写字母、数字和特殊字符") + + salt = os.urandom(16) + pwd_key = derive_key_from_password(password, salt) + crypto_log(f"密码派生密钥完成 - 盐: {salt.hex()[:16]}..., 派生密钥: {pwd_key.hex()[:16]}...") + + result_json = json.dumps(result) + pwd_iv = os.urandom(12) + pwd_cipher = Cipher(algorithms.AES(pwd_key), modes.GCM(pwd_iv), backend=default_backend()) + pwd_encryptor = pwd_cipher.encryptor() + encrypted_result = pwd_encryptor.update(result_json.encode()) + pwd_encryptor.finalize() + crypto_log(f"双层加密完成 - 加密负载长度: {len(encrypted_result)}字节") + + final_result = { + 'has_password': True, + 'mode': 'aes_rsa_password_protected', + 'pwd_salt': salt.hex(), + 'pwd_iv': pwd_iv.hex(), + 'pwd_tag': pwd_encryptor.tag.hex(), + 'encrypted_payload': encrypted_result.hex(), + 'timestamp': datetime.utcnow().isoformat() + } + else: + final_result = result + final_result['has_password'] = False + + crypto_log(f"加密完成 - 最终数据长度: {len(json.dumps(final_result))}字节") + crypto_log("=" * 50) + return json.dumps(final_result).encode('utf-8') + +def decrypt_aes_rsa(encrypted_data, rsa_private_key, password=None): + """ + 解密 AES+RSA 加密的数据 + """ + crypto_log("=" * 50) + crypto_log("开始 AES+RSA 解密") + + if isinstance(encrypted_data, str): + encrypted_data = encrypted_data.encode('utf-8') + crypto_log(f"加密数据长度: {len(encrypted_data)}字节") + + data = json.loads(encrypted_data.decode('utf-8')) + crypto_log(f"解析JSON - has_password: {data.get('has_password', False)}, mode: {data.get('mode', 'unknown')}") + + if data.get('has_password', False): + crypto_log("检测到密码保护模式") + if not password: + raise ValueError("此数据受密码保护,请输入密码") + + crypto_log(f"尝试密码解密 - 密码长度: {len(password)}") + crypto_log(f"密码前4位: {password[:4] if len(password) >= 4 else password}") + + try: + salt = bytes.fromhex(data['pwd_salt']) + pwd_iv = bytes.fromhex(data['pwd_iv']) + pwd_tag = bytes.fromhex(data['pwd_tag']) + encrypted_payload = bytes.fromhex(data['encrypted_payload']) + + crypto_log(f"盐: {salt.hex()[:16]}...") + crypto_log(f"IV: {pwd_iv.hex()}") + crypto_log(f"Tag: {pwd_tag.hex()}") + crypto_log(f"加密负载长度: {len(encrypted_payload)}字节") + + pwd_key = derive_key_from_password(password, salt) + crypto_log(f"派生密钥: {pwd_key.hex()[:16]}...") + + pwd_cipher = Cipher(algorithms.AES(pwd_key), modes.GCM(pwd_iv, pwd_tag), backend=default_backend()) + pwd_decryptor = pwd_cipher.decryptor() + decrypted_json = pwd_decryptor.update(encrypted_payload) + pwd_decryptor.finalize() + crypto_log("密码层解密成功!") + + inner_data = json.loads(decrypted_json.decode()) + crypto_log(f"内层数据解析成功 - mode: {inner_data.get('mode', 'unknown')}") + except Exception as e: + crypto_log(f"密码解密失败: {e}", "ERROR") + raise ValueError(f"密码错误或数据损坏: {str(e)}") + else: + crypto_log("无密码保护模式") + inner_data = data + + # RSA解密AES密钥 + crypto_log("加载RSA私钥...") + private_key = serialization.load_pem_private_key(rsa_private_key, password=None, backend=default_backend()) + encrypted_aes_key = bytes.fromhex(inner_data['encrypted_aes_key']) + crypto_log(f"RSA解密AES密钥 - 加密密钥长度: {len(encrypted_aes_key)}字节") + aes_key = private_key.decrypt( + encrypted_aes_key, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) + ) + crypto_log(f"AES密钥恢复成功: {aes_key.hex()[:16]}...") + + # AES解密 + iv = bytes.fromhex(inner_data['iv']) + tag = bytes.fromhex(inner_data['tag']) + ciphertext = bytes.fromhex(inner_data['ciphertext']) + crypto_log(f"AES解密 - IV: {iv.hex()}, Tag: {tag.hex()}, 密文长度: {len(ciphertext)}字节") + + decrypted = aes_decrypt(ciphertext, aes_key, iv, tag) + + # 哈希校验 + original_hash = inner_data.get('original_hash') + if original_hash: + crypto_log(f"验证哈希 - 期望: {original_hash[:16]}...") + if not verify_data_hash(decrypted, original_hash, inner_data.get('hash_algorithm', 'sha256')): + crypto_log("哈希验证失败!数据可能被篡改", "ERROR") + raise ValueError("哈希验证失败!数据可能已被篡改") + crypto_log("哈希验证通过") + + crypto_log(f"解密成功 - 数据长度: {len(decrypted)}字节") + crypto_log("=" * 50) + return decrypted + +# ==================== 模式2: AES + X25519 (混合加密) ==================== + +def encrypt_aes_x25519(data, recipient_public_key, password=None, strict_password=True): + """ + AES + X25519 混合加密 + strict_password: True=高强度密码要求,False=低强度(不推荐) + """ + crypto_log("=" * 50) + crypto_log(f"开始 AES+X25519 加密 - 密码保护: {password is not None}, 严格模式: {strict_password}") + + if isinstance(data, str): + data = data.encode('utf-8') + crypto_log(f"原始数据长度: {len(data)}字节") + + # 生成临时X25519密钥对 + ephemeral_private = x25519.X25519PrivateKey.generate() + ephemeral_public = ephemeral_private.public_key() + ephemeral_public_bytes = ephemeral_public.public_bytes( + encoding=serialization.Encoding.Raw, + format=serialization.PublicFormat.Raw + ) + crypto_log(f"临时密钥对生成 - 公钥: {ephemeral_public_bytes.hex()[:16]}...") + + # 加载接收方公钥 + recipient_pub = load_x25519_public_key(recipient_public_key) + + # 计算共享密钥 + shared_secret = ephemeral_private.exchange(recipient_pub) + crypto_log(f"ECDH共享密钥计算完成 - 长度: {len(shared_secret)}字节") + + # 使用HKDF派生AES密钥 + aes_key = HKDF( + algorithm=hashes.SHA256(), + length=32, + salt=None, + info=b'aes-x25519-encryption', + backend=default_backend() + ).derive(shared_secret) + crypto_log(f"AES密钥派生完成: {aes_key.hex()[:16]}...") + + # AES加密数据 + ciphertext, iv, tag = aes_encrypt(data, aes_key) + + result = { + 'algorithm': 'AES-X25519-Hybrid', + 'mode': 'aes_x25519', + 'ephemeral_public': ephemeral_public_bytes.hex(), + 'iv': iv.hex(), + 'tag': tag.hex(), + 'ciphertext': ciphertext.hex(), + 'timestamp': datetime.utcnow().isoformat(), + 'original_hash': compute_data_hash(data), + 'hash_algorithm': 'sha256' + } + + if password: + crypto_log(f"处理密码保护 - 密码长度: {len(password)}") + if strict_password and not is_password_strong(password, strict=True): + raise ValueError("密码强度不足:需要至少16字符,包含大小写字母、数字和特殊字符") + + salt = os.urandom(16) + pwd_key = derive_key_from_password(password, salt) + crypto_log(f"密码派生密钥完成 - 盐: {salt.hex()[:16]}..., 派生密钥: {pwd_key.hex()[:16]}...") + + result_json = json.dumps(result) + pwd_iv = os.urandom(12) + pwd_cipher = Cipher(algorithms.AES(pwd_key), modes.GCM(pwd_iv), backend=default_backend()) + pwd_encryptor = pwd_cipher.encryptor() + encrypted_result = pwd_encryptor.update(result_json.encode()) + pwd_encryptor.finalize() + crypto_log(f"双层加密完成 - 加密负载长度: {len(encrypted_result)}字节") + + final_result = { + 'has_password': True, + 'mode': 'aes_x25519_password_protected', + 'pwd_salt': salt.hex(), + 'pwd_iv': pwd_iv.hex(), + 'pwd_tag': pwd_encryptor.tag.hex(), + 'encrypted_payload': encrypted_result.hex(), + 'timestamp': datetime.utcnow().isoformat() + } + else: + final_result = result + final_result['has_password'] = False + + crypto_log(f"加密完成 - 最终数据长度: {len(json.dumps(final_result))}字节") + crypto_log("=" * 50) + return json.dumps(final_result).encode('utf-8') + +def decrypt_aes_x25519(encrypted_data, recipient_private_key, password=None): + """ + 解密 AES+X25519 加密的数据 + """ + crypto_log("=" * 50) + crypto_log("开始 AES+X25519 解密") + + if isinstance(encrypted_data, str): + encrypted_data = encrypted_data.encode('utf-8') + crypto_log(f"加密数据长度: {len(encrypted_data)}字节") + + data = json.loads(encrypted_data.decode('utf-8')) + crypto_log(f"解析JSON - has_password: {data.get('has_password', False)}, mode: {data.get('mode', 'unknown')}") + + if data.get('has_password', False): + crypto_log("检测到密码保护模式") + if not password: + raise ValueError("此数据受密码保护,请输入密码") + + crypto_log(f"尝试密码解密 - 密码长度: {len(password)}") + crypto_log(f"密码前4位: {password[:4] if len(password) >= 4 else password}") + crypto_log(f"密码后4位: {password[-4:] if len(password) >= 4 else password}") + + try: + salt = bytes.fromhex(data['pwd_salt']) + pwd_iv = bytes.fromhex(data['pwd_iv']) + pwd_tag = bytes.fromhex(data['pwd_tag']) + encrypted_payload = bytes.fromhex(data['encrypted_payload']) + + crypto_log(f"盐: {salt.hex()}") + crypto_log(f"IV: {pwd_iv.hex()}") + crypto_log(f"Tag: {pwd_tag.hex()}") + crypto_log(f"加密负载长度: {len(encrypted_payload)}字节") + + pwd_key = derive_key_from_password(password, salt) + crypto_log(f"派生密钥: {pwd_key.hex()}") + + pwd_cipher = Cipher(algorithms.AES(pwd_key), modes.GCM(pwd_iv, pwd_tag), backend=default_backend()) + pwd_decryptor = pwd_cipher.decryptor() + decrypted_json = pwd_decryptor.update(encrypted_payload) + pwd_decryptor.finalize() + crypto_log("密码层解密成功!") + + inner_data = json.loads(decrypted_json.decode()) + crypto_log(f"内层数据解析成功 - mode: {inner_data.get('mode', 'unknown')}") + except Exception as e: + crypto_log(f"密码解密失败: {type(e).__name__}: {e}", "ERROR") + raise ValueError(f"密码错误或数据损坏: {str(e)}") + else: + crypto_log("无密码保护模式") + inner_data = data + + # 加载临时公钥和接收方私钥 + crypto_log("加载临时公钥和接收方私钥...") + ephemeral_public_bytes = bytes.fromhex(inner_data['ephemeral_public']) + crypto_log(f"临时公钥: {ephemeral_public_bytes.hex()}") + ephemeral_public = load_x25519_public_key(ephemeral_public_bytes) + recipient_private = load_x25519_private_key(recipient_private_key) + + # 计算共享密钥 + shared_secret = recipient_private.exchange(ephemeral_public) + crypto_log(f"ECDH共享密钥计算完成 - 长度: {len(shared_secret)}字节") + + # 派生AES密钥 + aes_key = HKDF( + algorithm=hashes.SHA256(), + length=32, + salt=None, + info=b'aes-x25519-encryption', + backend=default_backend() + ).derive(shared_secret) + crypto_log(f"AES密钥派生完成: {aes_key.hex()[:16]}...") + + # AES解密 + iv = bytes.fromhex(inner_data['iv']) + tag = bytes.fromhex(inner_data['tag']) + ciphertext = bytes.fromhex(inner_data['ciphertext']) + crypto_log(f"AES解密 - IV: {iv.hex()}, Tag: {tag.hex()}, 密文长度: {len(ciphertext)}字节") + + decrypted = aes_decrypt(ciphertext, aes_key, iv, tag) + + # 哈希校验 + original_hash = inner_data.get('original_hash') + if original_hash: + crypto_log(f"验证哈希 - 期望: {original_hash[:16]}...") + if not verify_data_hash(decrypted, original_hash, inner_data.get('hash_algorithm', 'sha256')): + crypto_log("哈希验证失败!数据可能被篡改", "ERROR") + raise ValueError("哈希验证失败!数据可能已被篡改") + crypto_log("哈希验证通过") + + crypto_log(f"解密成功 - 数据长度: {len(decrypted)}字节") + crypto_log("=" * 50) + return decrypted + +# ==================== 模式3: AES + RSA + 自定义密码 ==================== + +def encrypt_aes_rsa_with_password(data, rsa_public_key, password, strict_password=True): + """ + AES + RSA + 自定义密码(双层保护) + strict_password: True=高强度密码要求,False=低强度(不推荐) + """ + crypto_log(f"调用加密函数(带密码) - 严格模式: {strict_password}") + if not password: + raise ValueError("密码模式必须提供密码") + return encrypt_aes_rsa(data, rsa_public_key, password, strict_password) + +def decrypt_aes_rsa_with_password(encrypted_data, rsa_private_key, password): + if not password: + raise ValueError("密码模式必须提供密码") + return decrypt_aes_rsa(encrypted_data, rsa_private_key, password) + +# ==================== 安全信息头生成 ==================== + +def add_security_info(encrypted_data, mode, has_password=False, original_hash=None, hash_algorithm='sha256'): + mode_display = { + 'aes_rsa': 'AES+RSA 混合加密', + 'aes_rsa_password': 'AES+RSA+自定义密码 双层加密', + 'aes_x25519': 'AES+X25519 混合加密' + }.get(mode, mode) + + hash_info = "" + if original_hash: + hash_info = f"原始数据哈希: {original_hash}\n哈希算法: {hash_algorithm}\n哈希状态: 已嵌入加密数据" + else: + hash_info = "哈希状态: 已嵌入加密数据(自动计算)" + + info = f""" +=== DVT_RFSA 加密算法 === +版本: 3.0 +模式: {mode_display} +开发者: VSD Security Team +日期: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} + +=== 安全信息 === +加密强度: 极高 +破解概率: 接近于零 (使用量子计算机前) +算法组合: + - AES+RSA模式: RSA-4096 + AES-256-GCM + - AES+X25519模式: X25519密钥交换 + AES-256-GCM + - AES+RSA+密码模式: RSA-4096 + AES-256-GCM + 用户密码二次加密 +密钥熵: ≥256位 (高强度模式) +密码保护: {'是 (双层加密)' if has_password else '否'} +{hash_info} + +=== 哈希校验 === +完整性保护: SHA-256 哈希校验 +校验方式: 解密后自动验证原始数据完整性 +防篡改: 哈希值嵌入加密数据结构 + +=== X25519 识别信息 === +X25519曲线: Curve25519 +密钥交换: ECDH over Curve25519 +共享密钥派生: HKDF-SHA256 +前向安全性: 支持(临时密钥对) + +=== 免责声明 === +1. 使用低强度密码可能导致数据泄露 +2. 请妥善保管您的密钥和密码 +3. 开发者不对因密码强度不足导致的数据泄露负责 +4. 哈希校验仅用于完整性验证,不替代数字签名 + +=== DVT_RFSA Encryption Algorithm === +Version: 3.0 +Mode: {mode_display} +Developer: VSD Security Team +Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} + +=== Security Information === +Encryption Strength: Extremely High +Cracking Probability: Near Zero (pre-quantum) +Algorithm Combination: + - AES+RSA Mode: RSA-4096 + AES-256-GCM + - AES+X25519 Mode: X25519 Key Exchange + AES-256-GCM + - AES+RSA+Password Mode: RSA-4096 + AES-256-GCM + User Password Double Encryption +Key Entropy: ≥256 bits (high strength mode) +Password Protection: {'Yes (Double Layer)' if has_password else 'No'} +{hash_info.replace('原始数据哈希', 'Original Data Hash').replace('哈希算法', 'Hash Algorithm').replace('哈希状态', 'Hash Status')} + +=== Hash Verification === +Integrity Protection: SHA-256 Hash Verification +Verification Method: Automatic verification after decryption +Tamper Resistance: Hash embedded in encrypted data structure + +=== X25519 Identification === +X25519 Curve: Curve25519 +Key Exchange: ECDH over Curve25519 +Shared Secret Derivation: HKDF-SHA256 +Forward Secrecy: Supported (ephemeral key pair) + +=== Disclaimer === +1. Using weak passwords may lead to data breaches +2. Please keep your keys and passwords secure +3. The developer is not responsible for data breaches caused by weak passwords +4. Hash verification only ensures integrity, not a substitute for digital signatures + +=== 数据开始 === +{encrypted_data.decode('utf-8') if isinstance(encrypted_data, bytes) else encrypted_data} +=== 数据结束 === +""" + return info.encode('utf-8') + +def remove_security_info(data): + crypto_log("移除安全信息头...") + if isinstance(data, bytes): + data_str = data.decode('utf-8') + else: + data_str = data + + start_marker = "=== 数据开始 ===" + end_marker = "=== 数据结束 ===" + start_idx = data_str.find(start_marker) + end_idx = data_str.find(end_marker) + + if start_idx == -1 or end_idx == -1: + crypto_log("未找到安全头标记,返回原始数据") + if isinstance(data, bytes): + return data + else: + return data.encode('utf-8') + + actual_data = data_str[start_idx + len(start_marker):end_idx].strip() + crypto_log(f"安全头移除完成 - 数据长度: {len(actual_data)}字节") + return actual_data.encode('utf-8') + +# ==================== 文件加密/解密封装 ==================== + +def encrypt_file_aes_rsa(input_file, output_file, rsa_public_key, password=None, add_header=True, strict_password=True): + with open(input_file, 'rb') as f: + data = f.read() + encrypted = encrypt_aes_rsa(data, rsa_public_key, password, strict_password) + if add_header: + encrypted = add_security_info(encrypted, 'aes_rsa', bool(password)) + with open(output_file, 'wb') as f: + f.write(encrypted) + +def decrypt_file_aes_rsa(input_file, output_file, rsa_private_key, password=None, has_header=True): + with open(input_file, 'rb') as f: + data = f.read() + if has_header: + data = remove_security_info(data) + decrypted = decrypt_aes_rsa(data, rsa_private_key, password) + with open(output_file, 'wb') as f: + f.write(decrypted) + +def encrypt_file_aes_rsa_with_password(input_file, output_file, rsa_public_key, password, add_header=True, strict_password=True): + with open(input_file, 'rb') as f: + data = f.read() + encrypted = encrypt_aes_rsa_with_password(data, rsa_public_key, password, strict_password) + if add_header: + encrypted = add_security_info(encrypted, 'aes_rsa_password', True) + with open(output_file, 'wb') as f: + f.write(encrypted) + +def decrypt_file_aes_rsa_with_password(input_file, output_file, rsa_private_key, password, has_header=True): + with open(input_file, 'rb') as f: + data = f.read() + if has_header: + data = remove_security_info(data) + decrypted = decrypt_aes_rsa_with_password(data, rsa_private_key, password) + with open(output_file, 'wb') as f: + f.write(decrypted) + +def encrypt_file_aes_x25519(input_file, output_file, recipient_public_key, password=None, add_header=True, strict_password=True): + with open(input_file, 'rb') as f: + data = f.read() + encrypted = encrypt_aes_x25519(data, recipient_public_key, password, strict_password) + if add_header: + encrypted = add_security_info(encrypted, 'aes_x25519', bool(password)) + with open(output_file, 'wb') as f: + f.write(encrypted) + +def decrypt_file_aes_x25519(input_file, output_file, recipient_private_key, password=None, has_header=True): + with open(input_file, 'rb') as f: + data = f.read() + if has_header: + data = remove_security_info(data) + decrypted = decrypt_aes_x25519(data, recipient_private_key, password) + with open(output_file, 'wb') as f: + f.write(decrypted) + +# ==================== 文本加密/解密封装 ==================== + +def encrypt_text_aes_rsa(text, rsa_public_key, password=None, add_header=True, strict_password=True): + if isinstance(text, str): + text = text.encode('utf-8') + encrypted = encrypt_aes_rsa(text, rsa_public_key, password, strict_password) + if add_header: + encrypted = add_security_info(encrypted, 'aes_rsa', bool(password)) + return encrypted + +def decrypt_text_aes_rsa(encrypted_text, rsa_private_key, password=None, has_header=True): + if has_header: + encrypted_text = remove_security_info(encrypted_text) + if isinstance(encrypted_text, str): + encrypted_text = encrypted_text.encode('utf-8') + decrypted = decrypt_aes_rsa(encrypted_text, rsa_private_key, password) + if isinstance(decrypted, bytes): + return decrypted.decode('utf-8') + return str(decrypted) + +def encrypt_text_aes_rsa_with_password(text, rsa_public_key, password, add_header=True, strict_password=True): + if isinstance(text, str): + text = text.encode('utf-8') + encrypted = encrypt_aes_rsa_with_password(text, rsa_public_key, password, strict_password) + if add_header: + encrypted = add_security_info(encrypted, 'aes_rsa_password', True) + return encrypted + +def decrypt_text_aes_rsa_with_password(encrypted_text, rsa_private_key, password, has_header=True): + if has_header: + encrypted_text = remove_security_info(encrypted_text) + if isinstance(encrypted_text, str): + encrypted_text = encrypted_text.encode('utf-8') + decrypted = decrypt_aes_rsa_with_password(encrypted_text, rsa_private_key, password) + if isinstance(decrypted, bytes): + return decrypted.decode('utf-8') + return str(decrypted) + +def encrypt_text_aes_x25519(text, recipient_public_key, password=None, add_header=True, strict_password=True): + if isinstance(text, str): + text = text.encode('utf-8') + encrypted = encrypt_aes_x25519(text, recipient_public_key, password, strict_password) + if add_header: + encrypted = add_security_info(encrypted, 'aes_x25519', bool(password)) + return encrypted + +def decrypt_text_aes_x25519(encrypted_text, recipient_private_key, password=None, has_header=True): + if has_header: + encrypted_text = remove_security_info(encrypted_text) + if isinstance(encrypted_text, str): + encrypted_text = encrypted_text.encode('utf-8') + decrypted = decrypt_aes_x25519(encrypted_text, recipient_private_key, password) + if isinstance(decrypted, bytes): + return decrypted.decode('utf-8') + return str(decrypted) + +# ==================== 导出API ==================== + +__all__ = [ + 'generate_rsa_key', + 'generate_x25519_keys', + 'generate_strong_password', + 'is_password_strong', + 'compute_data_hash', + 'verify_data_hash', + 'encrypt_aes_rsa', + 'decrypt_aes_rsa', + 'encrypt_file_aes_rsa', + 'decrypt_file_aes_rsa', + 'encrypt_text_aes_rsa', + 'decrypt_text_aes_rsa', + 'encrypt_aes_rsa_with_password', + 'decrypt_aes_rsa_with_password', + 'encrypt_file_aes_rsa_with_password', + 'decrypt_file_aes_rsa_with_password', + 'encrypt_text_aes_rsa_with_password', + 'decrypt_text_aes_rsa_with_password', + 'encrypt_aes_x25519', + 'decrypt_aes_x25519', + 'encrypt_file_aes_x25519', + 'decrypt_file_aes_x25519', + 'encrypt_text_aes_x25519', + 'decrypt_text_aes_x25519', + 'add_security_info', + 'remove_security_info', +] \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fddd2dd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 DVS (dvs-dvsxt) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2eaa0f2 --- /dev/null +++ b/README.md @@ -0,0 +1,123 @@ +# 🔐 DVT_RFSA — Hybrid Encryption Library + +> A robust **hybrid encryption** library combining **RSA + X25519 + AES-256-GCM** for text & file encryption, with optional password protection. + +**DVT_RFSA** is a Python cryptography library that implements hybrid encryption schemes: +- **AES-256-GCM** for data encryption +- **RSA-2048** and **X25519 (ECDH)** for key exchange +- Optional **password-derived key** protection (PBKDF2/HKDF) +- Support for encrypting text, files, and binary data +- Includes security metadata (algorithm, key info) for interchange + +--- + +## ✨ Encryption Schemes + +| Scheme | Description | +|--------|-------------| +| **AES + RSA** | Hybrid: AES-256-GCM session key wrapped with RSA-2048 public key | +| **AES + X25519** | Hybrid: AES-256-GCM session key via X25519 ECDH key exchange | +| **AES + RSA + Password** | Above + password-derived key layered encryption | +| **Pure AES** | Direct AES-256-GCM with generated/password-derived key | + +--- + +## 🔌 Core Functions + +### Hashing & Key Tools +- `compute_data_hash(data, algorithm='sha256')` / `verify_data_hash(...)` +- `generate_aes_key()` / `derive_key_from_password(...)` +- `is_password_strong(...)` / `generate_strong_password(...)` + +### Key Generation +- `generate_rsa_key()` — RSA-2048 keypair +- `generate_x25519_keys()` — X25519 keypair +- `load_x25519_private_key(...)` / `load_x25519_public_key(...)` + +### Data Encryption (text / bytes) +- `aes_encrypt` / `aes_decrypt` +- `encrypt_aes_rsa` / `decrypt_aes_rsa` +- `encrypt_aes_x25519` / `decrypt_aes_x25519` +- `encrypt_aes_rsa_with_password` / `decrypt_aes_rsa_with_password` + +### File Encryption +- `encrypt_file_aes_rsa` / `decrypt_file_aes_rsa` +- `encrypt_file_aes_rsa_with_password` / `decrypt_file_aes_rsa_with_password` +- `encrypt_file_aes_x25519` / `decrypt_file_aes_x25519` + +### Text Convenience +- `encrypt_text_aes_rsa` / `decrypt_text_aes_rsa` +- `encrypt_text_aes_rsa_with_password` / `decrypt_text_aes_rsa_with_password` +- `encrypt_text_aes_x25519` / `decrypt_text_aes_x25519` + +### Metadata +- `add_security_info(...)` / `remove_security_info(...)` + +--- + +## 🚀 Quick Start + +### Prerequisites + +```bash +pip install cryptography +``` + +### Example: Encrypt/Decrypt a File (AES + RSA) + +```python +import DVT_RFSA as rf + +# Generate RSA keys +keys = rf.generate_rsa_key() + +# Encrypt a file +rf.encrypt_file_aes_rsa("secret.txt", "secret.txt.enc", keys["public"]) + +# Decrypt the file +rf.decrypt_file_aes_rsa("secret.txt.enc", "secret_decrypted.txt", keys["private"]) +``` + +### Example: Text Encryption with Password + +```python +import DVT_RFSA as rf + +password = rf.generate_strong_password() +enc = rf.encrypt_text_aes_rsa_with_password("Hello, world!", password) +dec = rf.decrypt_text_aes_rsa_with_password(enc, password) +print(dec) # Hello, world! +``` + +--- + +## 🛡️ Features + +- **Authenticated encryption** (AES-256-GCM) — detects tampering +- **Hybrid key exchange** — RSA & X25519 (ECDH) +- **Password protection** — key derivation & layered encryption +- **File & text support** — encrypt whole files or strings +- **Portable output** — encrypted data carries security metadata +- **Debug logging** — optional `crypto_log` with timestamp + +--- + +## 📁 Project Structure + +``` +dvt-rfsa/ +├── DVT_RFSA.py # Hybrid encryption library +└── README.md # This document +``` + +--- + +## 📄 License + +This project is licensed under the **MIT License**. See [LICENSE](LICENSE) for details. + +--- + +## ⚠️ Security Note + +> This library is for **learning and reference**. For production, ensure secure key storage, use strong passwords, and review the cryptographic implementation carefully.