Business-BR-NFSe

 view release on metacpan or  search on metacpan

lib/Business/BR/NFSe.pm  view on Meta::CPAN

    # --- 4. Digest do infDPS ---
    # O elemento sendo assinado herda o namespace do pai no documento final,
    # então adicionamos o xmlns explicitamente antes do hash.
    (my $inf_dps_for_hash = $inf_dps) =~ s/<infDPS/<infDPS xmlns="$NS"/;
    my $digest_b64 = encode_base64(sha256(encode('UTF-8', $inf_dps_for_hash)), '');

    # --- 5. SignedInfo ---
    # Precisa fechar tags explicitamente (nada de auto-fechar) porque o servidor verifica
    # as tags contra o formulário canônico exc-c14n#WithComments, que expande <Bla/> em <Bla></Bla>.
    my $signed_info = join '',
        q(<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">),
        q(<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments"></CanonicalizationMethod>),
        q(<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>),
        qq(<Reference URI="#$id_dps">),
          q(<Transforms>),
            q(<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform>),
            q(<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments"></Transform>),
          q(</Transforms>),
          q(<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>),
          qq(<DigestValue>$digest_b64</DigestValue>),
        q(</Reference>),
        q(</SignedInfo>);

    # --- 6. Assinatura RSA-SHA256 sobre os bytes SignedInfo ---
    my $rsa     = Crypt::PK::RSA->new(\$self->{key_pem});
    my $sig_b64 = encode_base64($rsa->sign_message(encode('UTF-8', $signed_info), 'SHA256', 'v1.5'), '');

    # --- 7. Monta o XML final ---
    my $xml = join '',
        q(<?xml version="1.0" encoding="UTF-8"?>),
        qq(<DPS xmlns="$NS" versao="$VERSAO">),
          $inf_dps,
          q(<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">),
            $signed_info,
            qq(<SignatureValue>$sig_b64</SignatureValue>),
            qq(<KeyInfo><X509Data><X509Certificate>$self->{cert_b64}</X509Certificate></X509Data></KeyInfo>),
          q(</Signature>),
        q(</DPS>);

    # --- 8. GZip + base64 ---
    my $xml_bytes = encode('UTF-8', $xml);
    my $gzipped;
    gzip(\$xml_bytes, \$gzipped) or croak "gzip failed: $GzipError";



( run in 2.906 seconds using v1.01-cache-2.11-cpan-6de40a662fe )