| |
| """ |
| Script de Verificação CORRETO do Hash do Sistema VICK AI |
| Usa serialização canônica JSON (determinística) |
| Versão: 2.1 |
| """ |
|
|
| import hashlib |
| import json |
| import sys |
| import os |
| from pathlib import Path |
|
|
| |
| HASH_OFICIAL = "2ed9c8531958fa878637f852412e9490b53b33afe0ef6bc4d12c33c68563db05" |
|
|
| def calcular_hash_canonico(arquivo_json): |
| """ |
| Calcula hash SHA-256 usando serialização canônica do JSON |
| Garante determinismo mesmo com formatação diferente |
| """ |
| try: |
| with open(arquivo_json, 'r', encoding='utf-8') as f: |
| data = json.load(f) |
|
|
| |
| |
| canonical_json = json.dumps(data, sort_keys=True, separators=(',', ':')) |
|
|
| |
| hash_calculado = hashlib.sha256(canonical_json.encode('utf-8')).hexdigest() |
|
|
| return hash_calculado, canonical_json |
| except Exception as e: |
| print(f"❌ Erro ao calcular hash: {e}") |
| return None, None |
|
|
| def verificar_oids_individuais(data): |
| """ |
| Verifica OIDs (Object IDs) de cada componente individual |
| """ |
| print("\n🔍 Verificando OIDs individuais dos componentes...") |
|
|
| component_details = data.get('component_details', {}) |
| oids_verificados = 0 |
| oids_totais = 0 |
|
|
| for category, components in component_details.items(): |
| if category == '00_llm_fingerprint': |
| |
| continue |
|
|
| if not isinstance(components, dict): |
| continue |
|
|
| for comp_name, comp_hash in components.items(): |
| oids_totais += 1 |
|
|
| |
| if len(comp_hash) == 64 and all(c in '0123456789abcdef' for c in comp_hash): |
| oids_verificados += 1 |
| else: |
| print(f" ⚠️ {comp_name}: hash inválido") |
|
|
| print(f" ✓ {oids_verificados}/{oids_totais} OIDs válidos") |
| return oids_verificados == oids_totais |
|
|
| def verificar_assinatura_gpg(arquivo): |
| """ |
| Verifica assinatura GPG do manifest (se existir) |
| """ |
| sig_file = f"{arquivo}.sig" |
|
|
| if not os.path.exists(sig_file): |
| print("\n⚠️ Assinatura GPG não encontrada") |
| print(f" Procurando por: {sig_file}") |
| print(f" Recomendação: Assinar o manifest com GPG") |
| return None |
|
|
| print(f"\n🔐 Verificando assinatura GPG...") |
|
|
| try: |
| import subprocess |
| result = subprocess.run( |
| ['gpg', '--verify', sig_file, arquivo], |
| capture_output=True, |
| text=True |
| ) |
|
|
| if result.returncode == 0: |
| print(f" ✓ Assinatura GPG válida!") |
| print(f" {result.stderr.split('Good signature')[1].split('\\n')[0] if 'Good signature' in result.stderr else ''}") |
| return True |
| else: |
| print(f" ✗ Assinatura GPG inválida") |
| print(f" {result.stderr}") |
| return False |
| except FileNotFoundError: |
| print(f" ⚠️ GPG não instalado no sistema") |
| return None |
| except Exception as e: |
| print(f" ✗ Erro ao verificar assinatura: {e}") |
| return None |
|
|
| def verificar_componentes(arquivo_json): |
| """Verifica componentes do fingerprint""" |
| try: |
| with open(arquivo_json, 'r', encoding='utf-8') as f: |
| data = json.load(f) |
|
|
| print("\n📊 Informações do Certificado:") |
| print(f" Sistema: {data.get('system')}") |
| print(f" Versão: {data.get('version')}") |
| print(f" Criador: {data.get('creator')}") |
| print(f" Timestamp: {data.get('timestamp')}") |
|
|
| total_components = data.get('metadata', {}).get('total_components', 0) |
| print(f"\n📁 Total de Componentes: {total_components}") |
|
|
| print("\n🧬 Fingerprint do Modelo LLM:") |
| llm_fp = data.get('component_details', {}).get('00_llm_fingerprint', {}) |
| for key, value in llm_fp.items(): |
| print(f" • {key}: {value}") |
|
|
| |
| verificar_oids_individuais(data) |
|
|
| return True |
| except Exception as e: |
| print(f"❌ Erro ao ler componentes: {e}") |
| return False |
|
|
| def main(): |
| print("="*80) |
| print("🔐 VERIFICADOR DE HASH CORRETO - SISTEMA VICK AI v2.1") |
| print(" Usa serialização canônica JSON (determinística)") |
| print("="*80) |
|
|
| arquivo = "vick_fingerprint.json" |
|
|
| if not os.path.exists(arquivo): |
| print(f"\n❌ Arquivo não encontrado: {arquivo}") |
| print(f" Execute este script no diretório que contém {arquivo}") |
| sys.exit(1) |
|
|
| print(f"\n📄 Arquivo: {arquivo}") |
| print(f"🎯 Hash Oficial: {HASH_OFICIAL}") |
|
|
| |
| print(f"\n⏳ Calculando hash com serialização canônica...") |
| hash_calculado, canonical_json = calcular_hash_canonico(arquivo) |
|
|
| if not hash_calculado: |
| print("\n❌ FALHA NA VERIFICAÇÃO") |
| sys.exit(1) |
|
|
| print(f"✓ Hash Calculado: {hash_calculado}") |
| print(f" (usando JSON canônico: sort_keys=True, separators=(',',':'))") |
|
|
| |
| print(f"\n🔍 Comparando hashes...") |
|
|
| if hash_calculado == HASH_OFICIAL: |
| print("\n" + "="*80) |
| print("✅ CERTIFICADO AUTÊNTICO!") |
| print("="*80) |
| print("\nO hash calculado corresponde ao hash oficial registrado.") |
| print("Este certificado é genuíno e não foi alterado desde o registro.") |
|
|
| |
| verificar_componentes(arquivo) |
|
|
| |
| verificar_assinatura_gpg(arquivo) |
|
|
| print("\n" + "="*80) |
| print("✓ Verificação concluída com sucesso") |
| print("="*80) |
|
|
| print("\n💡 NOTA IMPORTANTE:") |
| print(" Este script usa serialização canônica (determinística).") |
| print(" O hash é calculado sobre JSON com sort_keys=True,") |
| print(" garantindo que formatação diferente não afete o resultado.") |
|
|
| sys.exit(0) |
| else: |
| print("\n" + "="*80) |
| print("❌ CERTIFICADO INVÁLIDO!") |
| print("="*80) |
| print("\n⚠️ ATENÇÃO: O hash não corresponde ao hash oficial.") |
| print("Este arquivo pode ter sido modificado ou corrompido.") |
| print("\nHash esperado:", HASH_OFICIAL) |
| print("Hash calculado:", hash_calculado) |
|
|
| |
| print(f"\nJSON canônico (primeiros 200 chars):") |
| print(f"{canonical_json[:200]}...") |
|
|
| print("\n" + "="*80) |
| sys.exit(1) |
|
|
| if __name__ == "__main__": |
| main() |
|
|