Blog do VG

Codificar é uma arte, mas nem todo mundo é um artista.

.NETLinuxProgramaçãoUtilidade Pública

Usando certificados no OpenIddict Core com Docker

Fala Devs, tudo sussa?

Recentemente estava avaliando o openiddict-core para passar a utilizar em novos projetos em .NET ao invés do meu amigo Keycloak, pois bem, li a documentação, criei um server de autenticação e autorização básico, gerei um pfx (costume de windows né) para assinatura do token, testei local, tudo funcionando, fui subir pra um ambiente de teste no docker e de cara já obtive um erro.

Unhandled exception. Interop+Crypto+OpenSslCryptographicException: error:10000080:BIO routines::no such file

   at Interop.Crypto.CheckValidOpenSslHandle(SafeHandle handle)

   at System.Security.Cryptography.X509Certificates.OpenSslX509CertificateReader.FromFile(String fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)

   at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(String fileName, String password, X509KeyStorageFlags keyStorageFlags)

A primeira coisa que eu pensei foi “Ah, é claro, devo ter esquecido de colocar pra copiar o pfx pra pasta dos binários”, mas olhei o fonte e estava certo, entrei no container pra ver se o arquivo estava lá e ele realmente estava, por algum motivo a porcaria do certificado não estava sendo encontrado, mas por que?

Depois de uns minutos de raiva e outros tantos de pesquisa (sim o Stackoverflow AINDA TEM SOLUÇÃO PRA MUITA COISA), descobri que o erro na verdade não tinha nada a ver com o certificado estar ou não presente no container. O problema era bem mais sutil (e sacana): o .pfx foi gerado no Windows, e o container que eu estava usando era Linux. Aí entra a treta.

O .NET no Windows usa a CAPI/CNG como backend criptográfico, que lida com .pfx tranquilamente. Já no Linux, o backend padrão é o OpenSSL, e ele é um pouco mais exigente. Em outras palavras: o OpenSSL não se comporta bem com certos .pfx criados no Windows. Mesmo que o arquivo esteja certo, mesmo que a senha esteja certa… ele simplesmente se recusa a abrir, jogando aquele erro zoado de “BIO routines::no such file”, que mais parece problema de caminho de arquivo, mas na real é o OpenSSL falando que deu merda em interpretar o conteúdo.

A solução? Trocar o .pfx por arquivos .pem.

Uma vez os .pem gerados, joguei eles na raiz da aplicação e mudei a chamada para testar.

De

var certificadoParaAssinatura = new X509Certificate2("token-signing-cert.pfx", "SenhaSuperSecreta123");

Para

var certificadoParaAssinatura = X509Certificate2.CreateFromPemFile("public-cert.pem", "private-key.pem");

E pronto, funcionou no Docker, no Windows, no Linux e até na geladeira se bobear.

O mais curioso é que o .pem funciona lindamente no Windows também, então acabei trocando de vez.

Se você estiver enfrentando esse tipo de problema com certificados em containers .NET, fica a dica: evite .pfx e prefira .pem, especialmente se o destino for Linux.

Só LEMBRANDO que para uma solução de produção, normalmente os certificados devem estar em um local seguro, afinal de contas eles servem para assinatura de token e seu vazamento poderia ter um potencial catastrófico para a sua aplicação, mas você é preocupado com segurança e não daria esse mole… NÃO É MESMO?

Referências:

https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509certificate2.createfrompemfile?view=net-9.0

 

Então é isso, até o próximo post que só Deus sabe quando vai sair.

vanderson

Analista/Desenvolvedor de Sistemas, Gamer, Blogger e um jogador de futebol praticamente profissional (no vídeogame).