Gerando o MD5 a ser impresso no cupom fiscal
Breve explicação do requisito IX do roteiro de homologação, a partir da versão 1.05.
Você não gostou da qualidade deste conteúdo?
(opcional) Você gostaria de comentar o que não lhe agradou?
Tenho sido questionado nos últimos dias sobre a nova regra do requisito IX do roteiro, aplicado a partir da versão 1.05.
Vamos analisar o texto.
ITEM 1: O PAF-ECF deve, a cada inicialização:
Logo na descrição já indica que deverá ser executado esta rotina toda vez que o aplicativo for inicializado, ou seja, no Delphi deverá se adicionado no evento “OnShow” do formulário principal;
a) gerar, por meio do algoritmo Message Digest-5 (MD-5), código de autenticação para cada arquivo
executável que realize os requisitos estabelecidos nesta especificação;
b) gerar um arquivo texto contendo a lista de arquivos autenticados, e seus respectivos códigos MD-5;
Nos itens “a” e “b” dizem para gerar um código MD5 para cada executável que fizer parte do PAF-ECF e armazenar em um arquivo do tipo “.TXT”. O arquivo deverá ficar mais ou menos assim:
C:\PAF_ECF\Configura.exe - a79fdb1100bc785fd2abe545686c2712
C:\PAF_ECF\Retaguarda.exe - 2eb6f562cf2ef6b6b66ed714c9413d47C
C:\PAF_ECF\PAF_ECF.exe - f32e0be6eba2c53983f9d767c5b0011d
C:\PAF_ECF\Sintegra.exe - f2151c0cf348cfa062b9569d9695488b
c) gerar, por meio do algoritmo Message Digest-5 (MD-5), código de autenticação do arquivo TXT a
que se refere a alínea “b” e gravar o resultado no arquivo auxiliar criptografado e inacessível ao
estabelecimento usuário de que trata o item 4 do Requisito XXII, sobrepondo à gravação anteriormente
realizada, devendo este código ser impresso no Cupom Fiscal, no campo:
Já no item “c”, diz que deverá ser gerado o MD5 do arquivo texto criado anteriormente com a lista de executáveis, e armazenar de forma criptografada, junto com o Serial e GT da impressora no arquivo auxiliar de verificação, referido no requisito XXII.
c1) "informações complementares", no caso de ECF que disponibilize este campo, devendo utilizar este
campo para esta informação e iniciando a impressão na primeira coluna da primeira linha;
c2) "mensagens promocionais", no caso de ECF que não disponibilize o campo "informações
complementares", devendo utilizar a primeira linha para esta informação e iniciando a impressão na
primeira coluna da primeira linha.
No complemento do item “c”, diz para imprimir este MD5 do arquivo “.TXT”, que foi armazenado no arquivo auxiliar, na primeira coluna da primeira linha do campo de mensagem promocional, usada para realizar o fechamento do cupom fiscal, ou seja, em todos os cupons fiscal impressos, deverá ter este MD5 no fechamento, como primeira informação.
Este requisito é uma forma de garantir que não haverá alterações no aplicativo homologado, pois uma vez que tenha alguma alteração no executável, o código MD5 não será mais o mesmo. E mesmo que não haja alteração na fonte do executável, o simples fato de re-compilar o mesmo, acarretará em mudança no MD5.
Segue abaixo o script da função que uso para realizar esta operação;
var Arquivo : TextFile;
NomeArq, ArqTexto, aMD5 : String;
F: TSearchRec;
Ret: Integer;
begin
Result := '';
try
// Apaga arquivo anterior
ArqTexto := ExtractFilePath(Application.ExeName)+'ArqMD5.txt';
if FileExists(ArqTexto) then
DeleteFile(ArqTexto);
// cria o arquivo TXT na mesma pasta do sistema
AssignFile(Arquivo,ArqTexto);
ReWrite(Arquivo);
// lista todos os arquivo exe da pasta do aplicativo e gera o MF5
Ret := FindFirst(ExtractFilePath(Application.ExeName)+'\*.exe', faAnyFile, F);
try
while Ret = 0 do
begin
if F.Attr and faDirectory <> faDirectory then
begin
NomeArq := ExtractFilePath(Application.ExeName)+'\'+F.Name;
aMD5 := MD5Print(MD5File(NomeArq));
WriteLn(Arquivo,NomeArq+' - '+aMD5);
end;
Ret := FindNext(F);
end;
finally
FindClose(F);
end;
Closefile(Arquivo);
// gera MD5 do arquivo texto
finally
Result := MD5Print(MD5File(ArqTexto));
end;
end;
Luis Carlos Godinho
Programador formado em 1995, pela ETEIT – Escola técnica da UNIVALE. Atualmente trabalhando com a plataforma Delphi. Tem se dedicado nos últimos anos, ao desenvolvimento de aplicações PAF-ECF, SPED fiscal e NFe.
40 COMENTÁRIOS
No artigo ficou faltando a funcao MD5Print(MD5File(ArqTexto));
Voce poderia passa-la?
Obrigado, assistencia@cmbalancas.com.br
Não é pra acontecer isso, pois a rotina deve ficar no onshow do formulário e com certeza neste momento o executável esta em uso. Você baixou o aplicativo exemplo que esta disponível no topo da página. Caso não tenha baixado, dê uma olhada lá, pois no exemplo esta fazendo certinho.
Abs!
para
para
para
var
Arquivo : TextFile;
NomeArq, ArqTexto, aMD5: string;
F : TSearchRec;
Ret : Integer;
begin
Result := '';
try
// Apaga arquivo anterior
ArqTexto := ExtractFilePath(Application.ExeName)+'ArqMD5.txt';
if FileExists(ArqTexto) then
DeleteFile(ArqTexto);
// cria o arquivo TXT na mesma pasta do sistema
AssignFile(Arquivo, ArqTexto);
ReWrite(Arquivo);
// lista todos os arquivo exe da pasta do aplicativo e gera o MF5
Ret := FindFirst(ExtractFilePath(Application.ExeName)+'\*.exe', faAnyFile, F);
try
while Ret=0 do
begin
if F.Attr and faDirectory<>faDirectory then
begin
NomeArq := ExtractFilePath(Application.ExeName)+'\'+F.Name;
aMD5 := MD5Print(MD5File(NomeArq));
WriteLn(Arquivo, NomeArq+' - '+aMD5);
end;
Ret := FindNext(F);
end;
finally
FindClose(F);
end;
Closefile(Arquivo);
// gera MD5 do arquivo texto
finally
Result := MD5Print(MD5File(ArqTexto));
end;
Olá!
ainda não terminei de ler todo o roteiro do paf, mas fiquei com uma duvida nessa sua aula: o aplicativo paf (ou seja, o executavel do paf) vai gerar um arquivo txt com todos os executaveis que estão no diretorio (que sub-entende que sejam os executaveis homologados), mas por que o retaguarda está ali? vou ter que homologar meu retaguarda tambem? meu retaguarda muda semanalmente, esse MD5 sempre vai mudar, como fica?
abraço!
Fernando.
Todos os executáveis e DLL que compôem o projeto do PAF. Se o seu retaguarda fizer parte do PAF, acredito que deverá homologar. Ma entendo que o retaguarda não precisa fazer parte do PAF.
Este projeto é apenas um exemplo.
Abs!
Entram sim, basta fazer a rotina adicionando a extenção .DLL.
Abs!
Grato,
André
plansoft@gmail.com
No proprio componente Acbr pode ser encontrada a unit.
De qualquer forma, segue o link:
http://www.koders.com/delphi/fid5A4F925F646C191A79107D11EDD80DDDF205615E.aspx
Abs!
http://www.devmedia.com.br/post-17327-MD5-em-Delphi-2010-Parte-I.html
Muito boa a dica, Obrigado!
Abs.!
O MD5 deve ser impressora no Cupom Fiscal?
Deve ser impresso na mensagem promocional do cupom o MD5 do arquivo txt com a lista de executaveis.
Abs.!
Gostaria de tirar uma dúvida..
O MD5 impresso no rodapé do cupom é o MD5 do arquivo .TXT que contém a relação dos binários e seus repectivos MD5, certo?
Porém cada vez que o PAF-ECF for inicializado, o mesmo deve recriar o arquivo arquivo texto, porém, pelo de recriar o arquivo .TXT, o mesmo fica com o seu md5 modificado.
Nós implementamos o nosso PAF-ECF desta forma e estamos tendo difilculdade, porque no laudo vai o md5 do arquivo .TXT gerado na última vez que foi execultado o aplicativo, porém, quando o mesmo é execultado navamento o arquivo .TXT é recriado com o mesmo conteúdo, porém com o md5 alterado.
Estamos realizando o procedimento correto?
O arquivo deve .TXT deve ser recriado?
Ao ser recriado e com isso o seu MD5 modificado isso não pode gerar problemas na confaz?
Agradeço a atenção dispensada,
Obrigado pela força.
Sds,
Cardoso
Sim, o txt com os MD5 deve ser recriado toda vez que entra. E apenas será modificado caso tenha sido alterado alguma coisa, mesmo que apenas um espaço em branco nos codigos. Caso contrario o mesmo não será alterado apenas com a execução.
Se no seu estiver alterando o MD5 toda vez que entra, certamente esta fazendo algo errado na rotina.
Abs.!
Ao Gerar o Arquivo PAF_LISTAMD5, as Dll's que tem o nome grande, por exemplo a darumaframework.dll sai zerado.
N3BEMAFI32.DLL E3311B82C38F603BACF23A2E76C6FFCF
N3DARUMAFRAMEWORK.DLL 00000000000000000000000000000000
Você saberia dizer se tem mesmo a ver com o tamanho do nome das dll's ou algum outro parâmetro?
Muito obrigado...
Acho que não tem haver com o tamanho do nome, mas para ter certeza renomeie o nome da mesma e tente executar pra ver.
Abs.!
Eu ainda não tive a oportunidade de trabalhar com o XE3 e Firemonkey, por isso não tenho uma sugestão. Mas sugiro colocar no fórum uma questão sobre recuperação de Path, provavelmente terá alguém que passou pelo mesmo problema. Como não tenho o XE3 aqui não tenho como tentar simular pra ver alguma sugestão.
Abs.!
COMO FAÇO P/IMPLEMENTAR ESSA FUNÇÃO NO DELPHI XE2,POIS TENTEI INCLUIR NO MEU PROJETO MAS ESTA DANDO ALGUNS ERROS!
O erro conhecido por mim é o da geração do MD5 que no caso não funciona com a unit em questão. A sugestão seria usar o exemplo do artigo do link: http://www.devmedia.com.br/md5-com-delphi-usando-indy/12647.
Abs.!
NO DELPHI 7 UM DETERMINADO EXE COM A FUNÇÃO GERA O MD5=36af7971b5d560f55f5dbf02504ca5ce E NO XE2 O MESMO EXE A FUNÇÃO RETORNA O MD5=d41d8cd98f00b204e9800998ecf8427e!
Se estiver tendo outro problema além deste, peço que especifique para que eu tente ajudar.
Abs.!
POIS ESTA DIVERGINDO DO MD5 GERADO COM O DELPHI 7!
QUAL SERIA A SOLUÇÃO P/ O XE2?
o que preciso saber é os erros que comentou. Quais são para que possa te ajudar.
MAS ESTÁ GERANDO O MD5 ERRADO!COMO EU LI FALEI,NO DELPHI 7 GERA O MD5 CERTO,E NO XE2 GERA UM MD5 DIFERENTE!ENTENDEU?
Abs.!
A ROTINA ESTA FUNCIONANDO NO XE2!SÓ Q COMO EU TINHA DITO,O MD5 GERADO NA ROTINA COM O DELPHI 7 É O CORRETO POIS ESTOU TESTANDO EM UM EXECUTÁVEL Q JA FOI HOMOLOGADO E O MD5 CONFERE!SÓ Q QUANDO GERO NO XE2 ESTÁ GERANDO UM MD5 DIFERENTE!OQ VC TEM A DIZER SOBRE ISSO?
Abs.!
COMO ASSIM INDY?
ME EXPLIQUE MELHOR!
uses
IdHashMessageDigest;
function MD5Arquivo(const Value: string): string;
var
xMD5: TIdHashMessageDigest5;
xArquivo: TFileStream;
begin
xMD5 := TIdHashMessageDigest5.Create;
xArquivo := TFileStream.Create(Value, fmOpenRead OR fmShareDenyWrite);
try
Result := xMD5.HashStreamAsHex(xArquivo);
finally
xArquivo.Free;
xMD5.Free;
end;
end;
function MD5String(const Value: string): string;
var
xMD5: TIdHashMessageDigest5;
begin
xMD5 := TIdHashMessageDigest5.Create;
try
Result := xMD5.HashStringAsHex(Value);
finally
xMD5.Free;
end;
end;

download

