Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validação das HASH geradas #49

Closed
pcasqueiro opened this issue Feb 20, 2020 · 42 comments
Closed

Validação das HASH geradas #49

pcasqueiro opened this issue Feb 20, 2020 · 42 comments
Labels
help wanted Extra attention is needed question Further information is requested wontfix This will not be worked on

Comments

@pcasqueiro
Copy link

Necessitamos de ajuda para compreender porque é que o validador da AGT está a dar erro nas 2ª e 3ª HASH do ficheiro SAFT em anexo.
public_phpPOS_1024.pem.txt

Falha na validação do Hash da parte AuditFile.SourceDocuments.SalesInvoices.2Invoice

Falha na validação do Hash da parte AuditFile.SourceDocuments.SalesInvoices.3Invoice

SAFT-AO-Feb-2020_facturacao.xml.txt

@cryptolopes cryptolopes added help wanted Extra attention is needed question Further information is requested labels Feb 20, 2020
@cryptolopes
Copy link
Member

cryptolopes commented Feb 20, 2020

SAF-T

SAFT-AO-Feb-2020_facturacao.xml.txt

O SAF-T não respeita a última versão do schema.

testing/SAFT-AO-Feb-2020_facturacao.xml:348: element WithholdingTaxAmount: Schemas validity error : Element '{urn:OECD:StandardAuditFile-Tax:AO_1.01_01}WithholdingTaxAmount': This element is not expected. Expected is ( {urn:OECD:StandardAuditFile-Tax:AO_1.01_01}WithholdingTaxType ).
testing/SAFT-AO-Feb-2020_facturacao.xml:404: element WithholdingTaxAmount: Schemas validity error : Element '{urn:OECD:StandardAuditFile-Tax:AO_1.01_01}WithholdingTaxAmount': This element is not expected. Expected is ( {urn:OECD:StandardAuditFile-Tax:AO_1.01_01}WithholdingTaxType ).
testing/SAFT-AO-Feb-2020_facturacao.xml:483: element WithholdingTaxAmount: Schemas validity error : Element '{urn:OECD:StandardAuditFile-Tax:AO_1.01_01}WithholdingTaxAmount': This element is not expected. Expected is ( {urn:OECD:StandardAuditFile-Tax:AO_1.01_01}WithholdingTaxType ).
testing/SAFT-AO-Feb-2020_facturacao.xml fails to validate

validação da estrutura:

$ xmllint --schema XSD/SAFTAO1.01_01.xsd testing/SAFT-AO-Feb-2020_facturacao.xml --noout

Assinaturas

public_phpPOS_1024.pem.txt

Verification Failure(1)
Verification Failure(2)
Verification Failure(3)

Parece-me que uma das causas possível é a chave privada não ter 1024 bits.

Exemplos de como fazer usando o OpenSSL

Assinar documentos usando a chave privada

$ echo -n 'mystring' | openssl dgst -sha1 -sign myprivate.pem -out sha1.sign

ou se o valor estiver guardado num ficheiro myfile.txt

$ openssl dgst -sha1 -sign myprivate.pem -out sha1.sign myfile.txt

codificar assinatura em base64

$ openssl enc -in sha1.sign -base64 -A -out sha1.b64

verificar assinatura com a chave pública

$ echo -n 'mystring' | openssl dgst -sha1 -verify mypublic.pem -signature sha1.sign

ou se o valor estiver guardado num ficheiro myfile.txt

$ openssl dgst -sha1 -verify mypublic.pem -signature sha1.sign myfile.txt

@cryptolopes cryptolopes added the wontfix This will not be worked on label Feb 20, 2020
@pcasqueiro
Copy link
Author

Caro Nelson, antes de mais, muito obrigado pela ajuda.
Algumas duvidas:
1.
Existe algum link (ou se me puder enviar por email muito agradecia) para fazer download do ultimo XSD ? é que realmente não encontro em lado nenhum, apenas para visualização.
2.
Nos Invoices o withholdingtax não faz sentido pois não existe taxa retida, correcto ? nos payments, se houver retenção terá de ser preechido com o imposto correcto.
Pode confirmar ?
E o elemento Settlement é obrigatório dentro do DocumentTotals ?

0
2020-02-17

  1. estou a gerar as chaves com OPENSSL
    openssl genrsa -out privatekey.txt 1024
    openssl rsa -in privatekey.txt -pubout -out publickey.txt

e a assinar o documento do seguinte modo:

$string2encrypt = $sales_data['sale_time'].';'.$doctype.';'.$gov_seriesprefix.'/'.$new_sale_number.';'.$sales_data['to
al'].';'.$lasthash;
$myHash = sha1($string2encrypt, TRUE); /* devolve valor binário */
openssl_private_encrypt($myHash, $encrypted, $privKey);
$encrypted_64 = base64_encode($encrypted);

este ultimo resultado, com 172 bytes, é escrito na base da dados.

parece-me equivalente ao que me envia para fazer do command line do opensll ...

@pcasqueiro
Copy link
Author

Entretanto gerei uma factura 1 e uma factura 2 e gerei as respectivas hash ecriptadas, uma de cada vez, com os comandos do openssl, com base na string a encriptar e coloquei essas hash no xml. Continuo com o mesmo erro de hash invalida.
str2enc_2.txt
str2enc_1.txt

Podem tentar do seu lado a ver se é a minha chave privada que está errada ?

privatekey.txt
publickey.txt
SAFT-AO-Feb-03_fact.xml.txt

@pcasqueiro pcasqueiro reopened this Feb 20, 2020
@aliencrash
Copy link

aliencrash commented Feb 22, 2020

Caro,
O teu ficheiro está errado. as strings geradas. Vê a imagem como deveria ser o formado da string.
imagem
Teria que ser
2020-02-21;2020-02-21T00:48:54;FR SEDFR20/1;6270.00;

@pcasqueiro
Copy link
Author

pcasqueiro commented Feb 22, 2020 via email

@cryptolopes
Copy link
Member

cryptolopes commented Feb 24, 2020

$string2encrypt = $sales_data['sale_time'].';'.$doctype.';'.$gov_seriesprefix.'/'.$new_sale_number.';'.$sales_data['to
al'].';'.$lasthash;

Parece-me existir aqui um valor em falta, o SystemEntryDate.

Atenção, é obrigatório que cada elemento esteja formatado de acordo com o schema:

  • InvoiceDate [AAAA-MM-DD]
  • SystemEntryDate [AAAA-MM-DDTHH:MM:SS]
  • InvoiceNo
  • GrossTotal [0.00] (duas casas decimais sempre!)
  • PreviousHash [172 bytes]

Parâmetros:

InvoiceDate;SystemEntryDate;InvoiceNo;GrossTotal;PreviousHash

@omdesignz
Copy link

omdesignz commented Mar 1, 2020

@pcasqueiro como resolveu esta questão. Estou com exactamente o mesmo erro. Se tiver apenas uma factura ele valida sem problemas mas quando tenho mais facturas no ficheiro XML apresenta este erro a partir da segunda factura.

code

@pcasqueiro
Copy link
Author

pcasqueiro commented Mar 2, 2020 via email

@omdesignz
Copy link

omdesignz commented Mar 2, 2020

Caro Nelson, antes de mais, muito obrigado pela ajuda.
Algumas duvidas:
1.
Existe algum link (ou se me puder enviar por email muito agradecia) para fazer download do ultimo XSD ? é que realmente não encontro em lado nenhum, apenas para visualização.
2.
Nos Invoices o withholdingtax não faz sentido pois não existe taxa retida, correcto ? nos payments, se houver retenção terá de ser preechido com o imposto correcto.
Pode confirmar ?
E o elemento Settlement é obrigatório dentro do DocumentTotals ?

0
2020-02-17

  1. estou a gerar as chaves com OPENSSL
    openssl genrsa -out privatekey.txt 1024
    openssl rsa -in privatekey.txt -pubout -out publickey.txt

e a assinar o documento do seguinte modo:

$string2encrypt = $sales_data['sale_time'].';'.$doctype.';'.$gov_seriesprefix.'/'.$new_sale_number.';'.$sales_data['to
al'].';'.$lasthash;
$myHash = sha1($string2encrypt, TRUE); /* devolve valor binário */
openssl_private_encrypt($myHash, $encrypted, $privKey);
$encrypted_64 = base64_encode($encrypted);

este ultimo resultado, com 172 bytes, é escrito na base da dados.

parece-me equivalente ao que me envia para fazer do command line do opensll ...

@pcasqueiro Refere-se a esta mensagem?

Usei o código acima e sem sucesso. Tu criaste o hash no acto da emissão da factura ou apenas no acto da exportação do ficheiro saft? Eu tenho gerado o hash no acto da emissão do documento e durante a exportação do ficheiro SAFT apenas faço a leitura das facturas (incluindo o hash).

Cmpts

@cryptolopes
Copy link
Member

cryptolopes commented Mar 2, 2020

code

@omdesignz
Uma classe para gerar o par de chaves para quê?
O par de chaves é algo que idealmente se gera apenas uma vez ao longo do ciclo de vida do produto.

@omdesignz
Copy link

code

Uma classe para gerar o par de chaves para quê?
O par de chaves é algo que idealmente se gera apenas uma vez ao longo do ciclo de vida do produto.

Caro @cryptolopes, a classe foi simplesmente para criar o par de chaves (primeira e única vez). Agora as outras classes do sistema implementam a função "encrypt". Talvez tinha que ser claro e informar que devem apenas ver a função encrypt.

Cmpts

@cryptolopes
Copy link
Member

a função "encrypt"

@omdesignz
Cola aqui por favor um exemplo de $data e de $digest

@omdesignz
Copy link

a função "encrypt"

@omdesignz
Cola aqui por favor um exemplo de $data e de $digest

code_digest_example
code_invoice

@cryptolopes
Copy link
Member

a função "encrypt"

@omdesignz

Cola aqui por favor um exemplo de $data e de $digest

Copia mesmo o valor de $digest e $data.

@omdesignz
Copy link

a função "encrypt"

@omdesignz

Cola aqui por favor um exemplo de $data e de $digest

Copia mesmo o valor de $digest e $data.

$data = 2020-01-01;2020-01-01T15:56:56;FT 2020/1;2700.00
$digest = 8859489f388afd6e6273a346a520ad8cca5e7926

@omdesignz
Copy link

@cryptolopes algum feedback que possa me dar? Até ao momento continuo com dificuldades ao validar o campo hash dos documentos no portal da AGT.

@cryptolopes
Copy link
Member

cryptolopes commented Mar 5, 2020

Olá @omdesignz

Falta um ; após o valor respeitante ao GrossTotal.

$data = 2020-01-01;2020-01-01T15:56:56;FT 2020/1;2700.00;
$digest = 5bc0529b6136d9e58fb8dc585427a95a7024d0e7

ver #49 (comment)

@pcasqueiro
Copy link
Author

pcasqueiro commented Mar 5, 2020 via email

@omdesignz
Copy link

@cryptolopes muito obrigado pelo feedback. Já estava a procura de outras formas de criar a assinatura. Vou reverter as alterações feitas, incluir o ; após o GrossTotal e voltar a testar.

Obrigado

@cryptolopes
Copy link
Member

cryptolopes commented Mar 5, 2020

Mesmo quando não tem “lasthash” leva esse separador “;” após o total ?

Sim. O ; atua uma como um separador de elementos.

@omdesignz
Copy link

Caros Produtores,
Boa tarde.

Após várias tentativas e diagnósticos na nossa classe de gerar o hash para cada documento, finalmente conseguimos gerar um hash validado com êxito no portal da AGT.

Alguns "GOTCHAS" que podemos frisar:

  1. O comando para a criação da assinatura no instrutivo fornecido pela AGT levou-nos a crer que podemos seguir as instruções linha por linha, que não devia ser, visto que não estamos a fazer uso da linha de comandos. Para os produtores que fazem uso da linha de comandos as instruções funcionam de uma forma impecável. Contudo, para o nosso caso, usando PHP e gerando o hash de uma dinâmica sem recorrer a linha de comandos e nem mesmo criar ficheiros os comandos diferem.

openssl dgst -sha1 -sign ChavePrivada.pem -out Registo1.sha1 Registo1.txt

  • Não precisamos criar o digest da informação a ser assinada porque o mesmo é criado automaticamente com a função openssl_sign($data, $signature, $private_key, OPENSSL_ALGO_SHA1);
  1. Como o código final e funcional, temos o seguinte:

code_data_sign_AGT

Estamos gratos pelos inputs do @pcasqueiro e @cryptolopes. Esperamos poder ajudar alguém que possa ter a mesma dificuldade.

@pcasqueiro
Copy link
Author

pcasqueiro commented Mar 7, 2020 via email

@omdesignz
Copy link

omdesignz commented Mar 7, 2020

Infelizmente o código:
$string2encrypt = $sales_data['sale_time'].';'.$doctype.';'.$gov_seriesprefix.'/'.$new_sale_number.';'.$sales_data['to al'].';'.$lasthash; $myHash = sha1($string2encrypt, TRUE); /* devolve valor binário */ openssl_private_encrypt($myHash, $encrypted, $privKey); $encrypted_64 = base64_encode($encrypted);

Não funcionou connosco.

@vd-king
Copy link

vd-king commented Apr 22, 2020

Boa tarde caríssimos,

Pretendo algumas dicas de como encriptar os dados usando a criptografia RSA, quando o tamanho do dado a encriptar é superior ao tamanho da chave (1024), e garantir que o texto encriptado não passe dos 172 bytes, usando a aplicação OpenSSL corre bem, mais ao usar o C#, ou o VB.NET me deparo com a dificuldade acima exposta.

Osvaldo Mateus

@cryptolopes
Copy link
Member

@vd-king
Copy link

vd-king commented Apr 22, 2020

@cryptolopes , grato pela pronta resposta, por acaso já acedi varias vezes o link sugerido, mais não optive sucesso, ja tentei importar de alguma forma uma biblioteca OpenSSL, mais mesmo assim não obtive sucesso, importa referir que quando se trata do primeiro registo, a encriptação corre com sucesso, mais a partir do segundo registo começam os erros

@pcasqueiro
Copy link
Author

pcasqueiro commented Apr 22, 2020 via email

@vd-king
Copy link

vd-king commented Apr 22, 2020

@cryptolopes , a grande questão é que a biblioteca Chilkat deve ser desbloqueada.

@pcasqueiro
Copy link
Author

pcasqueiro commented Apr 22, 2020 via email

@vd-king
Copy link

vd-king commented Apr 22, 2020

@pcasqueiro , grato pela resposta, o projecto acima serve apenas para criar certificados, assinar digitalmente. não permite criptografar e decriptografar,.

@pcasqueiro
Copy link
Author

pcasqueiro commented Apr 22, 2020 via email

@pcasqueiro
Copy link
Author

pcasqueiro commented Apr 22, 2020 via email

@vd-king
Copy link

vd-king commented Apr 22, 2020

Boa noite @pcasqueiro , grato pela resposta , ficarei aguardar a resposta do teste.
de salientar que estou a usar o c# e vb.net, ja tentei usar a biblioteca OpenSSL Chilkat, a questão é que é paga. já tentei executar o openssl a partir do vb.net, mais não acho a maneira mais correcta.

@vd-king
Copy link

vd-king commented Apr 23, 2020

Boa tarde @pcasqueiro , alguma novidade sobre os testes.
cmpts

@diogo-artilheiro-gomes
Copy link

Boa tarde,

Estou neste momento com o processo de certificação em curso e o unico ponto pendente é o SAFT.
Ao validar o ficheiro na plataforma da AGT recebo erro

"Falha na validação do hash da parte AuditFile.SourceDocuments.SalesInvoice.2Invoice"

Analisei as respostas a este issue e penso que todos os pontos estão correto. deixo a hash string base da fatura que é referenciada no erro:

2020-05-22;2020-05-22T16:29:38;FT 201/2020000002;30000.00;HZtWynzU3k7bNsF4/F+VpibbOgZc5CZ5858RNNNHqQHmvaQXYG4JPAjGk6N0YO

Alguem consegue ajudar?

@Stefano-Lorenzo
Copy link

Boas caríssimos,

Tenho dificuldades na validação das hash.

1ª assinatura:
2020-10-27;2020-10-27T20:32:13;OR 6ALL2020/1;67500.00;

hash: ZA5DkeKJ6y9OOwhZB+nqiXHXkPvlDYepgX53a00B3XmkV6WwaZy5fegDvM8A6xk9es/W8k8IpYimRC5GRQznHP9e/LKV9pGLMejszuw7UCZ2QRuz4mUrOJTYXqWYNYqTK9BV2KTIwqtV8ibivx/2oIQn6AsH7iDdvy2uxb1V7+w=

2ª assinatura:
2020-10-27;2020-10-27T20:32:49;OR 6ALL2020/2;95760.00;ZA5DkeKJ6y9OOwhZB+nqiXHXkPvlDYepgX53a00B3XmkV6WwaZy5fegDvM8A6xk9es/W8k8IpYimRC5GRQznHP9e/LKV9pGLMejszuw7UCZ2QRuz4mUrOJTYXqWYNYqTK9BV2KTIwqtV8ibivx/2oIQn6AsH7iDdvy2uxb1V7+w=

hash:
KU8tdvO0tgm0kVN82YiAbztQNsMEovGl4vLBBnxuQCRJSJJbJTI1ZEo8K9U5DHZi8YoBgfddEgRTRhKAnMS9GAuousvsSpYq8JQMOp4h4TDNQt+AfC2VMNgWNfLmzjhoZ39vK4+Im+Uo9Jo/oQ4FfNQZCzaEthiyz1FJEBNn+6o=

Capturar2

ChavePublica.txt

@3tipo
Copy link

3tipo commented Sep 6, 2021

PESSOAL UMA INFORMAÇÃO!!!!
SERÁ QUE AO VALIDAR O FICHEIRO SAFT NO PORTAL DA AGT DÃO UM LIMITE DE VEZES?
ESTOU ATENTAR SUBMETER PARA VALIDAR NÃO ESTÁ A COMPILAR(NEM DIZER QUE ESTÁ ERRADOO NEM DIZER QUE ESTÁ CERTO.
ME AJUDEM POR FAVOR

@NunoChandama
Copy link

Olá pessoal boa noite...

Estou precisando de alguns inputs com relação ao ficheiro. Cumpri com todos os requisitos e parâmetros.
Mas ainda validador diz sempre "HASH ERRADO" a partir do 2º documento

@JudsonArtur
Copy link

Caros Produtores, Boa tarde.

Após várias tentativas e diagnósticos na nossa classe de gerar o hash para cada documento, finalmente conseguimos gerar um hash validado com êxito no portal da AGT.

Alguns "GOTCHAS" que podemos frisar:

  1. O comando para a criação da assinatura no instrutivo fornecido pela AGT levou-nos a crer que podemos seguir as instruções linha por linha, que não devia ser, visto que não estamos a fazer uso da linha de comandos. Para os produtores que fazem uso da linha de comandos as instruções funcionam de uma forma impecável. Contudo, para o nosso caso, usando PHP e gerando o hash de uma dinâmica sem recorrer a linha de comandos e nem mesmo criar ficheiros os comandos diferem.

openssl dgst -sha1 -sign ChavePrivada.pem -out Registo1.sha1 Registo1.txt

  • Não precisamos criar o digest da informação a ser assinada porque o mesmo é criado automaticamente com a função openssl_sign($data, $signature, $private_key, OPENSSL_ALGO_SHA1);
  1. Como o código final e funcional, temos o seguinte:

code_data_sign_AGT

Estamos gratos pelos inputs do @pcasqueiro e @cryptolopes. Esperamos poder ajudar alguém que possa ter a mesma dificuldade.

Validação do hash do segundo Invoice continua a dar erro..

@Antonio1725
Copy link

Boa Tarde
JudsonArtur
Eu sou amador em php.
E tenho um projeto na qual preciso desenvolver um software para lincenciar na AGT gostarias que me desses uma explicação de como gerar um codigo hash mas com codigos simples

@Garcia2159
Copy link

Saudações a todos pessoal....

Meu nome é Garcia Miguel, sou programador PhP. Estou precisando de ajuda para a validação do Ficheiro Saft no Portal da AGT.

Mas até ao momento estou tendo bastante dificuldades na criação e validação do 1º Registo (Hash), segundo registo (2º Hash) e subsenquente. Por favor, alguém pra me orientar nessa. Por favor

@Antonio1725
Copy link

Antonio1725 commented Feb 15, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed question Further information is requested wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests