Resolvendo o erro Unsupported PKCS12 PFX data
História e solução sobre o problema ocorrido no Node.js
Essa semana resolvi um problema no Node.js, onde ao utilizar um certificado .pfx com o Axios ocorria o erro “Unsupported PKCS12 PFX data”, o código era o seguinte:
const axiosClient = axios.create({
httpsAgent: new https.Agent({
pfx: readFileSync(certificatePath),
passphrase: certificatePassword
})
})
const response = await axiosClient.get(URL);
e o erro era esse:
Error: Unsupported PKCS12 PFX data
at configSecureContext (node:internal/tls/secure-context:290:15)
at Object.createSecureContext (node:_tls_common:114:3)
at Object.connect (node:_tls_wrap:1764:48)
at Agent.createConnection (node:https:173:22)
at Agent.createSocket (node:_http_agent:330:26)
at Agent.addRequest (node:_http_agent:278:10)
at new ClientRequest (node:_http_client:340:16)
at Object.request (node:https:381:10)
at RedirectableRequest._performRequest (/home/alisson/.../node_modules/follow-redirects/index.js:337:24)
at new RedirectableRequest (/home/alisson/.../node_modules/follow-redirects/index.js:111:8)
at Axios.request (/home/alisson/.../node_modules/axios/lib/core/Axios.js:45:41)
at async <anonymous> (/home/alisson/.../index.ts:13:20) {
code: 'ERR_CRYPTO_UNSUPPORTED_OPERATION'
}
Quando fui procurar na internet e nas IAs da vida, normalmente não se acha muito contexto sobre o erro, somente umas dicas para usar a flag NODE_OPTIONS=--openssl-legacy-provider
antes de iniciar o serviço e o código volta a funcionar “mágicamente”.
Mas isso é gambiarra!
Inicialmente eu usei essa flag e o código continuou a funcionar, e simplesmente aceitei. Mas esse erro chegou para mim de novo em outro serviço e resolvi ir mais a fundo para entender.
Contexto do erro:
Como eu já tinha utilizado aquela flag para fazer funcionar o serviço, tinha uma ideia que fosse algo a ver com o OpenSSL. E pesquisando mais, acabei encontrando essa issue no repositório do Node.js:
https://github.com/nodejs/node/issues/40672
- Mas o que causa isso?
O erro era realmente no OpenSSL, e isso acontece porque a partir do Node.js 17 foi adotado o OpenSSL 3.0 para substituir o OpenSSL 1.1.1 utilizado anteriormente.
Assim, os certificados com uma criptografia que o OpenSSL classifica como fraca ocasionam um erro no OpenSSL que repassa o erro para o Node.
E aqui você pode ver as mudanças que o OpenSSL 3 fez: https://openssl-library.org/news/openssl-3.0-notes/
Solução:
Para resolver a criptografia fraca dos certificados, eu utilizei esses dois comandos:
execFileSync("openssl", [
"pkcs12",
"-in",
weakCertificatePath,
"-nodes",
"-legacy",
"-out",
decryptedPfxPath,
"-passin",
`pass:${certificatePassword}`,
]);
execFileSync("openssl", [
"pkcs12",
"-in",
decryptedPfxPath,
"-export",
"-out",
upgradedPfxPath,
"-passout",
`pass:${certificatePassword}`,
]);
O primeiro descriptografa o arquivo e gera na saída o certificado e a sua chave privada;
Já o segundo criptografa novamente, só que como está utilizando o OpenSSL 3, ele automaticamente irá utilizar uma cifra mais segura. E então o .pfx está atualizado e pode ser utilizado agora sem erros!