Request.ts (5842B)
1 import * as asn1js from "asn1js"; 2 import * as pvutils from "pvutils"; 3 import { CertID, CertIDJson, CertIDSchema } from "./CertID"; 4 import { EMPTY_STRING } from "./constants"; 5 import { AsnError } from "./errors"; 6 import { Extension, ExtensionJson } from "./Extension"; 7 import { Extensions, ExtensionsSchema } from "./Extensions"; 8 import { PkiObject, PkiObjectParameters } from "./PkiObject"; 9 import * as Schema from "./Schema"; 10 11 const REQ_CERT = "reqCert"; 12 const SINGLE_REQUEST_EXTENSIONS = "singleRequestExtensions"; 13 const CLEAR_PROPS = [ 14 REQ_CERT, 15 SINGLE_REQUEST_EXTENSIONS, 16 ]; 17 18 export interface IRequest { 19 reqCert: CertID; 20 singleRequestExtensions?: Extension[]; 21 } 22 23 export interface RequestJson { 24 reqCert: CertIDJson; 25 singleRequestExtensions?: ExtensionJson[]; 26 } 27 28 export type RequestParameters = PkiObjectParameters & Partial<IRequest>; 29 30 export type RequestSchema = Schema.SchemaParameters<{ 31 reqCert?: CertIDSchema; 32 extensions?: ExtensionsSchema; 33 singleRequestExtensions?: string; 34 }>; 35 36 /** 37 * Represents an Request described in [RFC6960](https://datatracker.ietf.org/doc/html/rfc6960) 38 */ 39 export class Request extends PkiObject implements IRequest { 40 41 public static override CLASS_NAME = "Request"; 42 43 public reqCert!: CertID; 44 public singleRequestExtensions?: Extension[]; 45 46 /** 47 * Initializes a new instance of the {@link Request} class 48 * @param parameters Initialization parameters 49 */ 50 constructor(parameters: RequestParameters = {}) { 51 super(); 52 53 this.reqCert = pvutils.getParametersValue(parameters, REQ_CERT, Request.defaultValues(REQ_CERT)); 54 if (SINGLE_REQUEST_EXTENSIONS in parameters) { 55 this.singleRequestExtensions = pvutils.getParametersValue(parameters, SINGLE_REQUEST_EXTENSIONS, Request.defaultValues(SINGLE_REQUEST_EXTENSIONS)); 56 } 57 58 if (parameters.schema) { 59 this.fromSchema(parameters.schema); 60 } 61 } 62 63 /** 64 * Returns default values for all class members 65 * @param memberName String name for a class member 66 * @returns Default value 67 */ 68 public static override defaultValues(memberName: typeof REQ_CERT): CertID; 69 public static override defaultValues(memberName: typeof SINGLE_REQUEST_EXTENSIONS): Extension[]; 70 public static override defaultValues(memberName: string): any { 71 switch (memberName) { 72 case REQ_CERT: 73 return new CertID(); 74 case SINGLE_REQUEST_EXTENSIONS: 75 return []; 76 default: 77 return super.defaultValues(memberName); 78 } 79 } 80 81 /** 82 * Compare values with default values for all class members 83 * @param memberName String name for a class member 84 * @param memberValue Value to compare with default value 85 */ 86 public static compareWithDefault(memberName: string, memberValue: any): boolean { 87 switch (memberName) { 88 case REQ_CERT: 89 return (memberValue.isEqual(Request.defaultValues(memberName))); 90 case SINGLE_REQUEST_EXTENSIONS: 91 return (memberValue.length === 0); 92 default: 93 return super.defaultValues(memberName); 94 } 95 } 96 97 /** 98 * @inheritdoc 99 * @asn ASN.1 schema 100 * ```asn 101 * Request ::= SEQUENCE { 102 * reqCert CertID, 103 * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } 104 *``` 105 */ 106 public static override schema(parameters: RequestSchema = {}): Schema.SchemaType { 107 const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); 108 109 return (new asn1js.Sequence({ 110 name: (names.blockName || EMPTY_STRING), 111 value: [ 112 CertID.schema(names.reqCert || {}), 113 new asn1js.Constructed({ 114 optional: true, 115 idBlock: { 116 tagClass: 3, // CONTEXT-SPECIFIC 117 tagNumber: 0 // [0] 118 }, 119 value: [Extensions.schema(names.extensions || { 120 names: { 121 blockName: (names.singleRequestExtensions || EMPTY_STRING) 122 } 123 })] 124 }) 125 ] 126 })); 127 } 128 129 public fromSchema(schema: Schema.SchemaType): void { 130 // Clear input data first 131 pvutils.clearProps(schema, CLEAR_PROPS); 132 133 // Check the schema is valid 134 const asn1 = asn1js.compareSchema(schema, 135 schema, 136 Request.schema({ 137 names: { 138 reqCert: { 139 names: { 140 blockName: REQ_CERT 141 } 142 }, 143 extensions: { 144 names: { 145 blockName: SINGLE_REQUEST_EXTENSIONS 146 } 147 } 148 } 149 }) 150 ); 151 AsnError.assertSchema(asn1, this.className); 152 153 // Get internal properties from parsed schema 154 this.reqCert = new CertID({ schema: asn1.result.reqCert }); 155 if (SINGLE_REQUEST_EXTENSIONS in asn1.result) { 156 this.singleRequestExtensions = Array.from(asn1.result.singleRequestExtensions.valueBlock.value, element => new Extension({ schema: element })); 157 } 158 } 159 160 public toSchema(): asn1js.Sequence { 161 //#region Create array for output sequence 162 const outputArray = []; 163 164 outputArray.push(this.reqCert.toSchema()); 165 166 if (this.singleRequestExtensions) { 167 outputArray.push(new asn1js.Constructed({ 168 optional: true, 169 idBlock: { 170 tagClass: 3, // CONTEXT-SPECIFIC 171 tagNumber: 0 // [0] 172 }, 173 value: [ 174 new asn1js.Sequence({ 175 value: Array.from(this.singleRequestExtensions, o => o.toSchema()) 176 }) 177 ] 178 })); 179 } 180 //#endregion 181 182 //#region Construct and return new ASN.1 schema for this object 183 return (new asn1js.Sequence({ 184 value: outputArray 185 })); 186 //#endregion 187 } 188 189 public toJSON(): RequestJson { 190 const res: RequestJson = { 191 reqCert: this.reqCert.toJSON() 192 }; 193 194 if (this.singleRequestExtensions) { 195 res.singleRequestExtensions = Array.from(this.singleRequestExtensions, o => o.toJSON()); 196 } 197 198 return res; 199 } 200 201 }