PeculiarVentures / PKI.js

PKI.js is a pure JavaScript library implementing the formats that are used in PKI applications (signing, encryption, certificate requests, OCSP and TSP requests/responses). It is built on WebCrypto (Web Cryptography API) and requires no plug-ins.
http://pkijs.org
Other
1.25k stars 204 forks source link

CertificateChainValidationEngine.verify always retrieves false (resultCode: -1) #284

Closed filipap closed 3 years ago

filipap commented 3 years ago

Good morning, i'm using pkijs on my ionic cli v5 app. When I use the CertificateChainValidationEngine to verify the certificate chain, it always gives me that error:

result: false
resultCode: -1
resultMessage: "No valid certificate paths found"

After some researching i found that issue, https://github.com/PeculiarVentures/PKI.js/issues/259, and I imported the lib @peculiar/webcrypto. However it still fails. Any suggestion? (PS. Ionic apps runs over nodejs)

YuryStrozhevsky commented 3 years ago

It is impossible to say anything without a full certificate chain (end-user certificates + all certificates of CAs). Also would be better to have your code which is working wirh PKIjs validation engine. BTW have you seen this and this?

filipap commented 3 years ago

@YuryStrozhevsky Root CA (self-signed certificate):

-----BEGIN CERTIFICATE-----
MIICmDCCAh+gAwIBAgIUeEALKbTjI01jFQyx562XlfncCqIwCgYIKoZIzj0EAwMw
RjELMAkGA1UEBhMCUFQxFzAVBgNVBAoMDk1vYmlsZUlEX0lBX1BUMR4wHAYDVQQD
DBV2aGFzbGFiMDMuaW5lc2N0ZWMucHQwHhcNMjAwODI3MTUxMjEwWhcNMzUwODI0
MTUxMjEwWjBGMQswCQYDVQQGEwJQVDEXMBUGA1UECgwOTW9iaWxlSURfSUFfUFQx
HjAcBgNVBAMMFXZoYXNsYWIwMy5pbmVzY3RlYy5wdDB2MBAGByqGSM49AgEGBSuB
BAAiA2IABECZ/1vZmOV0Lhj9F20uotPrshdU3eVTxPh6//GwxmuN0TT/hAyAs405
6O4HrezS2UzZxJEXpmmho4gj6tyMGAkZKQ2xIvLp6WoT6BwrwsFThMqJxrCNIfn5
6iNwF4lC7aOBzTCByjAdBgNVHQ4EFgQUFrmTNbAk6pHHzO4a+BBgV1qJmPAwCwYD
VR0PBAQDAgEGMD0GA1UdEgQ2MDSBE2NvbnRhY3RAbW9iaWxlaWQucHSGHWh0dHBz
Oi8vdmhhc2xhYjAzLmluZXNjdGVjLnB0MBIGA1UdEwEB/wQIMAYBAf8CAQAwSQYD
VR0fBEIwQDA+oDygOoY4aHR0cHM6Ly92aGFzbGFiMDUuaW5lc2N0ZWMucHQvdjIv
Y3Jscy9Nb2JpbGVJRF9JQV9QVC5kZXIwCgYIKoZIzj0EAwMDZwAwZAIwKZunNfR4
W2ydP3RmXG0as1cJqDx/wl5TRrS1lOnbrjwK4jhp5aJdp33j4bEKMZGKAjBPheaY
NaA5ekK3KIJIlRa9gNY7QPjWvMKSLT/m0XRzESNUW79NHuIs/rYHiMWAzgA=
-----END CERTIFICATE-----

Digital Signature certificate:

-----BEGIN CERTIFICATE-----
MIICyjCCAlGgAwIBAgIUfbcIFNPXrw0k0DSC8P9Ft+b7E/MwCgYIKoZIzj0EAwMw
RjELMAkGA1UEBhMCUFQxFzAVBgNVBAoMDk1vYmlsZUlEX0lBX1BUMR4wHAYDVQQD
DBV2aGFzbGFiMDMuaW5lc2N0ZWMucHQwHhcNMjAwODMxMTcxMDI2WhcNMjEwODMx
MTcxMDI2WjBGMQswCQYDVQQGEwJQVDEXMBUGA1UECgwOTW9iaWxlSURfSUFfUFQx
HjAcBgNVBAMMFXZoYXNsYWIwMy5pbmVzY3RlYy5wdDB2MBAGByqGSM49AgEGBSuB
BAAiA2IABDgVl7XS24j/mhLuefw+DoKcDh0Af0IS8cS5KAz4tk2RyCH5QuUPuX0c
J5AUjCTYCMxaXmJb973vigTzv/6gVLvDD1Hp+z0qR+vrwYEUb4Idr9eLMrVEdI9J
PL3rZQjNHaOB/zCB/DAfBgNVHSMEGDAWgBQWuZM1sCTqkcfM7hr4EGBXWomY8DAd
BgNVHQ4EFgQUnX3YlszQUX1202l8EPGZrvcHfvIwDgYDVR0PAQH/BAQDAgeAMD0G
A1UdEgQ2MDSBE2NvbnRhY3RAbW9iaWxlaWQucHSGHWh0dHBzOi8vdmhhc2xhYjAz
LmluZXNjdGVjLnB0MBIGA1UdJQQLMAkGByiBjF0FAQIwDAYDVR0TAQH/BAIwADBJ
BgNVHR8EQjBAMD6gPKA6hjhodHRwczovL3ZoYXNsYWIwNS5pbmVzY3RlYy5wdC92
Mi9jcmxzL01vYmlsZUlEX0lBX1BULmRlcjAKBggqhkjOPQQDAwNnADBkAjBNz4Pk
j8f772IgCxoUfIBNxeYtirbO2FdR/PDZTrF4IW8SIQqKNBJHXP2QvLu5QEgCMCLQ
9OKs233/2dbH3Gbx1jBVbY1IaqpmWucdgvUGZ/79aVlgKQ64QXZcWPRwQyRnPA==
-----END CERTIFICATE-----

the code I use to verify:

let root_cert_der = decodeCert(root_cert_pem);
let ds_cert_der = decodeCert(ds_cert_pem);
let trustedCertificates = [];
let certificates_to_verify = [];
let crls = [];
trustedCertificates.push(root_cert_der);
certificates_to_verify.push(ds_cert_der);
const certChainVerificationEngine = new pkijs.CertificateChainValidationEngine({
                trustedCertificates,
                certs: certificates_to_verify,
                crls
});

let result = await certChainVerificationEngine.verify();

function decodeCert:

function decodeCert(pem) {
  if(typeof pem !== 'string') {
      throw new Error('Expected PEM as string');
  }

  // Load certificate in PEM encoding (base64 encoded DER)
  const b64 = pem.replace(/(-----(BEGIN|END) CERTIFICATE-----|[\n\r])/g, '');

  // Now that we have decoded the cert it's now in DER-encoding
  const der = Buffer.from(b64, 'base64');

  // And massage the cert into a BER encoded one
  const ber = new Uint8Array(der).buffer;

  // And now Asn1js can decode things
  const asn1 = asn1js.fromBER(ber);

  return new pkijs.Certificate({ schema: asn1.result });
}
YuryStrozhevsky commented 3 years ago

I have tested it using this live example - all works fine with decoded (binary) data. So, I do suspect you have troubles decoding BASE-64. There were a number of similar issues, check this one for example. You could also search for "BASE-64" in closed issues.

filipap commented 3 years ago

I have tested it using this live example - all works fine with decoded (binary) data. So, I do suspect you have troubles decoding BASE-64. There were a number of similar issues, check this one for example. You could also search for "BASE-64" in closed issues.

After some researching inside https://github.com/PeculiarVentures/PKI.js/issues/208, I followed your suggestion and I changed the base64 decode function from this:

const der = Buffer.from(b64, 'base64');

const ber = new Uint8Array(der).buffer;

to this (used by the lib as well):

const ber = pvutils.stringToArrayBuffer(pvutils.fromBase64(b64))

And it worked absolutely fine! 😄 Thank you so much for your patience!