DFe.NET icon indicating copy to clipboard operation
DFe.NET copied to clipboard

Exception "Keyset does not exist" ao gerar NFe

Open matheusmig opened this issue 3 years ago • 4 comments

Ambiente da minha aplicação

Rodando em um App Service na Azure Projeto .Net Core 2.1 Possuo os certificados armazenados no Azure Key Vault, e carrego-os de lá conforme é necessário emitir uma Nfe.

Problema

Exceção intermitente Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Keyset does not exist ao tentar emitir uma NFe rodando em um projeto .Net Core no ambiente App Service da Azure.

A stack trace completa da Exception é a seguinte:

2021-07-15 13:42:15.075 +00:00 [Error] 
Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Keyset does not exist
   at Internal.NativeCrypto.CapiHelper.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
   at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeProvHandle()
   at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeKeyHandle()
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 keySize, CspParameters parameters, Boolean useDefaultKeySize)
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameters)
   at Internal.Cryptography.Pal.CertificatePal.<>c.<GetRSAPrivateKey>b__61_0(CspParameters csp)
   at Internal.Cryptography.Pal.CertificatePal.GetPrivateKey[T](Func`2 createCsp, Func`2 createCng)
   at Internal.Cryptography.Pal.CertificatePal.GetRSAPrivateKey()
   at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
   at NFe.Utils.Assinatura.Assinador.ObterAssinatura[T](T objeto, String id, X509Certificate2 certificadoDigital, Boolean manterDadosEmCache, String signatureMethod, String digestMethod, Boolean cfgServicoRemoverAcentos)
   at NFe.Utils.Assinatura.Assinador.ObterAssinatura[T](T objeto, String id, ConfiguracaoServico configuracaoServico)
   at NFe.Utils.NFe.ExtNFe.Assina(NFe nfe, ConfiguracaoServico cfgServico, X509Certificate2 _certificado)

Possível causa do problema

Após buscar referências na Web sobre este problema, chegamos a conclusão que é relacionado ao App Service da Azure e como ele se relaciona com o Sistema Operacional para gerenciar as keysets dos certificados. A opção X509KeyStorageFlags.MachineKeySet não 'conversa' bem com o App Service. Parece não haver uma solução definitiva pelo lado da Azure para o App Service.

Segue uma lista de relatos similares: Relato github dotnet outro relato outro relato 2 outro relato 3

Possível Solução

Apesar da Exception acontecer na Função OberAssinatura[T], acreditamos que o real causador do erro está na função que obtém o Certificado através do arquivo ou array de bytes., que seria a função private static X509Certificate2 ObterDoArrayBytes(byte[] arrayBytes, string senha) chamada internamente em X509Certificate2 ObterCertificado(ConfiguracaoCertificado configuracaoCertificado), essa função está com a opção X509KeyStorageFlags.MachineKeySet hardcoded.

Enfrentamos este mesmo problema em um código interno da nossa Aplicação, e conseguimos solucioná-lo alterando a configuração de carregamento do X509Certificate2 pra X509KeyStorageFlags.EphemeralKeySet

Sugestões de alterações para solucionar o problema

Será necessário 2 passos para atingir a solução

  1. Parametrizar a função private static X509Certificate2 ObterDoArrayBytes(byte[] arrayBytes, string senha), e também a fila de funções que invocam ela, para ser possível configurar as flags X509KeyStorageFlags, que desejam ser utilizadas, por fora da bilbioteca.
  2. O suporte para a flag X509KeyStorageFlags.EphemeralKeySet foi introduziada a partir do .Net Framework 4.7.2 e .Net Standard 2.1 , assim, será necessário atualizar a versão da biblioteca.

edit: corrigida formatação do texto

matheusmig avatar Jul 16 '21 14:07 matheusmig

.NET Core 2.1 tem end of life dia 21 de agosto, atualiza o bichinho! Vou verificar o que fazer nessa questão... tivemos o mesmo problema na issue #1238 , acho que está na hora de colocarmos o 509KeyStorageFlags como uma configuração! @marcosgerene @robertorp

danilobreda avatar Jul 16 '21 15:07 danilobreda

@matheusmig precisa do X509KeyStorageFlags.EphemeralKeySet ? Não queria atualizar para o .net standard 2.1 ... O seu .net core 2.1 por exemplo não teria suporte, apenas 3+

danilobreda avatar Jul 16 '21 15:07 danilobreda

De fato, estamos com a atualização do projeto planejada, estamos correndo atrás disso hehe. Como uma primeira mudança, a adição da opção de poder selecionar quais X509KeyStorageFlags serão utilizadas já é de grande benefício, inclusive para toda comunidade. Segundamente, se fosse possível adicionar suporte ao X509KeyStorageFlags.EphemeralKeySet seria uma baita mão para mim, porém, tenho receio que essa atualização para o .Net Standard 2.1 acarrete em muitas mudanças e acabe afetando negativamente muitos outros usuários.

matheusmig avatar Jul 16 '21 19:07 matheusmig

Para min cria-se na configuração geral mesmo para mudar a gosto.

robertorp avatar Sep 01 '21 17:09 robertorp

será feito na issue #1306

danilobreda avatar Mar 24 '23 00:03 danilobreda