124 lines
4.4 KiB
Python
124 lines
4.4 KiB
Python
class HexCipher:
|
|
"""
|
|
Um cifrador simples e reversível baseado em:
|
|
- XOR com chave
|
|
- Inversão de texto
|
|
- Representação em hexadecimal
|
|
|
|
Inspirado no componente original Delphi TEvCriptografa.
|
|
"""
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Construtor
|
|
# -------------------------------------------------------------------------
|
|
def __init__(self, key: str = "123", ignore_fields: list[str] | None = None):
|
|
"""Inicializa a classe com a chave fornecida."""
|
|
self._key = key
|
|
# nomes de campos que NÃO devem ser descriptografados (sempre minúsculos)
|
|
self._ignore_fields = (
|
|
{f.lower() for f in ignore_fields} if ignore_fields else set()
|
|
)
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Métodos públicos principais
|
|
# -------------------------------------------------------------------------
|
|
|
|
def encrypt(self, text: str) -> str:
|
|
"""
|
|
Recebe um texto puro e retorna sua versão criptografada em hexadecimal.
|
|
"""
|
|
binary_cipher = self._text_to_binary_cipher(text)
|
|
hex_cipher = "".join(self._decimal_to_hex(ord(c)) for c in binary_cipher)
|
|
return hex_cipher
|
|
|
|
def decrypt(self, hex_string: str) -> str:
|
|
"""
|
|
Recebe um texto criptografado em hexadecimal e retorna o texto puro.
|
|
"""
|
|
chars = []
|
|
for i in range(0, len(hex_string), 2):
|
|
hex_pair = hex_string[i : i + 2]
|
|
chars.append(chr(self._hex_to_decimal(hex_pair)))
|
|
|
|
binary_str = "".join(chars)
|
|
return self._binary_to_text(binary_str)
|
|
|
|
def decrypt_safe(self, value: str, field: str | None = None) -> str:
|
|
"""
|
|
Descriptografa com segurança:
|
|
- Se o campo estiver em _ignore_fields, retorna o valor original.
|
|
- Se o valor não parecer HEX válido, retorna o valor original.
|
|
- Em qualquer erro na descriptografia, retorna o valor original.
|
|
"""
|
|
# 1) Campo explicitamente ignorado
|
|
if field and field.lower() in self._ignore_fields:
|
|
return value
|
|
|
|
# 2) Valor vazio / None
|
|
if not value:
|
|
return value
|
|
|
|
# 3) Verifica se é HEX puro (somente 0-9 A-F) e tamanho par
|
|
import re
|
|
|
|
if re.fullmatch(r"[0-9A-Fa-f]+", value) is None:
|
|
return value
|
|
|
|
if len(value) % 2 != 0:
|
|
return value
|
|
|
|
# 4) Tenta descriptografar
|
|
try:
|
|
return self.decrypt(value)
|
|
except Exception:
|
|
return value
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Funções internas de criptografia/descriptografia
|
|
# -------------------------------------------------------------------------
|
|
|
|
def _text_to_binary_cipher(self, text: str) -> str:
|
|
"""
|
|
Criptografa um texto aplicando:
|
|
1. Inversão de caracteres.
|
|
2. Operação XOR entre cada caractere e um valor derivado da chave.
|
|
"""
|
|
text = self._reverse(text)
|
|
result = []
|
|
|
|
for position, char in enumerate(text, start=1):
|
|
key_char = self._key[position % len(self._key)]
|
|
key_value = ord(key_char) + position
|
|
result.append(chr(ord(char) ^ key_value))
|
|
|
|
return "".join(result)
|
|
|
|
def _binary_to_text(self, cipher_text: str) -> str:
|
|
"""
|
|
Descriptografa um texto binário cifrado por XOR.
|
|
O processo é simétrico: aplica o mesmo XOR e inverte novamente.
|
|
"""
|
|
result = []
|
|
|
|
for position, char in enumerate(cipher_text, start=1):
|
|
key_char = self._key[position % len(self._key)]
|
|
key_value = ord(key_char) + position
|
|
result.append(chr(ord(char) ^ key_value))
|
|
|
|
return self._reverse("".join(result))
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Funções auxiliares
|
|
# -------------------------------------------------------------------------
|
|
|
|
def _reverse(self, text: str) -> str:
|
|
"""Inverte a ordem dos caracteres de uma string."""
|
|
return text[::-1]
|
|
|
|
def _decimal_to_hex(self, number: int) -> str:
|
|
"""Converte um número decimal (byte) em uma string hexadecimal de 2 dígitos."""
|
|
return f"{number:02X}"
|
|
|
|
def _hex_to_decimal(self, hex_str: str) -> int:
|
|
"""Converte uma string hexadecimal de 2 dígitos em seu valor decimal (byte)."""
|
|
return int(hex_str, 16)
|