Initial commit: DVT_RFSA v1.0.0
This commit is contained in:
+17
@@ -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
|
||||||
+781
@@ -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',
|
||||||
|
]
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
Reference in New Issue
Block a user