Hash MD5 do epílogo TISS/ANS (Padrão TISS) — implementação portável zero-dep.
Project description
tiss-hash (Python)
Calcula o "hash" do trecho final de um documento TISS/ANS. Vamos por partes, sem pressa:
- XML é um formato de arquivo de texto que organiza dados em etiquetas (tags) aninhadas, parecido com as caixas dentro de caixas de uma pasta de arquivos. O Padrão TISS é o formato XML que as operadoras de saúde e os consultórios usam para trocar informações de atendimento no Brasil.
- Hash é uma "impressão digital" do conteúdo: uma sequência curta e fixa de caracteres calculada a partir de um texto. Se uma única letra do texto mudar, o hash muda completamente. Serve para conferir que dois lados estão falando do mesmo documento.
- MD5 é uma das receitas (algoritmos) que produzem esse hash. Ele sempre
devolve 32 caracteres hexadecimais (os dígitos
0-9e as letrasa-f). - Epílogo é a parte final do documento TISS: a etiqueta
<ans:hash>, onde esse hash precisa ser gravado.
Em uma frase: você entrega os bytes de um XML TISS, esta biblioteca devolve os
32 caracteres do hash que vão dentro de <ans:hash>. (Um byte é a menor
unidade de dado que o computador manipula; um arquivo de texto é uma fila de
bytes.)
Este é o port Python da biblioteca lib_hash_ans. ("Port" = a mesma
biblioteca reescrita em outra linguagem de programação.) Outras linguagens
(C, C++, Rust, PHP, Node.js, etc.) seguem o mesmo contrato e os mesmos
vetores de conformidade. Para entender o problema que esta lib resolve, leia
docs/USAGE.md (guia de uso) e
docs/ARCHITECTURE.md (conceitos e visão geral).
Antes de começar: instalar o Python
Python é a linguagem de programação usada neste port. Se você nunca instalou:
- Baixe e instale pelo site oficial: https://www.python.org/downloads/ (precisa da versão 3.10 ou mais nova). No Windows, marque a caixa "Add Python to PATH" durante a instalação.
- No Linux/macOS, o Python costuma já vir instalado. Confira com:
python3 --version
Se aparecer algo como Python 3.12.x, está pronto. O comando pip (gerenciador
que baixa bibliotecas Python) vem junto com o Python.
Quickstart
Uma dependência é uma biblioteca de terceiros que o seu código usa. O pip
baixa e instala dependências para você.
Instalação via PyPI (o repositório oficial de pacotes Python) ainda não publicada. Por enquanto, instale a partir do checkout do repositório (isto é, da pasta que você baixou com
git clone):
pip install ./langs/python
Quando publicada, bastará:
pip install tiss-hash
Uso:
from tiss_hash import hash_tiss, hash_tiss_file
# A partir de bytes
with open("lote_tiss_exemplo.xml", "rb") as fh:
digest = hash_tiss(fh.read())
print(digest) # hex MD5 de 32 chars, ex.: '3aa0c578c95cdb861a125f480a8a4de5'
# A partir de um caminho de arquivo
digest = hash_tiss_file("lote_tiss_exemplo.xml")
Tratamento de erro:
from tiss_hash import InvalidTissXml, hash_tiss
try:
hash_tiss(b"<nao-eh-xml")
except InvalidTissXml as exc:
print(f"falhou ao parsear: {exc}")
API
| Símbolo | Tipo | Descrição |
|---|---|---|
hash_tiss(xml: bytes) -> str |
função | Hash MD5 (hex, 32 chars) a partir dos bytes do XML. |
hash_tiss_file(path: str | os.PathLike) -> str |
função | Atalho que lê o arquivo e delega para hash_tiss. |
InvalidTissXml |
classe | Exceção (subclasse de ValueError) para XML malformado ou rejeitado por política de segurança. |
__version__ |
str | Versão do pacote. |
Algoritmo
Resumo do que hash_tiss faz, em prosa. ("Parsear" um XML é ler o texto e
montar a árvore de etiquetas na memória; o parser é o componente que faz
essa leitura. Encoding é a tabela que traduz caracteres em bytes, por
exemplo UTF-8. Namespace é um prefixo que evita confusão entre etiquetas de
origens diferentes; aqui o namespace TISS identifica a etiqueta <ans:hash>.)
- Parseia o XML (com
defusedxml, isto é, sem expansão de entidades e sem DOCTYPE externo). - Zera o conteúdo de
<ans:hash>(namespacehttp://www.ans.gov.br/padroes/tiss/schemas). - Concatena o
.textde cada elemento-folha (sem filhos) em ordem documental. - Calcula MD5 sobre os bytes UTF-8 da string resultante.
- Devolve o
hexdigest()minúsculo (32 caracteres).
Atenção: o encoding dos bytes alimentados ao MD5 é UTF-8, não ISO-8859-1. O manual TISS afirma o contrário, mas o valor que bate com os goldens reais é UTF-8.
Especificação canônica completa: docs/SPEC.md (na raiz do repositório).
Implementação de referência: conformance/reference.py.
Conformidade
"Conformidade" aqui significa: provar que este port produz exatamente o mesmo hash que a implementação oficial, em todos os casos previstos. Um vetor de conformidade é um par "arquivo de entrada -> hash esperado": rodamos a lib no arquivo e conferimos se o resultado bate. Um vetor positivo deve produzir um hash; um vetor negativo deve ser rejeitado (a lib precisa recusar o arquivo, em vez de inventar um hash).
Esta lib passa os 20 vetores de conformidade em
conformance/vectors.json, todos sintéticos (source: derived): 18
positivos e 2 negativos (que devem ser rejeitados). O conjunto público de
conformidade é 100% sintético, sem qualquer XML real de paciente. Os 18
positivos cobrem: mínimo, acentuação, campos vazios, CR/LF embutido,
múltiplas guias, entidades XML, entidades numéricas, CDATA, comentário,
atributo de folha, namespace alternativo, namespace default, documento sem
<ans:hash>, whitespace puro, zeros à esquerda, símbolos ISO-8859-1,
performance e BOM UTF-8. Os 2 negativos (syn_multi_hash.xml e
syn_utf16.xml) cobrem rejeição de múltiplos <ans:hash> e de UTF-16
(fora de escopo: encodings suportados são ISO-8859-1 e UTF-8). A lista
canônica vive em conformance/vectors.json.
Rodar os testes localmente, a partir da raiz do repositório:
python -m pip install -e ./langs/python[dev]
pytest langs/python/tests/ -v
Saída esperada: 24 passed. Desses, 20 testes são os vetores de
conformidade (um por vetor, parametrizados: 18 positivos comparam o hash,
2 negativos verificam a rejeição) e 4 são testes de API auxiliares
(hash_tiss_file, XML inválido, tipo de entrada errado e integridade do
manifesto).
Dependências
- Runtime:
defusedxml>=0.7.1(pure-Python, sem deps próprias). Usado no lugar dexml.etree.ElementTree.parseda stdlib para mitigar XXE e billion-laughs em XMLs vindos de terceiros. - Extra
lxml: opcional, reservado para uma implementação alternativa mais performática no futuro. - Extra
dev:pytest,pytest-cov.
Licença
MIT Copyright (c) 2026 Petrus Silva Costa. Licença única do projeto, na raiz do repositório.
Ver também
- Repositório (origin): https://github.com/petrinhu/TISS_ANS_hash
- Mirror: https://codeberg.org/petrinhu/TISS_ANS_hash
docs/USAGE.md: guia de uso, receitas e perguntas frequentes (comece por aqui se você quer só usar a lib).docs/ARCHITECTURE.md: conceitos e visão geral de como tudo se encaixa.docs/SPEC.md: especificação canônica do algoritmo (a referência precisa, palavra por palavra).docs/PORTING_GUIDE.md: guia para portar para outras linguagens.conformance/reference.py: implementação de referência (o "oráculo", isto é, a versão que define a resposta certa).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tiss_hash-0.1.0.tar.gz.
File metadata
- Download URL: tiss_hash-0.1.0.tar.gz
- Upload date:
- Size: 12.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59a7234be35dc303488da20f45c8c31c605c5dca5c91bbb31722ac152378229d
|
|
| MD5 |
0b373c00a5061b19930f0f43a2cd0396
|
|
| BLAKE2b-256 |
8b7daccd3c24d1263a6a3c802e7d7f28b6e705c0f5af9cfa02423f081229838b
|
File details
Details for the file tiss_hash-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tiss_hash-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b8ee5543c4721ba1c2d5ddecdb26f2b98752ac8ddaf3a3f4659a227a699dcf6
|
|
| MD5 |
11d7bed44cc03c4999813dca9f17f3bf
|
|
| BLAKE2b-256 |
28a916ca47ebe931fb3a3144d140fe4a0f20ee601092b074c6aba4269f5b4e8f
|