I need to save a certificate in both PEM and DER encoding.
PEM is not an issue:
const cert = forge.pki.createCertificate();
// (...)
// (...)
// cert.sign(...);
const pemCert = forge.pki.certificateToPem(cert);
fs.writeFileSync('cert.pem', pemCert, {encoding: 'utf-8'});
// ^ GOOD
DER on the other hand, I cannot figure out how to save the proper certificate to file.
I would expect the following JS code to match the output of
openssl x509 -outform der -in ./cert.pem -out ./cert_good.cer
,
however that is not the case and I get something different, apparently "malformed":
const derCert = forge.pki.pemToDer(pemCert).getBytes();
fs.writeFileSync('cert_bad.cer', derCert, {encoding: 'utf-8'});
When I say "malformed" I refer to the fact that
openssl x509 -inform der -in cert_bad.cer -text -noout
returns:
Could not find certificate from cert_bad.cer
What am I doing wrong?
ty
EDIT
I figured another way around this, using Node.js Crypto moudule -> class X509Certificate -> property raw.
Yet the question about node-forge remains. Anyway:
import { X509Certificate } from 'crypto'
const cert = forge.pki.createCertificate();
// (...)
// (...)
// cert.sign(...);
const pemCert = forge.pki.certificateToPem(cert);
fs.writeFileSync('cert.pem', pemCert, {encoding: 'utf-8'});
// ^ GOOD
const x509 = new X509Certificate(pemCert);
const derCert = x509.raw;
fs.writeFileSync('cert_good.cer', derCert, {encoding: 'utf-8'});
// ^ NOW ALSO GOOD
DER data is inherently binary (bytes or technically octets, not characters) but node-forge
uses a ByteBuffer
class that stores it in a JS string
which is designed for characters. Treating the DER bytes as characters encodable in UTF-8 produces garbage. You need to write this string
using encoding binary
or latin1
(aliases) in fs.writeFile*
to get the correct bytes. (I consider binary
clearer in this situation but the nodejs people consider it legacy and don't prefer it.)
OTOH builtin crypto
uses (also builtin) Buffer
and fs.writeFile*
when given a Buffer
ignores the encoding because it knows the Buffer
is already bytes and not characters.