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.
1 2 3 4 5 6 7 |
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
1 |
var certificadoParaAssinatura = new X509Certificate2("token-signing-cert.pfx", "SenhaSuperSecreta123"); |
Para
1 |
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.