Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect encoding of subject.getField("ST") when CJK chars in value #1047

Open
WangYihang opened this issue Sep 12, 2023 · 1 comment
Open

Comments

@WangYihang
Copy link

WangYihang commented Sep 12, 2023

Description

I found that forge has an inconsistent behaviour between crypto when parsing a certificate, which has a chinese character in subject value.

The crypto library is able to return the correct value, but forge can not.

The proof of concept code shows as follows.

Proof of Concept

package.json

{
  "name": "cert",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "cert",
      "version": "1.0.0",
      "license": "ISC",
      "dependencies": {
        "node-forge": "^1.3.1"
      }
    },
    "node_modules/node-forge": {
      "version": "1.3.1",
      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
      "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
      "engines": {
        "node": ">= 6.13.0"
      }
    }
  }
}

index.js

const crypto = require("crypto")
const forge = require('node-forge')

const x509 = `-----BEGIN CERTIFICATE-----
MIIHSjCCBjKgAwIBAgIQB8YyshMp/Wi3t2Ddh9FfIDANBgkqhkiG9w0BAQsFADBQ
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSowKAYDVQQDEyFE
aWdpQ2VydCBTZWN1cmUgU2l0ZSBQcm8gQ04gQ0EgRzMwHhcNMjMwMTMwMDAwMDAw
WhcNMjQwMjI3MjM1OTU5WjBzMQswCQYDVQQGEwJDTjESMBAGA1UECAwJ5YyX5Lqs
5biCMTkwNwYDVQQKEzBCZWlKaW5nIEJhaWR1IE5ldGNvbSBTY2llbmNlIFRlY2hu
b2xvZ3kgQ28uLCBMdGQxFTATBgNVBAMTDHd3dy5iYWlkdS5jbjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAJ+u39TS3SsIvepHcwfv1nzSRV8jlSNR0zez
CKFcrOc7QMsmgj19cB2LkTf18zGt2T3UR1f0JzkgeHm5ASh8MTN2SAPINJ+ySbAk
F3dpKZXuhSk0qmeLDKyVhSk5bbgdAjMX483dpKKRASoMyEW/amGypsQX0g/Qh/7U
X42/IW3r80jjgCTzq65t0hG4DYeW4eMd7pdO9dHtxsQCY7k4DpeVaXQivU0XJH1E
DjVLdq1sb9/oXFett3uEuGQ9Mv97dXjCtNKmz5sI7cwaQmH5zoTw74ILjrhJyhvv
9iBO+BZhGKnJD+LJKuOabF5sWtEeFISjfpvC2MZa3xmkVRdfzd0CAwEAAaOCA/sw
ggP3MB8GA1UdIwQYMBaAFHuj+v/11QldHvkq/4VT7a9HqNd6MB0GA1UdDgQWBBSD
2D2Y53Lia3BXmOA4tZ7nD/f9eTCB9AYDVR0RBIHsMIHpggx3d3cuYmFpZHUuY26C
CGJhaWR1LmNuggliYWlkdS5jb22CDGJhaWR1LmNvbS5jboILdy5iYWlkdS5jb22C
DHd3LmJhaWR1LmNvbYIQd3d3LmJhaWR1LmNvbS5jboIQd3d3LmJhaWR1LmNvbS5o
a4IMd3d3LmJhaWR1LmhrghB3d3cuYmFpZHUubmV0LmF1ghB3d3cuYmFpZHUubmV0
LnBoghB3d3cuYmFpZHUubmV0LnR3ghB3d3cuYmFpZHUubmV0LnZugg53d3d3LmJh
aWR1LmNvbYIRd3d3dy5iYWlkdS5jb20uY24wDgYDVR0PAQH/BAQDAgWgMB0GA1Ud
JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBHBgNVHR8EQDA+MDygOqA4hjZodHRw
Oi8vY3JsLmRpZ2ljZXJ0LmNuL0RpZ2lDZXJ0U2VjdXJlU2l0ZVByb0NOQ0FHMy5j
cmwwPgYDVR0gBDcwNTAzBgZngQwBAgIwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3
dy5kaWdpY2VydC5jb20vQ1BTMHsGCCsGAQUFBwEBBG8wbTAjBggrBgEFBQcwAYYX
aHR0cDovL29jc3AuZGlnaWNlcnQuY24wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNl
cnRzLmRpZ2ljZXJ0LmNuL0RpZ2lDZXJ0U2VjdXJlU2l0ZVByb0NOQ0FHMy5jcnQw
CQYDVR0TBAIwADCCAXwGCisGAQQB1nkCBAIEggFsBIIBaAFmAHYAdv+IPwq2+5VR
wmHM9Ye6NLSkzbsp3GhCCp/mZ0xaOnQAAAGGAEmsJwAABAMARzBFAiEA44GD/7FJ
BmyUTlrl7jfe6zOjRwd5ausfmffOfktdHrMCIG/X4jgmLdyAbLYR5gE2eAZePC0z
AF9XebbT2ovpzfYnAHUASLDja9qmRzQP5WoC+p0w6xxSActW3SyB2bu/qznYhHMA
AAGGAEmsDQAABAMARjBEAiAjDPkcIqKXgdGOmhvFiFFkGLg1R+CtwUmOZICC7YrC
pgIgCRc6lnKtZoa/sNhu5dJvR9F5LftB+ypVuJcHUrtzo94AdQA7U3d1Pi25gE6L
MFsG/kA7Z9hPw/THvQANLXJv4frUFwAAAYYASawDAAAEAwBGMEQCIBPl+lsd9Zi6
onLpqqXRxXokLmiKpCCm0sflo0dRglezAiAiMi8XsYUqlms94xuPWwu3zpq89Iq3
ZJdn0LLck7PKDTANBgkqhkiG9w0BAQsFAAOCAQEAIQaeaXINZBnioZo4+lTNI+NB
ru5I0lEWevV4pae28jFNRARNO34Lad0t58svnL6QfwWBYuj3JNPMh93TuAWN8qeg
3NLk6QUS6xlx78Tw3SSJGrtBIhztFWanKWdgUIikaUF4QgwJ+zI093vsZle4EfK0
WZVJu4oS2E9G+5rlVtp9RoVIcj0H2B+UFwCsm28chElCuBcFZztSWY/+lkUOfKI+
JQPQ4IXV57jhaEI8LA0ZsfLdzbkcmN+2yFDwaXQcCoR63t1AnUs75bL6rY/Roq8s
zpMevdWiKj8+Ev5tMGLWTeX+8+sn/8XHUSTO/ezhTxvICaOF2kilUnGRFFUWzA==
-----END CERTIFICATE-----`

const forge_cert = forge.pki.certificateFromPem(x509)
console.log(forge_cert.subject.getField("ST"))

const crypto_cert = new crypto.X509Certificate(x509)
console.log(crypto_cert.subject)

Current output

'å\x8C\x97京å¸\x82' should be 北京市

{
  type: '2.5.4.8',
  value: 'å\x8C\x97京å¸\x82',
  valueTagClass: 12,
  name: 'stateOrProvinceName',
  shortName: 'ST'
}
C=CN
ST=北京市
O=BeiJing Baidu Netcom Science Technology Co.\, Ltd
CN=www.baidu.cn

Expected output

{
  type: '2.5.4.8',
  value: '北京市',
  valueTagClass: 12,
  name: 'stateOrProvinceName',
  shortName: 'ST'
}
C=CN
ST=北京市
O=BeiJing Baidu Netcom Science Technology Co.\, Ltd
CN=www.baidu.cn

Environment

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 23.04
Release:	23.04
Codename:	lunar

$ node --version                             
v16.18.1

$ npm --version 
9.6.5
@mrprokes
Copy link

I had the same problem trying to make PKCS#7 encryption.

My solution was after loading the certificate loop through issuer fields, read it as ASCII and write it back as UTF-8 like that:
certificate.issuer.attributes.forEach(element => { element.value = Buffer.from(Buffer.from(element.value, 'ASCII')).toString('utf-8'); });

The problem with certificateFromPem() function is that it uses the obsolete method of reading base64 see:
var msg = { type: type, procType: null, contentDomain: null, dekInfo: null, headers: [], body: forge.util.decode64(match[3]) };

It is only a hotfix but I hope it will help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants