Adicionar src/renatoxsr-py/utils/zwid.py
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import base64
|
||||
|
||||
# Marcadores de fronteira (Não alteram o visual do texto)
|
||||
ZW_START = '\u200a' # Hair Space (usado como marcador de início)
|
||||
ZW_END = '\u202f' # Narrow No-Break Space (usado como marcador de fim)
|
||||
|
||||
# Lista com exatamente 32 caracteres invisíveis para os dados (Base32)
|
||||
ZW_CHARS = [
|
||||
'\u200b', '\u200c', '\u200d', '\ufeff', '\u200e', '\u200f', '\u202a', '\u202b',
|
||||
'\u202c', '\u202d', '\u202e', '\u2060', '\u2061', '\u2062', '\u2063', '\u2064',
|
||||
'\u2066', '\u2067', '\u2068', '\u2069', '\u206a', '\u206b', '\u206c', '\u206d',
|
||||
'\u206e', '\u206f', '\ufe00', '\ufe01', '\ufe02', '\ufe03', '\ufe04', '\ufe05',
|
||||
]
|
||||
|
||||
B32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
|
||||
|
||||
# Mapeamentos para conversão rápida
|
||||
B32_TO_ZW = {B32_ALPHABET[i]: ZW_CHARS[i] for i in range(32)}
|
||||
ZW_TO_B32 = {ZW_CHARS[i]: B32_ALPHABET[i] for i in range(32)}
|
||||
|
||||
def ocultar_texto(texto_visivel: str, texto_oculto: str) -> str:
|
||||
"""Codifica o texto oculto e o envelopa com marcadores de início e fim."""
|
||||
# Converte o texto oculto para Base32 sem padding
|
||||
b32_data = base64.b32encode(texto_oculto.encode('utf-8')).decode('utf-8').replace('=', '')
|
||||
|
||||
# Converte para a sequência invisível e adiciona as fronteiras START e END
|
||||
zw_encoded = ZW_START + "".join(B32_TO_ZW[char] for char in b32_data) + ZW_END
|
||||
|
||||
# Insere o bloco invisível de forma segura no início do texto visível
|
||||
return zw_encoded + texto_visivel
|
||||
|
||||
def revelar_texto(texto_com_marca: str) -> str:
|
||||
"""Localiza os marcadores de início e fim para extrair e decodificar o payload."""
|
||||
# Encontra os índices dos delimitadores
|
||||
try:
|
||||
inicio = texto_com_marca.index(ZW_START) + 1
|
||||
fim = texto_com_marca.index(ZW_END, inicio)
|
||||
except ValueError:
|
||||
return "" # Marcadores não encontrados ou incompletos
|
||||
|
||||
# Extrai apenas o bloco que está estritamente entre o início e o fim
|
||||
bloco_invisivel = texto_com_marca[inicio:fim]
|
||||
|
||||
# Filtra apenas os caracteres válidos do nosso alfabeto de dados
|
||||
zw_extraido = [char for char in bloco_invisivel if char in ZW_TO_B32]
|
||||
|
||||
# Reconstrói a string Base32
|
||||
b32_data = "".join(ZW_TO_B32[char] for char in zw_extraido)
|
||||
|
||||
if not b32_data:
|
||||
return ""
|
||||
|
||||
# Ajusta o padding do Base32
|
||||
mod = len(b32_data) % 8
|
||||
if mod:
|
||||
b32_data += '=' * (8 - mod)
|
||||
|
||||
return base64.b32decode(b32_data.encode('utf-8')).decode('utf-8')
|
||||
|
||||
# --- Exemplo de Uso ---
|
||||
if __name__ == "__main__":
|
||||
texto_original = "Mensagem importante que será enviada ao cliente."
|
||||
id_secreto = "ID-999-STRICT"
|
||||
|
||||
# Injetando
|
||||
texto_com_payload = ocultar_texto(texto_original, id_secreto)
|
||||
print(f"Texto gerado (Total de caracteres: {len(texto_com_payload)}):")
|
||||
print(f"-> {texto_com_payload} <-\n")
|
||||
|
||||
# Extraindo
|
||||
id_descoberto = revelar_texto(texto_com_payload)
|
||||
print(f"ID isolado e extraído com sucesso: '{id_descoberto}'")
|
||||
Reference in New Issue
Block a user