Extensions.ts (3511B)
1 import * as asn1js from "asn1js"; 2 import * as pvutils from "pvutils"; 3 import { EMPTY_STRING } from "./constants"; 4 import { AsnError } from "./errors"; 5 import { Extension, ExtensionJson, ExtensionSchema } from "./Extension"; 6 import { PkiObject, PkiObjectParameters } from "./PkiObject"; 7 import * as Schema from "./Schema"; 8 9 const EXTENSIONS = "extensions"; 10 const CLEAR_PROPS = [ 11 EXTENSIONS, 12 ]; 13 14 export interface IExtensions { 15 /** 16 * List of extensions 17 */ 18 extensions: Extension[]; 19 } 20 21 export type ExtensionsParameters = PkiObjectParameters & Partial<IExtensions>; 22 23 export type ExtensionsSchema = Schema.SchemaParameters<{ 24 extensions?: string; 25 extension?: ExtensionSchema; 26 }>; 27 28 export interface ExtensionsJson { 29 extensions: ExtensionJson[]; 30 } 31 32 /** 33 * Represents the Extensions structure described in [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280) 34 */ 35 export class Extensions extends PkiObject implements IExtensions { 36 37 public static override CLASS_NAME = "Extensions"; 38 39 public extensions!: Extension[]; 40 41 /** 42 * Initializes a new instance of the {@link Extensions} class 43 * @param parameters Initialization parameters 44 */ 45 constructor(parameters: ExtensionsParameters = {}) { 46 super(); 47 48 this.extensions = pvutils.getParametersValue(parameters, EXTENSIONS, Extensions.defaultValues(EXTENSIONS)); 49 50 if (parameters.schema) { 51 this.fromSchema(parameters.schema); 52 } 53 } 54 55 /** 56 * Returns default values for all class members 57 * @param memberName String name for a class member 58 * @returns Default value 59 */ 60 public static override defaultValues(memberName: typeof EXTENSIONS): Extension[]; 61 public static override defaultValues(memberName: string): any { 62 switch (memberName) { 63 case EXTENSIONS: 64 return []; 65 default: 66 return super.defaultValues(memberName); 67 } 68 } 69 70 /** 71 * @inheritdoc 72 * @asn ASN.1 schema 73 * ```asn 74 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 75 * ``` 76 * 77 * @param parameters Input parameters for the schema 78 * @param optional Flag that current schema should be optional 79 * @returns ASN.1 schema object 80 */ 81 public static override schema(parameters: ExtensionsSchema = {}, optional = false) { 82 const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); 83 84 return (new asn1js.Sequence({ 85 optional, 86 name: (names.blockName || EMPTY_STRING), 87 value: [ 88 new asn1js.Repeated({ 89 name: (names.extensions || EMPTY_STRING), 90 value: Extension.schema(names.extension || {}) 91 }) 92 ] 93 })); 94 } 95 96 public fromSchema(schema: Schema.SchemaType): void { 97 // Clear input data first 98 pvutils.clearProps(schema, CLEAR_PROPS); 99 100 // Check the schema is valid 101 const asn1 = asn1js.compareSchema(schema, 102 schema, 103 Extensions.schema({ 104 names: { 105 extensions: EXTENSIONS 106 } 107 }) 108 ); 109 AsnError.assertSchema(asn1, this.className); 110 111 // Get internal properties from parsed schema 112 this.extensions = Array.from(asn1.result.extensions, element => new Extension({ schema: element })); 113 } 114 115 public toSchema(): asn1js.Sequence { 116 //#region Construct and return new ASN.1 schema for this object 117 return (new asn1js.Sequence({ 118 value: Array.from(this.extensions, o => o.toSchema()) 119 })); 120 //#endregion 121 } 122 123 public toJSON(): ExtensionsJson { 124 return { 125 extensions: this.extensions.map(o => o.toJSON()) 126 }; 127 } 128 129 }