- Frontend v4 accessible sur réseau local (192.168.1.40) - Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard) - Ollama GPU fonctionnel - Self-healing interactif - Dashboard confiance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
114 lines
3.6 KiB
Python
114 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Analyze the structure of an encrypted file to understand the padding issue.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
def analyze_encrypted_file():
|
|
"""Analyze the encrypted file structure."""
|
|
|
|
print("=== Analyzing Encrypted File Structure ===")
|
|
|
|
# Load environment
|
|
env_local_path = Path(".env.local")
|
|
if env_local_path.exists():
|
|
with open(env_local_path, 'r') as f:
|
|
for line in f:
|
|
line = line.strip()
|
|
if line and not line.startswith('#') and '=' in line:
|
|
key, value = line.split('=', 1)
|
|
os.environ[key.strip()] = value.strip()
|
|
|
|
password = os.getenv("ENCRYPTION_PASSWORD")
|
|
print(f"Password: {password[:16]}..." if password else "No password")
|
|
|
|
# Find encrypted file
|
|
enc_files = list(Path("agent_v0/sessions").glob("*.enc"))
|
|
if not enc_files:
|
|
print("No .enc files found")
|
|
return False
|
|
|
|
enc_file = enc_files[0]
|
|
print(f"Analyzing: {enc_file}")
|
|
print(f"File size: {enc_file.stat().st_size} bytes")
|
|
|
|
# Read file structure
|
|
with open(enc_file, 'rb') as f:
|
|
salt = f.read(16)
|
|
iv = f.read(16)
|
|
ciphertext = f.read()
|
|
|
|
print(f"Salt: {len(salt)} bytes")
|
|
print(f"IV: {len(iv)} bytes")
|
|
print(f"Ciphertext: {len(ciphertext)} bytes")
|
|
print(f"Ciphertext % 16: {len(ciphertext) % 16}")
|
|
|
|
if len(ciphertext) % 16 != 0:
|
|
print("Ciphertext length is not a multiple of 16!")
|
|
return False
|
|
|
|
# Try manual decryption to see where it fails
|
|
try:
|
|
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
from cryptography.hazmat.backends import default_backend
|
|
from cryptography.hazmat.primitives import hashes
|
|
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
|
|
|
# Derive key
|
|
kdf = PBKDF2HMAC(
|
|
algorithm=hashes.SHA256(),
|
|
length=32,
|
|
salt=salt,
|
|
iterations=100000,
|
|
backend=default_backend()
|
|
)
|
|
key = kdf.derive(password.encode('utf-8'))
|
|
print("Key derivation successful")
|
|
|
|
# Decrypt
|
|
cipher = Cipher(
|
|
algorithms.AES(key),
|
|
modes.CBC(iv),
|
|
backend=default_backend()
|
|
)
|
|
decryptor = cipher.decryptor()
|
|
plaintext = decryptor.update(ciphertext) + decryptor.finalize()
|
|
print(f"Decryption successful, plaintext length: {len(plaintext)}")
|
|
|
|
# Check padding
|
|
if len(plaintext) == 0:
|
|
print("Plaintext is empty!")
|
|
return False
|
|
|
|
padding_length = plaintext[-1]
|
|
print(f"Last byte (padding length): {padding_length}")
|
|
|
|
if padding_length < 1 or padding_length > 16:
|
|
print(f"Invalid padding length: {padding_length}")
|
|
return False
|
|
|
|
# Check padding bytes
|
|
padding_bytes = plaintext[-padding_length:]
|
|
print(f"Padding bytes: {[b for b in padding_bytes]}")
|
|
|
|
all_correct = all(b == padding_length for b in padding_bytes)
|
|
if not all_correct:
|
|
print("Padding bytes are not all the same!")
|
|
print(f"Expected all bytes to be {padding_length}")
|
|
return False
|
|
|
|
print("Padding validation successful")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"Manual decryption failed: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
success = analyze_encrypted_file()
|
|
sys.exit(0 if success else 1) |