Description
When creating a CSR with forge 1.3.1 that has a CN with special characters (Sišek
), parsing it from PEM messes up the String (Sišek
) even when valueTagClass: forge.asn1.Type.UTF8
is set.
Sišek
expressed as bytes is [83, 105, 197, 161, 101, 107]
, the problem here is, that each byte is individually interpreted as a UTF-8 codepoint instead of correctly interpreting [197, 161]
as a single codepoint.
Converting from Uint8Array to String correctly can be done with new TextDecoder("utf-8").decode(new Uint8Array([83, 105, 197, 161, 101, 107]))
.
Reading the generated PEM file with OpenSSL produces the correct result.
var keypair = await forge.pki.rsa.generateKeyPair({ bits: 512 });
var csr = forge.pki.createCertificationRequest();
csr.setSubject([{ name: "emailAddress", value: "[email protected]", valueTagClass: forge.asn1.Type.UTF8 }, { name: "commonName", value: "Sišek", valueTagClass: forge.asn1.Type.UTF8 }]);
csr.setAttributes([{ name: "extensionRequest", extensions: [{ name: "subjectAltName", altNames: [{ type: 1, value: "[email protected]" }] }] }]);
csr.publicKey = keypair.publicKey;
csr.sign(keypair.privateKey, forge.md.sha256.create());
console.log(csr.subject.attributes.find((attr) => attr.name == "commonName").value);
// outputs Sišek, as expected
var pem = forge.pki.certificationRequestToPem(csr);
var csrFromPem = forge.pki.certificationRequestFromPem(pem);
console.log(csrFromPem.subject.attributes.find((attr) => attr.name == "commonName").value);
// outputs SiÅ¡ek instead of the expected Sišek
Funnily enough, when using forge.asn1.prettyPrint(forge.pki.certificationRequestToAsn1(csrFromPem))
, the String value is displayed correctly (this is also true if the argument is csr
). This is achieved by running the value through forge.util.decodeUtf8(value)
before displaying it.