ZeusAutomacao / DFe.NET

Biblioteca para Geração de NFe(2.0, 3.10 e 4.0) e NFCe(3.10 e 4.0) e consumo dos serviços necessários à sua manutenção, conforme descritos em http://www.nfe.fazenda.gov.br/portal/principal.aspx
GNU Lesser General Public License v2.1
754 stars 477 forks source link

Certificado A3 Unable to cast object of type RSACng to type RSACryptoServiceProvider #1133

Closed evertonbatini closed 4 years ago

evertonbatini commented 4 years ago

No ASP.NET Core, ao tentar utilizar um certificado A3 recebo esse erro:

Unable to cast object of type 'System.Security.Cryptography.RSACng' to type 'System.Security.Cryptography.RSACryptoServiceProvider'.

No método DefinirPinParaChavePrivada tem um cast da certificado.PrivateKey para RSACryptoServiceProvider

Porém, a certificado.PrivateKey neste momento é do tipo RSACng.

No NFe.AppTeste funciona, e no NFe.AppTeste.NetCore da esse erro

Caminho completo do erro...

at DFe.Utils.Assinatura.CertificadoDigital.DefinirPinParaChavePrivada(X509Certificate2 certificado, String pin) at DFe.Utils.Assinatura.CertificadoDigital.ObterDoRepositorioPassandoPin(String serial, String senha) at DFe.Utils.Assinatura.CertificadoDigital.ObterCertificado(ConfiguracaoCertificado configuracaoCertificado) at NFe.Servicos.ServicosNFe..ctor(ConfiguracaoServico cFgServico, X509Certificate2 certificado)

marcosgerene commented 4 years ago

No NFe.AppTeste funciona, e no NFe.AppTeste.NetCore da esse erro ... at DFe.Utils.Assinatura.CertificadoDigital.DefinirPinParaChavePrivada(X509Certificate2 certificado, String pin)

Acredito que o @danilobreda possa te responder melhor, mas até aonde eu conheço não é possível definir chave para o Pin (quando A3) em .Net Core, deve-se sempre solicitar a chave ao usuário.

Por favor teste o evento que você está usando (envio, consulta, etc) sem passar implicitamente a o PIN, mas fazendo com que o usuário informe o mesmo.

evertonbatini commented 4 years ago

Realmente, sem passar a senha funciona

Precisei também aumentar o time out, aparentemente é considerado o tempo em que o usuário está digitando o pin nesse time out, aumentando já resolveu.

marcosgerene commented 4 years ago

@evertonbatini

Realmente, sem passar a senha funciona

Precisei também aumentar o time out, aparentemente é considerado o tempo em que o usuário está digitando o pin nesse time out, aumentando já resolveu.

O timeout até aonde eu sei leva em consideração somente a requisição ao webservice, eu uso 30 segundos aqui (30000) como padrão, em alguns poucos clienstes aumento para 60 (em caso de internet instável).

Mas se resolveu, melhor, vou esperar se o @danilobreda ou o @robertorp tem alguma outra sugestão, se ninguém falar nada até o fim do dia fecho a issue.

Abraços

danilobreda commented 4 years ago

Hoje o código tem suporte apenas para A1, passando os bytes da chave e a senha. Até o momento não houve testes de chave A3 para o dotnet Core, até porque na época que fizemos (.net core 2.0) o windowsforms etc não era suportado e existiam alguns bugs nessa questão. Hoje com dotnet 3.1 já tem como ter um suporte para A3 e até mesmo referenciar alguns elementos que antigamente não existiam para que tenha o suporte necessário. Preciso verificar o código e implementar esses novos processos, porem, infelizmente hoje não tenho A3 para efetuar testes. Não entendi muito bem como você está utilizando ASP NET Core com A3, o "pen drive" está conectado no servidor? Não conheço muito bem como funciona o A3 mas é assim não é? rsrs

evertonbatini commented 4 years ago

No meu teste o certificado está na minha máquina, que é o servidor (de desenvolvimento). (Angular e ASP.NET Core)

Não fiz o teste em produção ainda (Amazon Linux CentOS)

A ideia seria o certificado ficar na máquina do cliente, algo parecido com o Portal e-CAC (da pra selecionar o certificado que está no cliente e ele é enviado ao servidor de alguma maneira)

Eu tenho o A3 aqui, mas não tenho ideia de como implementar kk

guidi commented 4 years ago

@evertonbatini essa idéia do certificado ficar na máquina do cliente não vai dar muito certo não... a não ser que você adote algo como um "programa assinador" ou crie um plugin pro navegador pra interagir com a sua aplicação.

danilobreda commented 4 years ago

@evertonbatini infelizmente A3 não da certo de forma web, hoje tenho esse problema no meu sistema que é 100% web (aspnet core + vuejs). Hoje utilizo apenas A1 que fica com o certificado em bytes e a senha gravada no meu banco de dados. Existem alguns links sobre esse problema do A3... a única solução hoje é como o @guidi descreveu, fazer um serviço que fica executando na maquina do cliente que esta o A3 conectado e efetuar o processo de assinar na maquina do cara com esse programa. Aqui vai alguns links desse problema enfrentado por todos :/ https://www.projetoacbr.com.br/forum/topic/33264-certificado-a3-web/ https://www.javac.com.br/jc/posts/list/3830-certificado-a3-e-web-resolvido.page https://www.guj.com.br/t/gerar-nfe-com-certificado-a3-pelo-servidor-web/134390 https://pt.stackoverflow.com/questions/80568/certificado-digital-com-php https://pt.stackoverflow.com/questions/149950/certificado-a3-no-asp-net-mvc-e-iis

Se descobrir uma maneira de fazer compartilha com a gente! :D Hoje a ideia que tenho é criar essa aplicação/servico que fica rodando no cliente, e assim eu consigo assinar no cliente mesmo meu xml e retornar pro servidor. Ai você pode usar signalr, rabbitmq, ou http mesmo... porem tem que ser algo rápido de servidor para cliente.

robertorp commented 4 years ago

Infelizmente certificado A3 é chumbado na pendriver/cartão. Não tem como você utilizar um certificado A3 com WEB.

Unica maneira é criando um aplicativo local na maquina do cliente que irá assinar os documentos como o amigo @guidi falou, eu iria até mais longe, deixaria o aplicativo local assinando é enviando para a sefaz no cliente somente depois de autorizado/erro/rejeição (alguma possível resposta) que iria mandar pra web novamente, bom que economizaria até consumo de banda no servidor hehe

evertonbatini commented 4 years ago

Entendi

Pelo que encontrei aqui pesquisando, no caso do portal e-CAC, quando clico pra autenticar via certificado, e abre um prompt do navegador para selecionar (mostrando a lista dos certificados instalados na minha máquina).

O que acontece é que quando o navegador tenta acessar uma url específica, o servidor solicita um certificado de cliente, e o navegador entende isso e abre o prompt.

O e-CAC só da um submit no form que acessa essa url "/autenticacao/Login/Certificado" (get)

É algo que faça com que o servidor solicite um certificado de cliente, vou tentar encontrar isso.

Só que mesmo eu conseguindo fazer isso, não sei até que ponto esse certificado ficará disponível no servidor, para assinar os XML por exemplo, ou se funciona apenas para autenticação como é utilizado no e-CAC.

guidi commented 4 years ago

@evertonbatini o certificado que você vai obter nessa requisição não vai servir para assinar um arquivo digital, para assinar você precisa da chave privada, que no caso do certificado A3 fica gravada no token ou cartão, não é possível exportar essa chave privada, já passei por essa necessidade a alguns anos atrás, a solução que acabei adotando foi a do aplicativo assinador, que já mencionei na issue, de qualquer forma, se você achar uma solução melhor, compartilha aqui com a gente.

evertonbatini commented 4 years ago

Entendi, imaginei isso mesmo, que o e-CAC só tem acesso aos dados do certificado (cnpj), e sabe que é um certificado válido, então permite o acesso.

Minha esperança era de que se os dados do certificado chegam no servidor, como o cnpj por exemplo, poderia ter alguma forma de utilizá-lo la também, mas como você falou, aparentemente o servidor deles só recebe informações básicas do certificado e não a chave privada, o que faz mais sentido mesmo pela própria segurança do A3.

marcosgerene commented 4 years ago

@evertonbatini

O A3 não pode ser usado para web, a não ser de forma como o @guidi mencionou (com um app assinador rodando de forma local no client).

A issue se tratava de um erro pontual (estava passando senha para o A3, o que não é permitido para .Net Core).

Acredito que se vamos estender a discussão ou mudar o foco seria legal outra issue, porque pode servir de base de pesquisa no futuro.

Vou fechar a issue, se tiver mais dúvidas referente a este tema pode reabrir, ou abra uma nova issue para outra dúvida qualquer.

Abraços