Problema com o campo <SignatureValue>

527 views
Skip to first unread message

Adriano Garcia

unread,
Aug 27, 2012, 12:06:49 PM8/27/12
to nfe...@googlegroups.com
Pessoal, sou novo no forum e gostaria de compartilhar conhecimentos com vocês.
Estou assinando minha XML e sempre da o erro de  297 [xMotivo] => Rejeição: Assinatura difere do calculado  
Eu baixei o emissor da secretaria de SP e gerei a mesma nota e conferi item por item e esta tudo igual, menos o campo <SignatureValue>.
Fazendo varios testes verifiquei que mesmo eu mudando as informações da nota ele gera sempre o mesmo codigo no campo <SignatureValue> sendo que deveria mudar os caracteres em cada nota emitida.
Alguém ja teve esse problema?
Segue anexo meu xml
Att

Adriano Garcia
teste-sign1.xml

FerreiraH.

unread,
Aug 27, 2012, 1:39:50 PM8/27/12
to nfe...@googlegroups.com
seu codigo esta colocando uma constante ?
ou seu codigo le sempre a mesma parte do xml 

--
--
Você recebeu esta mensagem porque está inscrito no Grupo "NFePHP".
Para Postar: nfe...@googlegroups.com
Para Sair do Grupo: nfephp+un...@googlegroups.com
Link: http://groups.google.com.br/group/nfephp?hl=pt-BR
-------
FAQ: https://www.assembla.com/wiki/show/nfephp/FAQ
Como Participar: https://www.assembla.com/wiki/show/nfephp/Como_participar
Como Utilizar: http://www.assembla.com/wiki/show/nfephp/Como_utilizar
 
 
 



--
 Sistema de Automação Comercial Open Source
Ferreira Helder

Adriano Garcia

unread,
Aug 27, 2012, 2:20:32 PM8/27/12
to nfe...@googlegroups.com
Boa Tarde Ferreira

Como se tivesse uma constante que esta jogando sempre na mesma tag <SignatureValue> do XML assinado.
Estou usando a API e segue a parte do codigo que gera a assinatura:

public function signXML($docxml, $tagid=''){
            if ( $tagid == '' ){
                $this->errMsg = "Uma tag deve ser indicada para que seja assinada!!\n";
                $this->errStatus = true;
                return false;
            }
            if ( $docxml == '' ){
                $this->errMsg = "Um xml deve ser passado para que seja assinado!!\n";
                $this->errStatus = true;
                return false;
            }
            // obter o chave privada para a ssinatura
            $fp = fopen($this->priKEY, "r");
            $priv_key = fread($fp, 8192);
            fclose($fp);
            $pkeyid = openssl_get_privatekey($priv_key);
            // limpeza do xml com a retirada dos CR, LF e TAB
            $order = array("\r\n", "\n", "\r", "\t");
            $replace = '';
            $docxml = str_replace($order, $replace, $docxml);
            // carrega o documento no DOM
            $xmldoc = new DOMDocument('1.0', 'utf-8');
            $xmldoc->preservWhiteSpace = false; //elimina espaços em branco
            $xmldoc->formatOutput = false;
            // muito importante deixar ativadas as opçoes para limpar os espacos em branco
            // e as tags vazias
            if ($xmldoc->loadXML($docxml,LIBXML_NOBLANKS | LIBXML_NOEMPTYTAG)){
                $root = $xmldoc->documentElement;
            } else {
                $this->errMsg = "Erro ao carregar XML, provavel erro na passagem do parâmetro docXML!!\n";
                $this->errStatus = true;
                return false;
            }
            //extrair a tag com os dados a serem assinados
            $node = $xmldoc->getElementsByTagName($tagid)->item(0);
            $id = trim($node->getAttribute("Id"));
            $idnome = preg_replace('/[^0-9]/','', $id);
            //extrai os dados da tag para uma string
            $dados = $node->C14N(false,false,NULL,NULL);
            //calcular o hash dos dados
            $hashValue = hash('sha1',$dados,true);
            //converte o valor para base64 para serem colocados no xml
            $digValue = base64_encode($hashValue);
            //monta a tag da assinatura digital
            $Signature = $xmldoc->createElementNS($this->URLdsig,'Signature');
            $root->appendChild($Signature);
            $SignedInfo = $xmldoc->createElement('SignedInfo');
            $Signature->appendChild($SignedInfo);
            //Cannocalization
            $newNode = $xmldoc->createElement('CanonicalizationMethod');
            $SignedInfo->appendChild($newNode);
            $newNode->setAttribute('Algorithm', $this->URLCanonMeth);
            //SignatureMethod
            $newNode = $xmldoc->createElement('SignatureMethod');
            $SignedInfo->appendChild($newNode);
            $newNode->setAttribute('Algorithm', $this->URLSigMeth);
            //Reference
            $Reference = $xmldoc->createElement('Reference');
            $SignedInfo->appendChild($Reference);
            $Reference->setAttribute('URI', '#'.$id);
            //Transforms
            $Transforms = $xmldoc->createElement('Transforms');
            $Reference->appendChild($Transforms);
            //Transform
            $newNode = $xmldoc->createElement('Transform');
            $Transforms->appendChild($newNode);
            $newNode->setAttribute('Algorithm', $this->URLTransfMeth_1);
            //Transform
            $newNode = $xmldoc->createElement('Transform');
            $Transforms->appendChild($newNode);
            $newNode->setAttribute('Algorithm', $this->URLTransfMeth_2);
            //DigestMethod
            $newNode = $xmldoc->createElement('DigestMethod');
            $Reference->appendChild($newNode);
            $newNode->setAttribute('Algorithm', $this->URLDigestMeth);
            //DigestValue
            $newNode = $xmldoc->createElement('DigestValue',$digValue);
            $Reference->appendChild($newNode);
            // extrai os dados a serem assinados para uma string
            $dados = $SignedInfo->C14N(false,false,NULL,NULL);
            //inicializa a variavel que irá receber a assinatura
            $signature = '';
            //executa a assinatura digital usando o resource da chave privada
            $resp = openssl_sign($dados,$signature,$pkeyid);
            //codifica assinatura para o padrao base64
            $signatureValue = base64_encode($signature);
            //SignatureValue
            $newNode = $xmldoc->createElement('SignatureValue',$signatureValue);
            $Signature->appendChild($newNode);
            //KeyInfo
            $KeyInfo = $xmldoc->createElement('KeyInfo');
            $Signature->appendChild($KeyInfo);
            //X509Data
            $X509Data = $xmldoc->createElement('X509Data');
            $KeyInfo->appendChild($X509Data);
            //carrega o certificado sem as tags de inicio e fim
            $cert = $this->__cleanCerts($this->pubKEY);
            //X509Certificate
            $newNode = $xmldoc->createElement('X509Certificate',$cert);
            $X509Data->appendChild($newNode);
            //grava na string o objeto DOM
            $docxml = $xmldoc->saveXML();
            // libera a memoria
            openssl_free_key($pkeyid);
            //retorna o documento assinado
            return $docxml;
    }

Att

Adriano Garcia

On Monday, August 27, 2012 2:39:50 PM UTC-3, FERREIRA.H wrote:
seu codigo esta colocando uma constante ?
ou seu codigo le sempre a mesma parte do xml 

Em 27 de agosto de 2012 13:06, Adriano Garcia <veto...@gmail.com> escreveu:
Pessoal, sou novo no forum e gostaria de compartilhar conhecimentos com vocês.
Estou assinando minha XML e sempre da o erro de  297 [xMotivo] => Rejeição: Assinatura difere do calculado  
Eu baixei o emissor da secretaria de SP e gerei a mesma nota e conferi item por item e esta tudo igual, menos o campo .
Fazendo varios testes verifiquei que mesmo eu mudando as informações da nota ele gera sempre o mesmo codigo no campo <SignatureValue> sendo que deveria mudar os caracteres em cada nota emitida.
Alguém ja teve esse problema?
Segue anexo meu xml
Att

Adriano Garcia

--
--
Você recebeu esta mensagem porque está inscrito no Grupo "NFePHP".
Para Postar: nfe...@googlegroups.com
Para Sair do Grupo: nfephp+un...@googlegroups.com
Link: http://groups.google.com.br/group/nfephp?hl=pt-BR
-------
FAQ: https://www.assembla.com/wiki/show/nfephp/FAQ
Como Participar: https://www.assembla.com/wiki/show/nfephp/Como_participar
Como Utilizar: http://www.assembla.com/wiki/show/nfephp/Como_utilizar
 
 
 

Jose Luiz Aguiari

unread,
Aug 20, 2018, 10:18:06 PM8/20/18
to NFePHP
Olá.. boa noite... 
Pesquisando esse tipo de erro... tb estou com esse problema hoje... não uso o NFePHP optei em fazer um transmissor próprio pois o NFePHP começou a ficar meio que impossível até em dar manutenção quando se muda algo simples, em fim, optei em fazer um próprio... Estou me deparando exatamente com esse erro.. já pesquisei em vários sites e nada... 
Vi que sua mensagem foi em 2012 e se obteve algum sucesso e poder compartilhar agradeceria muito, como disse... olhando sua rotina fiz uma com as mesmas caractristicas mas não encentro o erro...


  public function AssinaXML($TagId, $pXML = '')
  {
    $_IdFun = 'AssinaXML';
    try
    {
//remove sujeiras do xml...
      $asc31 = array(chr(1),chr(2),chr(3),chr(4),chr(5),chr(6),chr(7),chr(8),chr(9),chr(10),chr(11),chr(12),chr(13),chr(14),chr(15),chr(16),
                     chr(17),chr(18),chr(19),chr(20),chr(21),chr(22),chr(23),chr(24),chr(25),chr(26),chr(27),chr(28),chr(29),chr(30),chr(31),
                     $hXML,$hXMLSimples);

//limpar caracteres ASCII de 1 a 31...
      $XML = str_ireplace($asc31, '', $pXML);

//Verifica se a tag root para assinar existe...
      if(!stripos($XML,$TagId))
      {
        $this->erro = '<br>['.$_IdFun.'] XML a ser assinado, não possui a tag <'.$TagId.'> !!...';
        throw new Exception($this->erro);
      }

//Verifica se já não foi assinado...
      if(stripos($XML,'<Signature>'))
      {
        $this->erro = '<br>['.$_IdFun.'] XML já possui assinatura informado !!...';
        throw new Exception($this->erro);
      }

//prepara string XML para tratamento...
      $xmldoc = new DOMDocument('1.0', 'utf-8');
      $xmldoc->preserveWhiteSpace = false;
      $xmldoc->formatOutput = false;
      $xmldoc->loadXML($XML,LIBXML_NOBLANKS | LIBXML_NOEMPTYTAG);

//extrair a tag com os dados a serem assinados...
      $node = $xmldoc->getElementsByTagName($TagId)->item(0);
//pega o atributo id do node a ser assinado...
      $idSigned = trim($node->getAttribute("Id"));
//extrai os dados da tag para uma string na forma canonica...
      $dados = $node->C14N(false, false, null, null);
//Criar DigestValue para o node...
      $digValue = '';
//calcular o hash dos dados...
      $hashValue = hash('sha1', $dados, true);
//converter o hash para base64...
      $digValue = base64_encode($hashValue);

//montar a tag SignedInfo...
      $SignedInfo = '<SignedInfo>'
                     .'<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>'
                     .'<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>'
                     .'<Reference URI="#'.$idSigned.'">'
                       .'<Transforms>'
                         .'<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>'
                         .'<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>'
                       .'</Transforms>'
                       .'<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>'
                       .'<DigestValue>'.$digValue.'</DigestValue>'
                     .'</Reference>'
                   .'</SignedInfo>';

//Ler a chave privada com a senha do arquivo .pem ...
      $privKey = openssl_pkey_get_private(file_get_contents($this->PathFilePriKey));
      if(!$privKey)
      {
        $this->erro = '<br>['.$_IdFun.'] Houve erro no carregamento da chave privada !!... '.$this->PathFilePriKey;
        throw new Exception($this->erro);
      }

//Criar SignatureValue para o node <SignedInfo>...
      $Signature = '';
//Assinar com dados da chave privada...
      if (!openssl_sign($SignedInfo, $Signature, $privKey, OPENSSL_ALGO_SHA1))
      {
        $this->erro = '<br>['.$_IdFun.'] Erro durante a assinatura digital com chave privada !!...';
        throw new Exception($this->erro);
      }
//converte a assinatura em base64
      $SignatureValue = base64_encode($Signature);
//fechar a chave do certificado...
      openssl_free_key($privKey);

//montar a tag SignedInfo...
      $Signature = '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">'.$SignedInfo
                    .'<SignatureValue>'.$SignatureValue.'</SignatureValue>'
                    .'<KeyInfo>'
                      .'<X509Data>'
                        .'<X509Certificate>'.$this->getPublicKey().'</X509Certificate>'
                      .'</X509Data>'
                    .'</KeyInfo>'
                  .'</Signature>';

//agregar assinatira no marcador...
      $this->XMLAssinado = $Signature;

      return true;
    }
    catch(PDOException $e)
    {
      $this->erro = '<b>ERRO: </b> '.(stripos($e->getMessage(),$_IdFun) ? '' : '<br>['.$_IdFun.'] ').$e->getMessage();
      return false;
    }
  }

Eng Helder Ferreira.

unread,
Aug 21, 2018, 6:10:27 AM8/21/18
to nfe...@googlegroups.com
Olá 
Você assinou seu XML utilizando o nosso nfephp ?
Não, então como vamos conseguir comparar ?
Quando eu estava ajudando desenvolver as primeiras NFe com o nfephp, o Roberto me ajudou colocando a rotina de limpeza parecida com a acima.
Dá uma buscada no código fonte aberto do nfephp Speed-nfe lá deve estar certinho.
Abraços

--
--
Você recebeu esta mensagem porque está inscrito no Grupo "NFePHP".
Para Postar: nfe...@googlegroups.com
Para Sair do Grupo: nfephp+un...@googlegroups.com
Link: http://groups.google.com.br/group/nfephp?hl=pt-BR
-------
Repositórios: https://github.com/nfephp-org
---
Você recebeu essa mensagem porque está inscrito no grupo "NFePHP" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para nfephp+un...@googlegroups.com.
Para mais opções, acesse https://groups.google.com/d/optout.

Fábio Ananias

unread,
Oct 11, 2023, 10:56:50 AM10/11/23
to nfe...@googlegroups.com
Bom dia Pessoal,
tudo bem?

Estou reutilizando este tópico pois foi o mais próximo que encontrei quanto a problemas de assinatura.

Para transmissão do grupo R-4000 alguém passou por muitos problemas com o "id" ou "id"?
Estou travado nesse retorno:
MS0030
A estrutura do arquivo XML está em desconformidade com o esquema XSD. The 'Id' attribute is not declared. The required attribute 'id' is missing.


Será que com os dados abaixo alguém percebe algum erro que estou cometendo e não estou vendo?


No sped-efdreinf-master/src/Common/Factory.php já vi que vocês identificaram que a cada versão eles mudam de "id" para "Id", vice-versa, e a gente que se vire né!?..
Este é um trecho do init() do Factory.php
image.png

Já troquei de id para Id, vice-versa, e até mesmo com as duas formas, mas não tenho sucesso. 
(Após analisar os XSDs e os arquivos gerados diretamente no portal do reinf, achei mais provável que seja necessário usar tanto Id quanto id).

Estou fazendo testes no ambiente de testes (então me avise se o PAU estiver lá por favor)..

Meu xml (o qual mando um print também em anexo) está como mostro abaixo. Veja que até na assinatura já pus os IDs imaginando que o problema poderia estar lá.

image.png


Este é um evento lançado e baixado diretamente do portal do reinf, por isso pensei em adicionar o Id na assinatura:
image.png


Para "empacotar" eu interpretei o envioLoteEventosAssincrono-v1_00_00.xsd da seguinte forma:
 Só é necessário o "Id" em cada um dos "eventos":
image.png



Obrigado desde já!



1_transmitido.png
2_evento_do_portal.PNG
3_envioLoteEventosAssincrono-v1_00_00_interpretacao.png

Fábio Ananias

unread,
Oct 11, 2023, 11:05:46 AM10/11/23
to nfe...@googlegroups.com

Ah,
 e ainda tem o evt4020PagtoBeneficiarioPJ-v2_01_02.xsd...
image.png

Engraçado que passo nas validações locais tanto para a geração do evento, validando com o evt4020PagtoBeneficiarioPJ-v2_01_02.xsd
quanto para a transmissão, validando com o envioLoteEventosAssincrono-v1_00_00.xsd

🤔😣😥🤞✌

Fábio Ananias

unread,
Oct 12, 2023, 11:00:36 PM10/12/23
to nfe...@googlegroups.com
Oi pessoal,
Obrigado a todos que deram uma olhada no meu erro,
E me desculpem por um erro tão básico:
Meu XML está correto da forma como lhes enviei. A minha consulta do retorno é que estava errada. Acabei consultando várias vezes o primeiro protocolo que obtive (quando realmente faltava um Id, ou Id).

Obrigado a todos.
Reply all
Reply to author
Forward
0 new messages