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.3k stars 204 forks source link

[OCSPRequest] fromSchema overrides `signatureAlgorithm` with value from `certs` #313

Open dhensby opened 3 years ago

dhensby commented 3 years ago

As part of the OCSPRequest specification , OCSP requests can be signed by the private key of the certificate making the OCSP Request. This forms the optionalSignature part of the Request.

The optionalSignature is formed of a signature algorithm, the signature itself and then an optional sequence of 1 or more certificates (usually the issuing certificate, but it can be a chain of certs).

When decoding an OCSPRequest, the current implementation will erroneously decode the signing algorithm used.

I believe this is because of a naming collision for signatureAlgorithm, which is used both my optionalSignature and the nested Certificate that forms part of optionalSignature.

Given that there can be multiple certificates in the sequence, it also appears that the previous certificate's signatureAlgorithm is overridden by that of the next.

So there appear to be two problems (though I have not verified the 2nd):

  1. The signatureAlgorithm from the sequence of certificates overwrites that of the optionalSignature
  2. An array of certificates will each override the root signatureAlgorithm
dhensby commented 3 years ago

Here's an example of creating a OCSPRequest and then decoding it and where the problem is:

const { createHash }= require('crypto');
const pkijs = require('pkijs');
const asn1js = require('asn1js');

function pemToCert(pem) {
    const certData = pem
        .replace(/-{5}([^-]+)-{5}/g, '')
        .replace(/\n|\r/g, '');
    const certBuffer = Buffer.from(certData, 'base64');
    return new pkijs.Certificate({
        schema: asn1js.fromBER(new Uint8Array(certBuffer).buffer).result,
    });
}

function getCertSerialNumber(certificate) {
    return Buffer.from(certificate.serialNumber.valueBlock.valueHex);
}

function getIssuerKeyHash(certificate) {
    const aki = certificate.extensions.find(({ extnID }) => extnID === '2.5.29.35');
    return Buffer.from(aki.parsedValue.keyIdentifier.valueBlock.valueHex);
}

(async () => {
    const cert = pemToCert(certPem);
    const issuerCert = pemToCert(issuerPem);

    const issuerNameHash = createHash('sha1').update(Buffer.from(cert.issuer.valueBeforeDecode)).digest();
    const issuerKeyHash = getIssuerKeyHash(cert);
    const serialNumber = getCertSerialNumber(cert);

    const request = new pkijs.OCSPRequest();
    request.tbsRequest.requestorName = new pkijs.GeneralName({
        type: 4, // directoryName
        value: cert.issuer,
    });
    request.tbsRequest.requestList = [
        new pkijs.Request({
            reqCert: new pkijs.CertID({
                hashAlgorithm: new pkijs.AlgorithmIdentifier({
                    algorithmId: '1.3.14.3.2.26', // SHA-1
                }),
                issuerNameHash: new asn1js.OctetString({ valueHex: issuerNameHash }),
                issuerKeyHash: new asn1js.OctetString({ valueHex: issuerKeyHash }),
                serialNumber: new asn1js.Integer({ valueHex: serialNumber }),
            }),
        }),
    ];
    request.optionalSignature = new pkijs.Signature({
        certs: [issuerCert],
    });

    await request.sign(..., 'SHA-512');

    // logs 1.2.840.113549.1.1.13 - the correct OID for SHA-512
    console.log(request.optionalSignature.signatureAlgorithm.algorithmId.toString())

    const ocspRequest = Buffer.from(request.toSchema(true).toBER(false));

    const decoded = new pkijs.OCSPRequest({ schema: asn1js.fromBER(new Uint8Array(ocspRequest).buffer).result });

    // logs 1.2.840.113549.1.1.5 - the OID for sha1 - the alg of the issuer cert signature
    console.log(decoded.optionalSignature.signatureAlgorithm.algorithmId.toString());

})().catch(console.error);
dhensby commented 3 years ago

I've had a good dig into this and can't see how to set the naming such that the signatureAlgorithm isn't overridden by the Certs or to have it stored against a different entry (like ocspRequest.signatureAlg).

microshine commented 3 years ago

@dhensby Could you share ASN.1 encoded OSCP request?

dhensby commented 3 years ago

Hi @microshine - the encoded request doesn't really matter because it's about the encoding process and the way that the objects are stored against a "root" schema object with shared names.

dhensby commented 3 years ago

Here is a request, though:

3082046c308193a14aa4483046310b300906035504061302555331133011060355040a130a476f6f676c6520496e633122302006035504031319476f6f676c6520496e7465726e657420417574686f72697479304530433041300706052b0e03021a0414d43b6713ab1a8679f0b70e169e9df889ed387a4b0414bfc030ebf543113e67ba9e91fb
fc6adae36b1224020a43c7e38e0000000061dea08203d2308203ce300b06092a864886f70d01010d038201010083767e1458a3545d564099375318cc443299db93d032f5c039c96f0bce358cbd5dc7463e676a00f982d5e21281027646512b39b181d1df82f4556a3305e3b781b1d3fc1904391d0178da0b8f74e9bf8ff43bb006098797f6cd9d
5a934fe6d5988e13671a12c2a4dcf5a02d03cc25cc9beb330edbe4ec597bf33750003e9e24143b7e82d242e059ca6e1e3e32027d0028eb45997b00ce724e9019d62b17bc5cb8a6bc89e637b0fd9ce815dd90a8d86164c6774304abb8208f5607b714468cacdd2f28060914cee3b9cdb53d9bf149300ddbcfe7dd1f8e2088e9f1d9266448ae6e55
9e13c85d41090d5158fc503e5b0fbb1571527a21cf5976df88fd5247591d0fa08202b8308202b4308202b030820219a00302010202030b6771300d06092a864886f70d0101050500304e310b30090603550406130255533110300e060355040a130745717569666178312d302b060355040b132445717569666178205365637572652043657274
6966696361746520417574686f72697479301e170d3039303630383230343332375a170d3133303630373139343332375a3046310b300906035504061302555331133011060355040a130a476f6f676c6520496e633122302006035504031319476f6f676c6520496e7465726e657420417574686f7269747930819f300d06092a864886f70d01
0101050003818d0030818902818100c9edb7a48b9c57e7843e407d84f48fd171635399e7797414af44993320928d7be5280cbaad6c497e835f34594e0a7a30cdd0d7c45745edd5aad67326cead3213b8d70f1d3bdfdddc0836a86f51449bcad6205273b72687356adba9e5d459a52bfc671939fa9318186cdedd258a0e331447c2ef015079e4fd
69d1a7c0ace2576f0203010001a381a33081a0300e0603551d0f0101ff040403020106301d0603551d0e04160414bfc030ebf543113e67ba9e91fbfc6adae36b1224301f0603551d2304183016801448e668f92bd2b295d747d82320104f3398909fd430120603551d130101ff040830060101ff020100303a0603551d1f04333031302fa02da0
2b8629687474703a2f2f63726c2e67656f74727573742e636f6d2f63726c732f73656375726563612e63726c300d06092a864886f70d010105050003818100b88a23c64896b1117c60775e059aaba1c6fa821c1807c4eb81b0a866eb49a8e90cd329adf5ef244cfde44bca7f5e63ab9927cb9f36212cb9106067cdd2b4f0f0ab71e58b5a892711
84aa8ebf99f09d09210a52199a5a09d290b7fa0cf87e78a2b085af5c4c99d95c5529f9a551422e3acb388c783bcbf8fb9587bcbc90f95032
microshine commented 3 years ago

@dhensby Have you seen @peculiar/asn1-schema and @peculiar/asn1-ocsp modules? These modules declare ASN.1 schemas only

I've created a simple example of parsing the OCSP request you shared.

https://codesandbox.io/s/parse-ocsp-request-53yr2

Does it return correct data?

As I can remember the problem with naming collision is in ASN1js module. It must use unique names for schema entries. Cause it returns all named schemas in a single object and doesn't keep the data structure.

microshine commented 3 years ago

It shows different mechanisms for certificate.signatureAlgorithm and optionalSignature.signatureAlgorithm

image

microshine commented 3 years ago

Here is the result of Object.keys for asn1.result from Signature

Signature: [
  'blockLength',
  'error',
  'warnings',
  'valueBeforeDecode',
  'idBlock',
  'lenBlock',
  'valueBlock',
  'signatureAlgorithm',
  'signature',
  'tbsCertificate',
  'tbsCertificate.version',
  'tbsCertificate.serialNumber',
  'tbsCertificate.signature',
  '',
  'tbsCertificate.issuer',
  'tbsCertificate.validity',
  'tbsCertificate.notBefore',
  'tbsCertificate.notAfter',
  'tbsCertificate.subject',
  'tbsCertificate.subjectPublicKeyInfo',
  'tbsCertificate.extensions',
  'signatureValue',
  'certs'
]

You can see that Signatute fields are mixed with the fields of the Certificate. And each Certificate field will be contain data from the last certificate in list

dhensby commented 3 years ago

Thanks for the replies @microshine.

Have you seen @peculiar/asn1-schema and @peculiar/asn1-ocsp modules? These modules declare ASN.1 schemas only

I haven't see these, I'll take a look.

As I can remember the problem with naming collision is in ASN1js module. It must use unique names for schema entries. Cause it returns all named schemas in a single object and doesn't keep the data structure.

You can see that Signatute fields are mixed with the fields of the Certificate. And each Certificate field will be contain data from the last certificate in list

Yes, this is precisely the problem. The names that are being passed to the asn1js module aren't taking account of "context" (ie: that they are nested). There appears to be a local option that can be passed to Repeated schemas, which I've tried to use for the certs but this doesn't seem to entirely solve the problem.

It looks to be like it would be best if the OCSPRequest.fromSchema method could pass down the names of the tbsCertificate signatures so that the naming collision is avoided but I could quite figure out how to do it.

It shows different mechanisms for certificate.signatureAlgorithm and optionalSignature.signatureAlgorithm

That looks correct; I'll do some investigating.


In summary, does this mean that essentially it's a known-issue either with this lib or asn1js and there's not a lot to be done about it?

microshine commented 3 years ago

I'll take a look at this problem and try to fix it in PKIjs. But ideally, we need to update ASN1js API which requires update PKIjs too (it's a lot of changes). Right now I'm busy on another project and going to do these updates after that.

@peculiar/asn1-schema is based on ASN1js library and solves that problem

YuryStrozhevsky commented 3 years ago

@dhensby If you do worry about same naming then better way is to change default naming in schema function:

    static schema(parameters = {})
    {
        /**
         * @type {Object}
         * @property {string} [blockName]
         * @property {string} [tbsRequest]
         * @property {string} [optionalSignature]
         */
        const names = getParametersValue(parameters, "names", {});

        return (new asn1js.Sequence({
            name: names.blockName || "OCSPRequest",
            value: [
                TBSRequest.schema(names.tbsRequest || {
                    names: {
                        blockName: "tbsRequest"
                    }
                }),
                new asn1js.Constructed({
                    optional: true,
                    idBlock: {
                        tagClass: 3, // CONTEXT-SPECIFIC
                        tagNumber: 0 // [0]
                    },
                    value: [
                        Signature.schema(names.optionalSignature || {
                            names: {
                                blockName: "optionalSignature",
                                signatureAlgorithm: {
                                    names: {
                                        blockName: "optionalSignatureAlgorithm"
                                    }
                                },
                            }
                        })
                    ]
                })
            ]
        }));
    }

Each naming could be configured via a parameters to schema function. Also this line is unnecessary - the optional flag works during schema parsing only.

dhensby commented 3 years ago

@YuryStrozhevsky - I don't think the naming works deep enough because we want to change the name of optionalSignature on the certs that are extracted inside the Signature.

Also, becuase we're using fromSchema which then just loads a Signature, I think it's the Signature.schema that needs changing?

YuryStrozhevsky commented 3 years ago

@dhensby It do works "deep enough" :) Just check the schema functions for all related subelements.

YuryStrozhevsky commented 3 years ago

Also, becuase we're using fromSchema which then just loads a Signature, I think it's the Signature.schema that needs changing?

No, only a parameter to the function call should be changed.

YuryStrozhevsky commented 3 years ago
    static schema(parameters = {})
    {
        /**
         * @type {Object}
         * @property {string} [blockName]
         * @property {string} [tbsRequest]
         * @property {string} [optionalSignature]
         */
        const names = getParametersValue(parameters, "names", {});

        return (new asn1js.Sequence({
            name: names.blockName || "OCSPRequest",
            value: [
                TBSRequest.schema(names.tbsRequest || {
                    names: {
                        blockName: "tbsRequest"
                    }
                }),
                new asn1js.Constructed({
                    optional: true,
                    idBlock: {
                        tagClass: 3, // CONTEXT-SPECIFIC
                        tagNumber: 0 // [0]
                    },
                    value: [
                        Signature.schema(names.optionalSignature || {
                            names: {
                                blockName: "optionalSignature",
                                signatureAlgorithm: {
                                    names: {
                                        blockName: "optionalSignatureAlgorithm"
                                    }
                                },
                                certs: {
                                    signatureAlgorithm: {
                                        names: {
                                            blockName: "certificateOptionalSignatureAlgorithm"
                                        }
                                    },
                                }
                            }
                        })
                    ]
                })
            ]
        }));
    }
YuryStrozhevsky commented 3 years ago

@dhensby In fact you do not need to change PKIjs for this. All you need is to make you own class which would be a "successor" for OCSPRequest then make you own fromSchema function in the class and the just call schema with necessary parameters. So, all other functions of the new class would works same with OCSPRequest, but schema parsing would satisfy your specific needs.

dhensby commented 3 years ago

@YuryStrozhevsky my specific needs are to parse standards compliant OCSP requests, which I'd suggest is what the library is intended for. I'm happy to implement a custom class locally that works, but I've opened this issue to highlight that the current implementation doesn't work correctly.

Thanks for the example code, I'll give that a run and see if it makes a difference.

Also, I think that on inspection the problem isn't really with the OCSPRequest implementation (though it may well be "fixable" there) but with the fact that there is a naming collision with Certificate.signatureAlgorithm and Signature.signatureAlgorithm. There is also the possibility that the array of Certificates in OCSPRequest will cause this Certificate naming collision to be a problem as well if more than 1 certificate is supplied to the array.

dhensby commented 3 years ago

@YuryStrozhevsky - I've tested the change locally with your suggestion from https://github.com/PeculiarVentures/PKI.js/issues/313#issuecomment-827494462 and it does not make any difference

YuryStrozhevsky commented 3 years ago

@dhensby I am not at work at the moment. As soon as I will I promise to test it myself. In any case I do suggest you to inspect “schema” functions deeper - it do satisfy all you possible needs. As for “current implementation doesn’t work correctly”: I don’t see any errors in your findings. All you described is that names overrides. Please specify where exactly you think PKIJS works incorrectly.

dhensby commented 3 years ago

I spent about 4 hours yesterday stepping through the parsing in a debugger, so I've looked pretty deeply into how this is working and I'm not completely able to follow it all the way down and not to the point of being able to fix the problem. It looks like @microshine understands that there is indeed some naming collision issues going on, so maybe he knows best how to resolve it.

The high level problem is this: I parse a valid (accepted by the VA server) OCSP Request, this request has an optionalSignature which has signatureAlgorithm of sha512WithRsaEncryption. When the parsing of the request is finished by the library the signature algorithm is reported as sha256WithRsaEncryption. When I step through with the debugger I can see up to this line https://github.com/PeculiarVentures/PKI.js/blob/master/src/OCSPRequest.js#L160 the algorithmIdentifier is correctly extracted - ie: asn1.result.optionalSignature.signatureAlgorithm is correct. However, once it is processed by Signature.fromSchema the asn1.result.optionalSignature.signatureAlgorithm has been overwritten by the algorithmIdentifier that was extracted from the last Certificate entry in the certs array that forms part of the optionalSignature. Therefore when the OCSPRequest is reencoded to asn1 the optionalSignature.signatureAlgorithm is erroneously declared as sha256WithRsaEncryption.

I think the root cause of the problem is that there is a naming collision with signatureAlgorithm in both OCSPRequest and Certificate and that this isn't name-spaced in any way to prevent this from happening. The fact that there is also a collision with Certificate and itself meaning an array of certificates will continuously override the value of the previous one. See https://github.com/PeculiarVentures/PKI.js/blob/v2.1.95/src/Signature.js#L122-L125

YuryStrozhevsky commented 3 years ago

@dhensby OK I have tested it. Code should be like this ![Uploading 480E407C-46AA-444F-B722-8110F469D7E9.jpeg…]()

YuryStrozhevsky commented 3 years ago
static schema(parameters = {}) {
    /**
     * @type {Object}
     * @property {string} [blockName]
     * @property {string} [tbsRequest]
     * @property {string} [optionalSignature]
     */
    const names = getParametersValue(parameters, "names", {});
    return new asn1js.Sequence({
      name: names.blockName || "OCSPRequest",
      value: [TBSRequest.schema(names.tbsRequest || {
        names: {
          blockName: "tbsRequest"
        }
      }), new asn1js.Constructed({
        optional: true,
        idBlock: {
          tagClass: 3,
          // CONTEXT-SPECIFIC
          tagNumber: 0 // [0]

        },
        value: [Signature.schema(names.optionalSignature || {
          names: {
            blockName: "optionalSignature",
              certs: {
                names: {
                    signatureAlgorithm: {
                        names: {
                            blockName: 'otpionalCertSignAlgorithm',
                        }
                    }
                }
              }
          }
        })]
      })]
    });
  }
dhensby commented 3 years ago

Thanks for that. Using your code:

static schema(parameters = {}) {
    /**
     * @type {Object}
     * @property {string} [blockName]
     * @property {string} [tbsRequest]
     * @property {string} [optionalSignature]
     */
    const names = getParametersValue(parameters, "names", {});
    return new asn1js.Sequence({
      name: names.blockName || "OCSPRequest",
      value: [TBSRequest.schema(names.tbsRequest || {
        names: {
          blockName: "tbsRequest"
        }
      }), new asn1js.Constructed({
        optional: true,
        idBlock: {
          tagClass: 3,
          // CONTEXT-SPECIFIC
          tagNumber: 0 // [0]

        },
        value: [Signature.schema(names.optionalSignature || {
          names: {
            blockName: "optionalSignature",
              certs: {
                names: {
                    signatureAlgorithm: {
                        names: {
                            blockName: 'otpionalCertSignAlgorithm',
                        }
                    }
                }
              }
          }
        })]
      })]
    });
  }

The encoded data still reports the signature algorithm as 1.2.840.113549.1.1.11 (sha256WithRSAEncryption) and not 1.2.840.113549.1.1.13 (sha512WithRSAEncryption). So it does not appear to resolve the problem.

Parsed result before constructing Signature

After Signature construction

YuryStrozhevsky commented 3 years ago

@dhensby I don’t have any more time today for you and again suggest you to inspect how pkijs names any objects inside schema static functions. Will continue tomorrow.

dhensby commented 3 years ago

I have a slight feeling that the solution is to add local: true to here https://github.com/PeculiarVentures/PKI.js/blob/v2.1.95/src/Signature.js#L122-L125

But that causes quite a large change to the parsing behaviour and something I don't have the knowledge or time to fix throughout the library.

YuryStrozhevsky commented 3 years ago

@dhensby No, all this not a big problem at all. But yes, it was a mistake, but a mistake not in OCSPRequest class but in Signature. So, here is the correct code for Signature.fromSchema function:

    fromSchema(schema)
    {
        //region Clear input data first
        clearProps(schema, [
            "signatureAlgorithm",
            "signature",
            "certs"
        ]);
        //endregion

        //region Check the schema is valid
        const asn1 = asn1js.compareSchema(schema,
            schema,
            Signature.schema({
                names: {
                    signatureAlgorithm: {
                        names: {
                            blockName: "signatureAlgorithm"
                        }
                    },
                    signature: "signature",
                    certs: {
                        names: {
                            signatureAlgorithm: {
                                names: {
                                    blockName: "certSignatureAlgorithm"
                                }
                            }
                        }
                    }
                }
            })
        );

        if(asn1.verified === false)
            throw new Error("Object's schema was not verified against input data for Signature");
        //endregion

        //region Get internal properties from parsed schema
        this.signatureAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.signatureAlgorithm });
        this.signature = asn1.result.signature;

        if("certs" in asn1.result)
            this.certs = Array.from(asn1.result.certs, element => new Certificate({ schema: element }));
        //endregion
    }

As you can see all the changes are about simple changes in schema naming.

Thank you, it is really hard to find such errors. And the error could have a big "consiquences".

microshine commented 3 years ago

@dhensby Please take a look at this example

import { X509CertificateGenerator, Name as X509Name } from "@peculiar/x509";
import { Certificate, GeneralName, Name } from "@peculiar/asn1-x509";
import { sha1, sha256WithRSAEncryption } from "@peculiar/asn1-rsa";
import { Crypto } from "@peculiar/webcrypto";
import { AsnConvert, OctetString } from "@peculiar/asn1-schema";
import { CertID, OCSPRequest, Request, Signature, TBSRequest } from "@peculiar/asn1-ocsp";
import { Convert } from "pvtsutils";

const crypto = new Crypto();

async function main() {
  const year = 31104e6;
  const alg = {
    name: "RSASSA-PKCS1-v1_5",
    hash: "SHA-256",
    modulusLength: 2048,
    publicExponent: new Uint8Array([1, 0, 1])
  };

  // Create CA cert
  const caKeys = await crypto.subtle.generateKey(alg, false, [
    "sign",
    "verify"
  ]);
  const caCert = await X509CertificateGenerator.createSelfSigned(
    {
      name: "CN=Test Root CA",
      keys: caKeys,
      notBefore: new Date(),
      notAfter: new Date(Date.now() + (2 * year)), // + 2y
      serialNumber: "01",
      signingAlgorithm: alg
    },
    crypto
  );
  console.log("CA certificate created");

  // Create LEaf cert
  const leafKeys = await crypto.subtle.generateKey(alg, false, [
    "sign",
    "verify"
  ]);
  const leafCert = await X509CertificateGenerator.create(
    {
      subject: "CN=Test cert",
      issuer: caCert.subject,
      signingKey: caKeys.privateKey,
      publicKey: leafKeys.publicKey,
      notBefore: new Date(),
      notAfter: new Date(Date.now() + year), // + 1y
      serialNumber: "02",
      signingAlgorithm: alg
    },
    crypto
  );
  console.log("Leaf certificate created");

  const issuerNameHash = await crypto.subtle.digest("SHA-1", new X509Name(leafCert.issuer).toArrayBuffer());
  const issuerKeyHash = await leafCert.publicKey.getThumbprint("SHA-1", crypto);

  // Create OCSP request
  const tbsRequest = new TBSRequest({
    requestorName: new GeneralName({
      directoryName: AsnConvert.parse(new X509Name(leafCert.subject).toArrayBuffer(), Name),
    }),
    requestList: [
      new Request({
        reqCert: new CertID({
          hashAlgorithm: sha1,
          issuerNameHash: new OctetString(issuerNameHash),
          issuerKeyHash: new OctetString(issuerKeyHash),
          serialNumber: Convert.FromHex(leafCert.serialNumber),
        }),
      }),
    ],
  });
  const signature = await crypto.subtle.sign(alg, leafKeys.privateKey, AsnConvert.serialize(tbsRequest));

  const ocspRequest = new OCSPRequest({
    tbsRequest,
    optionalSignature: new Signature({
      certs: [AsnConvert.parse(leafCert.rawData, Certificate)],
      signatureAlgorithm: sha256WithRSAEncryption,
      signature,
    }),
  });
  const ocspRequestRaw = AsnConvert.serialize(ocspRequest);

  console.log("OCSP request:");
  console.log(Convert.ToHex(ocspRequestRaw));
}

main().catch((e) => console.error(e));

Output

CA certificate created
Leaf certificate created
OCSP request:
3082042c305aa118a41630143112301006035504031309546573742063657274303e303c303a300906052b0e03021a050004148f560cabb8fd639be521e57651e35b17258e07d4041427efa936161ed849527c3e0c47f085ca57ef1476020102a08203cc308203c8300d06092a864886f70d0101100500038201010079542da667db1af29aaa071d971ca39496502d8f262679074341c476cc718bfe6602a47cec39529e4c24ba5240bcfe773cc3f1c20d7a58c3f6fd5deb49d65df6b8faf2301fb3aa97d9f61bb5a7c4a2046ab59e3d8bc913d9be179ec2dfa493b43758a6508ae7407c4cb99e5132269bed8df0e7d79bf661ff24a8927a176daa6a7718b250826e0696b1dbad047f377de945625103e900dbe39172399a785f23625b485c08de56156cef790716cd604c5edb3658abc0401a977329f5035a3a90442e22ee717d3a9f1221683dd7ff3d3374a45c8a7fd03eb690c04f027d2b593a4b00f4ad038426b1e898bdb0e88330c7d0ad231e9ee2e589856bf915755fe4f640a08202b0308202ac308202a830820190a003020102020102300d06092a864886f70d01010b05003017311530130603550403130c5465737420526f6f74204341301e170d3231303432373133323435395a170d3232303432323133323435395a3014311230100603550403130954657374206365727430820122300d06092a864886f70d01010105000382010f003082010a02820101009ac77db2ee36cdca5ed2b7044d0d5726e59f774e32a2eec13eed6805ae311b4cc9b7cbece9c938b767bec4ce1f3f56b2fe4613172e4b35e109ae23a7b1a6a3d4b70a236eba506378b6832acf96446316ed838a1f0f985fac6bfe60b4966906e604b93f9412bc4b670ff3726370a8ae7e3967e8c9c9dc7cf230bd7900c4800db7ce65be46acb603f07bc0de2f1ba4ec3537e50f5fc07259663ffe9f1132bb7da060de197a5b524ed0ddd16e2a075d830a68c3ce3eb9720f6259aead640ea9b42272f88873368441a945a7f9b6363c92a73251da5a100e3ea9bf276f22cae76e6070fc15f52360e2166b8770e00c8caa4ec15150736027f5f39dc650488b42e14d0203010001a3023000300d06092a864886f70d01010b05000382010100b7439b6dc23422635502a3442d40e170fe3bf5ffd7e503d2d9fa7f4221cc0a01b5b83e5e9097d04a01b43dc1116e8fc51e955a8e32385f992f16e71cb7c490387e27384c28688c054a22b33a2c0ac4c0fa205c82ad183fe05c9fcbe99f41b3df5152d0ffe2ceec2f972001bc9c28af4a483934562e371d3a04ee87bbd1bf648d0b5a99081caa4b93f38fa4f2f355b605783b35e354ce6993f623ed2c67efc9f5baf3513340b19445d266016c734f2f186ff177726d9e2b9186cd2abe3804a419c6278f220b7c3461f15bcb0b657c0d41dd41a1c24004cb2e6442d1305a7f3c9388e873da0bd93d1f260663eed3c2eb52e13da5a46cc0c3404645f67173e2aa7f
dhensby commented 3 years ago

@microshine I've been looking at those other libraries and they do appear to be much more reliable and do decode and encode OSCPRequests successfully, so I am building out a proof of concept with those; thanks for the proof-of-concept code :)

The only small part that is a bit more work is that the built-in extension parsing has not been implemented.

microshine commented 3 years ago

@peculiar/x509 does it. It also allows registering known extensions in runtime.

By default, it implements these extensions

image

microshine commented 3 years ago

Here is one more example of @peculiar/x509 usage

https://codesandbox.io/s/generate-cert-fjwfh?file=/src/main.js

As you can see each extension has got parsed values

image

dhensby commented 3 years ago

Interesting - is there any docs on how to register the extensions at runtime? It doesn't appear to be doing it for AsnConvert.parse(certBuffer, Certificate);

extensions

microshine commented 3 years ago

https://peculiarventures.github.io/x509/classes/extensionfactory.html#register