Olá Wallison,
Pelo visto o erro está na assinatura.
Use esse código:
function assinaXML($docxml, $tagid){
$URLdsig='http://www.w3.org/2000/09/xmldsig#';
$URLCanonMeth='http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
$URLSigMeth='http://www.w3.org/2000/09/xmldsig#rsa-sha1';
$URLTransfMeth_1='http://www.w3.org/2000/09/xmldsig#enveloped-signature';
$URLTransfMeth_2='http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
$URLDigestMeth='http://www.w3.org/2000/09/xmldsig#sha1';
try {
//Certificado
$crt_dir = getcwd().DIRECTORY_SEPARATOR.'cert'.DIRECTORY_SEPARATOR;
$priKEY = "{$crt_dir}pkey.pem";
$keypass = file_get_contents("{$crt_dir}pass.txt");
$pubKEY = "{$crt_dir}cert.pem";
$xml = $docxml;
// obter o chave privada para a ssinatura
$prikeyid = openssl_pkey_get_private(file_get_contents($priKEY), $keypass);
// limpeza do xml com a retirada dos CR, LF e TAB
$order = array("\r\n", "\n", "\r", "\t");
$replace = '';
$xml = str_replace($order, $replace, $xml);
// Habilita a manipulação de erros da libxml
libxml_use_internal_errors(true);
//limpar erros anteriores que possam estar em memória
libxml_clear_errors();
// carrega o documento no DOM
$xmldoc = new DOMDocument('1.0', 'utf-8');
$xmldoc->preservWhiteSpace = true; //elimina espaços em branco
$xmldoc->formatOutput = false;
// muito importante deixar ativadas as opções para limpar os espacos em branco
// e as tags vazias
if ($xmldoc->loadXML($xml, LIBXML_NOBLANKS | LIBXML_NOEMPTYTAG)) {
$root = $xmldoc->documentElement;
} else {
$msg = "Erro ao carregar XML, provavel erro na passagem do parametro docxml ou no proprio xml!!";
$errors = libxml_get_errors();
if (!empty($errors)) {
$i = 1;
foreach ($errors as $error) {
$msg .= "\n [$i]-" . trim($error->message);
}
libxml_clear_errors();
}
throw new Exception($msg);
}
//extrair a tag com os dados a serem assinados
$node = $xmldoc->getElementsByTagName($tagid)->item(0);
if (!isset($node)) {
$msg = "A tag < $tagid > não existe no XML!!";
throw new Exception($msg);
}
$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($URLdsig, 'Signature');
//adiciona a assinatura
$node->parentNode->appendChild($Signature);
$SignedInfo = $xmldoc->createElement('SignedInfo');
$Signature->appendChild($SignedInfo);
//Cannocalization
$newNode = $xmldoc->createElement('CanonicalizationMethod');
$SignedInfo->appendChild($newNode);
$newNode->setAttribute('Algorithm', $URLCanonMeth);
//SignatureMethod
$newNode = $xmldoc->createElement('SignatureMethod');
$SignedInfo->appendChild($newNode);
$newNode->setAttribute('Algorithm', $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', $URLTransfMeth_1);
//Transform
$newNode = $xmldoc->createElement('Transform');
$Transforms->appendChild($newNode);
$newNode->setAttribute('Algorithm', $URLTransfMeth_2);
//DigestMethod
$newNode = $xmldoc->createElement('DigestMethod');
$Reference->appendChild($newNode);
$newNode->setAttribute('Algorithm', $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, $prikeyid);
//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 = str_replace("\r", '', file_get_contents($pubKEY));
$cert = str_replace("\n", '', $cert);
$cert = str_replace('-----BEGIN CERTIFICATE-----', '', $cert);
$cert = wordwrap(trim(str_replace('-----END CERTIFICATE-----', '', $cert)), 64, "\n", true);
//X509Certificate
$newNode = $xmldoc->createElement('X509Certificate', $cert);
$X509Data->appendChild($newNode);
//grava na string o objeto DOM
$xml = $xmldoc->saveXML($xmldoc->documentElement);
// libera a memoria
openssl_free_key($prikeyid);
} catch (Exception $e) {
throw $e;
}
//retorna o documento assinado
return $xml;
} //fim signXML
Se for implementação da Fiorilli.
Aguarde que estou gerando um GIST para ela.