DFe.NET
DFe.NET copied to clipboard
Exception "Keyset does not exist" ao gerar NFe
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
- 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 flagsX509KeyStorageFlags
, que desejam ser utilizadas, por fora da bilbioteca. - 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
.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
@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+
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.
Para min cria-se na configuração geral mesmo para mudar a gosto.
será feito na issue #1306