tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CertificateRevocationList.ts (20174B)


      1 import * as asn1js from "asn1js";
      2 import * as pvtsutils from "pvtsutils";
      3 import * as pvutils from "pvutils";
      4 import * as common from "./common";
      5 import { AlgorithmIdentifier, AlgorithmIdentifierJson, AlgorithmIdentifierSchema } from "./AlgorithmIdentifier";
      6 import { RelativeDistinguishedNames, RelativeDistinguishedNamesJson, RelativeDistinguishedNamesSchema } from "./RelativeDistinguishedNames";
      7 import { Time, TimeJson, TimeSchema } from "./Time";
      8 import { RevokedCertificate, RevokedCertificateJson } from "./RevokedCertificate";
      9 import { Extensions, ExtensionsJson, ExtensionsSchema } from "./Extensions";
     10 import * as Schema from "./Schema";
     11 import { Certificate } from "./Certificate";
     12 import { PublicKeyInfo } from "./PublicKeyInfo";
     13 import { id_AuthorityInfoAccess, id_AuthorityKeyIdentifier, id_BaseCRLNumber, id_CertificateIssuer, id_CRLNumber, id_CRLReason, id_FreshestCRL, id_InvalidityDate, id_IssuerAltName, id_IssuingDistributionPoint } from "./ObjectIdentifiers";
     14 import { AsnError } from "./errors";
     15 import { PkiObject, PkiObjectParameters } from "./PkiObject";
     16 import { EMPTY_BUFFER } from "./constants";
     17 
     18 const TBS = "tbs";
     19 const VERSION = "version";
     20 const SIGNATURE = "signature";
     21 const ISSUER = "issuer";
     22 const THIS_UPDATE = "thisUpdate";
     23 const NEXT_UPDATE = "nextUpdate";
     24 const REVOKED_CERTIFICATES = "revokedCertificates";
     25 const CRL_EXTENSIONS = "crlExtensions";
     26 const SIGNATURE_ALGORITHM = "signatureAlgorithm";
     27 const SIGNATURE_VALUE = "signatureValue";
     28 const TBS_CERT_LIST = "tbsCertList";
     29 const TBS_CERT_LIST_VERSION = `${TBS_CERT_LIST}.version`;
     30 const TBS_CERT_LIST_SIGNATURE = `${TBS_CERT_LIST}.signature`;
     31 const TBS_CERT_LIST_ISSUER = `${TBS_CERT_LIST}.issuer`;
     32 const TBS_CERT_LIST_THIS_UPDATE = `${TBS_CERT_LIST}.thisUpdate`;
     33 const TBS_CERT_LIST_NEXT_UPDATE = `${TBS_CERT_LIST}.nextUpdate`;
     34 const TBS_CERT_LIST_REVOKED_CERTIFICATES = `${TBS_CERT_LIST}.revokedCertificates`;
     35 const TBS_CERT_LIST_EXTENSIONS = `${TBS_CERT_LIST}.extensions`;
     36 const CLEAR_PROPS = [
     37  TBS_CERT_LIST,
     38  TBS_CERT_LIST_VERSION,
     39  TBS_CERT_LIST_SIGNATURE,
     40  TBS_CERT_LIST_ISSUER,
     41  TBS_CERT_LIST_THIS_UPDATE,
     42  TBS_CERT_LIST_NEXT_UPDATE,
     43  TBS_CERT_LIST_REVOKED_CERTIFICATES,
     44  TBS_CERT_LIST_EXTENSIONS,
     45  SIGNATURE_ALGORITHM,
     46  SIGNATURE_VALUE
     47 ];
     48 
     49 export interface ICertificateRevocationList {
     50  tbs: ArrayBuffer;
     51  version: number;
     52  signature: AlgorithmIdentifier;
     53  issuer: RelativeDistinguishedNames;
     54  thisUpdate: Time;
     55  nextUpdate?: Time;
     56  revokedCertificates?: RevokedCertificate[];
     57  crlExtensions?: Extensions;
     58  signatureAlgorithm: AlgorithmIdentifier;
     59  signatureValue: asn1js.BitString;
     60 }
     61 
     62 export type TBSCertListSchema = Schema.SchemaParameters<{
     63  tbsCertListVersion?: string;
     64  signature?: AlgorithmIdentifierSchema;
     65  issuer?: RelativeDistinguishedNamesSchema;
     66  tbsCertListThisUpdate?: TimeSchema;
     67  tbsCertListNextUpdate?: TimeSchema;
     68  tbsCertListRevokedCertificates?: string;
     69  crlExtensions?: ExtensionsSchema;
     70 }>;
     71 
     72 export interface CertificateRevocationListJson {
     73  tbs: string;
     74  version: number;
     75  signature: AlgorithmIdentifierJson;
     76  issuer: RelativeDistinguishedNamesJson;
     77  thisUpdate: TimeJson;
     78  nextUpdate?: TimeJson;
     79  revokedCertificates?: RevokedCertificateJson[];
     80  crlExtensions?: ExtensionsJson;
     81  signatureAlgorithm: AlgorithmIdentifierJson;
     82  signatureValue: asn1js.BitStringJson;
     83 }
     84 
     85 function tbsCertList(parameters: TBSCertListSchema = {}): Schema.SchemaType {
     86  //TBSCertList ::= SEQUENCE  {
     87  //    version                 Version OPTIONAL,
     88  //                                 -- if present, MUST be v2
     89  //    signature               AlgorithmIdentifier,
     90  //    issuer                  Name,
     91  //    thisUpdate              Time,
     92  //    nextUpdate              Time OPTIONAL,
     93  //    revokedCertificates     SEQUENCE OF SEQUENCE  {
     94  //        userCertificate         CertificateSerialNumber,
     95  //        revocationDate          Time,
     96  //        crlEntryExtensions      Extensions OPTIONAL
     97  //        -- if present, version MUST be v2
     98  //    }  OPTIONAL,
     99  //    crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
    100  //    -- if present, version MUST be v2
    101  //}
    102  const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {});
    103 
    104  return (new asn1js.Sequence({
    105    name: (names.blockName || TBS_CERT_LIST),
    106    value: [
    107      new asn1js.Integer({
    108        optional: true,
    109        name: (names.tbsCertListVersion || TBS_CERT_LIST_VERSION),
    110        value: 2
    111      }), // EXPLICIT integer value (v2)
    112      AlgorithmIdentifier.schema(names.signature || {
    113        names: {
    114          blockName: TBS_CERT_LIST_SIGNATURE
    115        }
    116      }),
    117      RelativeDistinguishedNames.schema(names.issuer || {
    118        names: {
    119          blockName: TBS_CERT_LIST_ISSUER
    120        }
    121      }),
    122      Time.schema(names.tbsCertListThisUpdate || {
    123        names: {
    124          utcTimeName: TBS_CERT_LIST_THIS_UPDATE,
    125          generalTimeName: TBS_CERT_LIST_THIS_UPDATE
    126        }
    127      }),
    128      Time.schema(names.tbsCertListNextUpdate || {
    129        names: {
    130          utcTimeName: TBS_CERT_LIST_NEXT_UPDATE,
    131          generalTimeName: TBS_CERT_LIST_NEXT_UPDATE
    132        }
    133      }, true),
    134      new asn1js.Sequence({
    135        optional: true,
    136        value: [
    137          new asn1js.Repeated({
    138            name: (names.tbsCertListRevokedCertificates || TBS_CERT_LIST_REVOKED_CERTIFICATES),
    139            value: new asn1js.Sequence({
    140              value: [
    141                new asn1js.Integer(),
    142                Time.schema(),
    143                Extensions.schema({}, true)
    144              ]
    145            })
    146          })
    147        ]
    148      }),
    149      new asn1js.Constructed({
    150        optional: true,
    151        idBlock: {
    152          tagClass: 3, // CONTEXT-SPECIFIC
    153          tagNumber: 0 // [0]
    154        },
    155        value: [Extensions.schema(names.crlExtensions || {
    156          names: {
    157            blockName: TBS_CERT_LIST_EXTENSIONS
    158          }
    159        })]
    160      }) // EXPLICIT SEQUENCE value
    161    ]
    162  }));
    163 }
    164 
    165 export type CertificateRevocationListParameters = PkiObjectParameters & Partial<ICertificateRevocationList>;
    166 
    167 export interface CertificateRevocationListVerifyParams {
    168  issuerCertificate?: Certificate;
    169  publicKeyInfo?: PublicKeyInfo;
    170 }
    171 
    172 const WELL_KNOWN_EXTENSIONS = [
    173  id_AuthorityKeyIdentifier,
    174  id_IssuerAltName,
    175  id_CRLNumber,
    176  id_BaseCRLNumber,
    177  id_IssuingDistributionPoint,
    178  id_FreshestCRL,
    179  id_AuthorityInfoAccess,
    180  id_CRLReason,
    181  id_InvalidityDate,
    182  id_CertificateIssuer,
    183 ];
    184 /**
    185 * Represents the CertificateRevocationList structure described in [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)
    186 */
    187 export class CertificateRevocationList extends PkiObject implements ICertificateRevocationList {
    188 
    189  public static override CLASS_NAME = "CertificateRevocationList";
    190 
    191  public tbsView!: Uint8Array;
    192  /**
    193   * @deprecated Since version 3.0.0
    194   */
    195  public get tbs(): ArrayBuffer {
    196    return pvtsutils.BufferSourceConverter.toArrayBuffer(this.tbsView);
    197  }
    198 
    199  /**
    200   * @deprecated Since version 3.0.0
    201   */
    202  public set tbs(value: ArrayBuffer) {
    203    this.tbsView = new Uint8Array(value);
    204  }
    205  public version!: number;
    206  public signature!: AlgorithmIdentifier;
    207  public issuer!: RelativeDistinguishedNames;
    208  public thisUpdate!: Time;
    209  public nextUpdate?: Time;
    210  public revokedCertificates?: RevokedCertificate[];
    211  public crlExtensions?: Extensions;
    212  public signatureAlgorithm!: AlgorithmIdentifier;
    213  public signatureValue!: asn1js.BitString;
    214 
    215  /**
    216   * Initializes a new instance of the {@link CertificateRevocationList} class
    217   * @param parameters Initialization parameters
    218   */
    219  constructor(parameters: CertificateRevocationListParameters = {}) {
    220    super();
    221 
    222    this.tbsView = new Uint8Array(pvutils.getParametersValue(parameters, TBS, CertificateRevocationList.defaultValues(TBS)));
    223    this.version = pvutils.getParametersValue(parameters, VERSION, CertificateRevocationList.defaultValues(VERSION));
    224    this.signature = pvutils.getParametersValue(parameters, SIGNATURE, CertificateRevocationList.defaultValues(SIGNATURE));
    225    this.issuer = pvutils.getParametersValue(parameters, ISSUER, CertificateRevocationList.defaultValues(ISSUER));
    226    this.thisUpdate = pvutils.getParametersValue(parameters, THIS_UPDATE, CertificateRevocationList.defaultValues(THIS_UPDATE));
    227    if (NEXT_UPDATE in parameters) {
    228      this.nextUpdate = pvutils.getParametersValue(parameters, NEXT_UPDATE, CertificateRevocationList.defaultValues(NEXT_UPDATE));
    229    }
    230    if (REVOKED_CERTIFICATES in parameters) {
    231      this.revokedCertificates = pvutils.getParametersValue(parameters, REVOKED_CERTIFICATES, CertificateRevocationList.defaultValues(REVOKED_CERTIFICATES));
    232    }
    233    if (CRL_EXTENSIONS in parameters) {
    234      this.crlExtensions = pvutils.getParametersValue(parameters, CRL_EXTENSIONS, CertificateRevocationList.defaultValues(CRL_EXTENSIONS));
    235    }
    236    this.signatureAlgorithm = pvutils.getParametersValue(parameters, SIGNATURE_ALGORITHM, CertificateRevocationList.defaultValues(SIGNATURE_ALGORITHM));
    237    this.signatureValue = pvutils.getParametersValue(parameters, SIGNATURE_VALUE, CertificateRevocationList.defaultValues(SIGNATURE_VALUE));
    238 
    239    if (parameters.schema) {
    240      this.fromSchema(parameters.schema);
    241    }
    242  }
    243 
    244  /**
    245   * Returns default values for all class members
    246   * @param memberName String name for a class member
    247   * @returns Default value
    248   */
    249  public static override defaultValues(memberName: typeof TBS): ArrayBuffer;
    250  public static override defaultValues(memberName: typeof VERSION): number;
    251  public static override defaultValues(memberName: typeof SIGNATURE): AlgorithmIdentifier;
    252  public static override defaultValues(memberName: typeof ISSUER): RelativeDistinguishedNames;
    253  public static override defaultValues(memberName: typeof THIS_UPDATE): Time;
    254  public static override defaultValues(memberName: typeof NEXT_UPDATE): Time;
    255  public static override defaultValues(memberName: typeof REVOKED_CERTIFICATES): RevokedCertificate[];
    256  public static override defaultValues(memberName: typeof CRL_EXTENSIONS): Extensions;
    257  public static override defaultValues(memberName: typeof SIGNATURE_ALGORITHM): AlgorithmIdentifier;
    258  public static override defaultValues(memberName: typeof SIGNATURE_VALUE): asn1js.BitString;
    259  public static override defaultValues(memberName: string): any {
    260    switch (memberName) {
    261      case TBS:
    262        return EMPTY_BUFFER;
    263      case VERSION:
    264        return 0;
    265      case SIGNATURE:
    266        return new AlgorithmIdentifier();
    267      case ISSUER:
    268        return new RelativeDistinguishedNames();
    269      case THIS_UPDATE:
    270        return new Time();
    271      case NEXT_UPDATE:
    272        return new Time();
    273      case REVOKED_CERTIFICATES:
    274        return [];
    275      case CRL_EXTENSIONS:
    276        return new Extensions();
    277      case SIGNATURE_ALGORITHM:
    278        return new AlgorithmIdentifier();
    279      case SIGNATURE_VALUE:
    280        return new asn1js.BitString();
    281      default:
    282        return super.defaultValues(memberName);
    283    }
    284  }
    285 
    286  /**
    287   * @inheritdoc
    288   * @asn ASN.1 schema
    289   * ```asn
    290   * CertificateList ::= SEQUENCE  {
    291   *    tbsCertList          TBSCertList,
    292   *    signatureAlgorithm   AlgorithmIdentifier,
    293   *    signatureValue       BIT STRING  }
    294   *```
    295   */
    296  public static override schema(parameters: Schema.SchemaParameters<{
    297    tbsCertListVersion?: string;
    298    signature?: AlgorithmIdentifierSchema;
    299    issuer?: RelativeDistinguishedNamesSchema;
    300    tbsCertListThisUpdate?: TimeSchema;
    301    tbsCertListNextUpdate?: TimeSchema;
    302    tbsCertListRevokedCertificates?: string;
    303    crlExtensions?: ExtensionsSchema;
    304    signatureAlgorithm?: AlgorithmIdentifierSchema;
    305    signatureValue?: string;
    306  }> = {}): Schema.SchemaType {
    307    const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {});
    308 
    309    return (new asn1js.Sequence({
    310      name: (names.blockName || "CertificateList"),
    311      value: [
    312        tbsCertList(parameters),
    313        AlgorithmIdentifier.schema(names.signatureAlgorithm || {
    314          names: {
    315            blockName: SIGNATURE_ALGORITHM
    316          }
    317        }),
    318        new asn1js.BitString({ name: (names.signatureValue || SIGNATURE_VALUE) })
    319      ]
    320    }));
    321  }
    322 
    323  public fromSchema(schema: Schema.SchemaType): void {
    324    // Clear input data first
    325    pvutils.clearProps(schema, CLEAR_PROPS);
    326 
    327    // Check the schema is valid
    328    const asn1 = asn1js.compareSchema(schema,
    329      schema,
    330      CertificateRevocationList.schema()
    331    );
    332    AsnError.assertSchema(asn1, this.className);
    333 
    334    //#region Get internal properties from parsed schema
    335    this.tbsView = (asn1.result.tbsCertList as asn1js.Sequence).valueBeforeDecodeView;
    336 
    337    if (TBS_CERT_LIST_VERSION in asn1.result) {
    338      this.version = asn1.result[TBS_CERT_LIST_VERSION].valueBlock.valueDec;
    339    }
    340    this.signature = new AlgorithmIdentifier({ schema: asn1.result[TBS_CERT_LIST_SIGNATURE] });
    341    this.issuer = new RelativeDistinguishedNames({ schema: asn1.result[TBS_CERT_LIST_ISSUER] });
    342    this.thisUpdate = new Time({ schema: asn1.result[TBS_CERT_LIST_THIS_UPDATE] });
    343    if (TBS_CERT_LIST_NEXT_UPDATE in asn1.result) {
    344      this.nextUpdate = new Time({ schema: asn1.result[TBS_CERT_LIST_NEXT_UPDATE] });
    345    }
    346    if (TBS_CERT_LIST_REVOKED_CERTIFICATES in asn1.result) {
    347      this.revokedCertificates = Array.from(asn1.result[TBS_CERT_LIST_REVOKED_CERTIFICATES], element => new RevokedCertificate({ schema: element }));
    348    }
    349    if (TBS_CERT_LIST_EXTENSIONS in asn1.result) {
    350      this.crlExtensions = new Extensions({ schema: asn1.result[TBS_CERT_LIST_EXTENSIONS] });
    351    }
    352 
    353    this.signatureAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.signatureAlgorithm });
    354    this.signatureValue = asn1.result.signatureValue;
    355    //#endregion
    356  }
    357 
    358  protected encodeTBS() {
    359    //#region Create array for output sequence
    360    const outputArray: any[] = [];
    361 
    362    if (this.version !== CertificateRevocationList.defaultValues(VERSION)) {
    363      outputArray.push(new asn1js.Integer({ value: this.version }));
    364    }
    365 
    366    outputArray.push(this.signature.toSchema());
    367    outputArray.push(this.issuer.toSchema());
    368    outputArray.push(this.thisUpdate.toSchema());
    369 
    370    if (this.nextUpdate) {
    371      outputArray.push(this.nextUpdate.toSchema());
    372    }
    373 
    374    if (this.revokedCertificates) {
    375      outputArray.push(new asn1js.Sequence({
    376        value: Array.from(this.revokedCertificates, o => o.toSchema())
    377      }));
    378    }
    379 
    380    if (this.crlExtensions) {
    381      outputArray.push(new asn1js.Constructed({
    382        optional: true,
    383        idBlock: {
    384          tagClass: 3, // CONTEXT-SPECIFIC
    385          tagNumber: 0 // [0]
    386        },
    387        value: [
    388          this.crlExtensions.toSchema()
    389        ]
    390      }));
    391    }
    392    //#endregion
    393 
    394    return (new asn1js.Sequence({
    395      value: outputArray
    396    }));
    397  }
    398 
    399  /**
    400   * Convert current object to asn1js object and set correct values
    401   * @returns asn1js object
    402   */
    403  public toSchema(encodeFlag = false) {
    404    //#region Decode stored TBS value
    405    let tbsSchema;
    406 
    407    if (!encodeFlag) {
    408      if (!this.tbsView.byteLength) { // No stored TBS part
    409        return CertificateRevocationList.schema();
    410      }
    411 
    412      const asn1 = asn1js.fromBER(this.tbsView);
    413      AsnError.assert(asn1, "TBS Certificate Revocation List");
    414      tbsSchema = asn1.result;
    415    }
    416    //#endregion
    417    //#region Create TBS schema via assembling from TBS parts
    418    else {
    419      tbsSchema = this.encodeTBS();
    420    }
    421    //#endregion
    422 
    423    //#region Construct and return new ASN.1 schema for this object
    424    return (new asn1js.Sequence({
    425      value: [
    426        tbsSchema,
    427        this.signatureAlgorithm.toSchema(),
    428        this.signatureValue
    429      ]
    430    }));
    431    //#endregion
    432  }
    433 
    434  public toJSON(): CertificateRevocationListJson {
    435    const res: CertificateRevocationListJson = {
    436      tbs: pvtsutils.Convert.ToHex(this.tbsView),
    437      version: this.version,
    438      signature: this.signature.toJSON(),
    439      issuer: this.issuer.toJSON(),
    440      thisUpdate: this.thisUpdate.toJSON(),
    441      signatureAlgorithm: this.signatureAlgorithm.toJSON(),
    442      signatureValue: this.signatureValue.toJSON()
    443    };
    444 
    445    if (this.version !== CertificateRevocationList.defaultValues(VERSION))
    446      res.version = this.version;
    447 
    448    if (this.nextUpdate) {
    449      res.nextUpdate = this.nextUpdate.toJSON();
    450    }
    451 
    452    if (this.revokedCertificates) {
    453      res.revokedCertificates = Array.from(this.revokedCertificates, o => o.toJSON());
    454    }
    455 
    456    if (this.crlExtensions) {
    457      res.crlExtensions = this.crlExtensions.toJSON();
    458    }
    459 
    460    return res;
    461  }
    462 
    463  /**
    464   * Returns `true` if supplied certificate is revoked, otherwise `false`
    465   * @param certificate
    466   */
    467  public isCertificateRevoked(certificate: Certificate): boolean {
    468    // Check that issuer of the input certificate is the same with issuer of this CRL
    469    if (!this.issuer.isEqual(certificate.issuer)) {
    470      return false;
    471    }
    472 
    473    // Check that there are revoked certificates in this CRL
    474    if (!this.revokedCertificates) {
    475      return false;
    476    }
    477 
    478    // Search for input certificate in revoked certificates array
    479    for (const revokedCertificate of this.revokedCertificates) {
    480      if (revokedCertificate.userCertificate.isEqual(certificate.serialNumber)) {
    481        return true;
    482      }
    483    }
    484 
    485    return false;
    486  }
    487 
    488  /**
    489   * Make a signature for existing CRL data
    490   * @param privateKey Private key for "subjectPublicKeyInfo" structure
    491   * @param hashAlgorithm Hashing algorithm. Default SHA-1
    492   * @param crypto Crypto engine
    493   */
    494  public async sign(privateKey: CryptoKey, hashAlgorithm = "SHA-1", crypto = common.getCrypto(true)): Promise<void> {
    495    // Get a private key from function parameter
    496    if (!privateKey) {
    497      throw new Error("Need to provide a private key for signing");
    498    }
    499 
    500    //#region Get a "default parameters" for current algorithm and set correct signature algorithm
    501    const signatureParameters = await crypto.getSignatureParameters(privateKey, hashAlgorithm);
    502    const { parameters } = signatureParameters;
    503    this.signature = signatureParameters.signatureAlgorithm;
    504    this.signatureAlgorithm = signatureParameters.signatureAlgorithm;
    505    //#endregion
    506 
    507    //#region Create TBS data for signing
    508    this.tbsView = new Uint8Array(this.encodeTBS().toBER());
    509    //#endregion
    510 
    511    //#region Signing TBS data on provided private key
    512    const signature = await crypto.signWithPrivateKey(this.tbsView as BufferSource, privateKey, parameters as any);
    513    this.signatureValue = new asn1js.BitString({ valueHex: signature });
    514    //#endregion
    515  }
    516 
    517  /**
    518   * Verify existing signature
    519   * @param parameters
    520   * @param crypto Crypto engine
    521   */
    522  public async verify(parameters: CertificateRevocationListVerifyParams = {}, crypto = common.getCrypto(true)): Promise<boolean> {
    523    let subjectPublicKeyInfo: PublicKeyInfo | undefined;
    524 
    525    //#region Get information about CRL issuer certificate
    526    if (parameters.issuerCertificate) { // "issuerCertificate" must be of type "Certificate"
    527      subjectPublicKeyInfo = parameters.issuerCertificate.subjectPublicKeyInfo;
    528 
    529      // The CRL issuer name and "issuerCertificate" subject name are not equal
    530      if (!this.issuer.isEqual(parameters.issuerCertificate.subject)) {
    531        return false;
    532      }
    533    }
    534 
    535    //#region In case if there is only public key during verification
    536    if (parameters.publicKeyInfo) {
    537      subjectPublicKeyInfo = parameters.publicKeyInfo; // Must be of type "PublicKeyInfo"
    538    }
    539    //#endregion
    540 
    541    if (!subjectPublicKeyInfo) {
    542      throw new Error("Issuer's certificate must be provided as an input parameter");
    543    }
    544    //#endregion
    545 
    546    //#region Check the CRL for unknown critical extensions
    547    if (this.crlExtensions) {
    548      for (const extension of this.crlExtensions.extensions) {
    549        if (extension.critical) {
    550          // We can not be sure that unknown extension has no value for CRL signature
    551          if (!WELL_KNOWN_EXTENSIONS.includes(extension.extnID))
    552            return false;
    553        }
    554      }
    555    }
    556    //#endregion
    557 
    558    return crypto.verifyWithPublicKey(this.tbsView as BufferSource, this.signatureValue, subjectPublicKeyInfo, this.signatureAlgorithm);
    559  }
    560 
    561 }