AlgorithmIdentifier.ts (6070B)
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 { PkiObject, PkiObjectParameters } from "./PkiObject"; 6 import * as Schema from "./Schema"; 7 8 const ALGORITHM_ID = "algorithmId"; 9 const ALGORITHM_PARAMS = "algorithmParams"; 10 const ALGORITHM = "algorithm"; 11 const PARAMS = "params"; 12 const CLEAR_PROPS = [ 13 ALGORITHM, 14 PARAMS 15 ]; 16 17 export interface IAlgorithmIdentifier { 18 /** 19 * ObjectIdentifier for algorithm (string representation) 20 */ 21 algorithmId: string; 22 /** 23 * Any algorithm parameters 24 */ 25 algorithmParams?: any; 26 } 27 28 export type AlgorithmIdentifierParameters = PkiObjectParameters & Partial<IAlgorithmIdentifier>; 29 30 /** 31 * JSON representation of {@link AlgorithmIdentifier} 32 */ 33 export interface AlgorithmIdentifierJson { 34 algorithmId: string; 35 algorithmParams?: any; 36 } 37 38 export type AlgorithmIdentifierSchema = Schema.SchemaParameters<{ 39 algorithmIdentifier?: string; 40 algorithmParams?: string; 41 }>; 42 43 /** 44 * Represents the AlgorithmIdentifier structure described in [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280) 45 */ 46 export class AlgorithmIdentifier extends PkiObject implements IAlgorithmIdentifier { 47 48 public static override CLASS_NAME = "AlgorithmIdentifier"; 49 50 public algorithmId!: string; 51 public algorithmParams?: any; 52 53 /** 54 * Initializes a new instance of the {@link AlgorithmIdentifier} class 55 * @param parameters Initialization parameters 56 */ 57 constructor(parameters: AlgorithmIdentifierParameters = {}) { 58 super(); 59 60 this.algorithmId = pvutils.getParametersValue(parameters, ALGORITHM_ID, AlgorithmIdentifier.defaultValues(ALGORITHM_ID)); 61 if (ALGORITHM_PARAMS in parameters) { 62 this.algorithmParams = pvutils.getParametersValue(parameters, ALGORITHM_PARAMS, AlgorithmIdentifier.defaultValues(ALGORITHM_PARAMS)); 63 } 64 65 if (parameters.schema) { 66 this.fromSchema(parameters.schema); 67 } 68 } 69 70 /** 71 * Returns default values for all class members 72 * @param memberName String name for a class member 73 * @returns Default value 74 */ 75 public static override defaultValues(memberName: typeof ALGORITHM_ID): string; 76 public static override defaultValues(memberName: typeof ALGORITHM_PARAMS): any; 77 public static override defaultValues(memberName: string): any { 78 switch (memberName) { 79 case ALGORITHM_ID: 80 return EMPTY_STRING; 81 case ALGORITHM_PARAMS: 82 return new asn1js.Any(); 83 default: 84 return super.defaultValues(memberName); 85 } 86 } 87 88 /** 89 * Compares values with default values for all class members 90 * @param memberName String name for a class member 91 * @param memberValue Value to compare with default value 92 */ 93 static compareWithDefault(memberName: string, memberValue: any): boolean { 94 switch (memberName) { 95 case ALGORITHM_ID: 96 return (memberValue === EMPTY_STRING); 97 case ALGORITHM_PARAMS: 98 return (memberValue instanceof asn1js.Any); 99 default: 100 return super.defaultValues(memberName); 101 } 102 } 103 104 /** 105 * @inheritdoc 106 * @asn ASN.1 schema 107 * ```asn 108 * AlgorithmIdentifier ::= Sequence { 109 * algorithm OBJECT IDENTIFIER, 110 * parameters ANY DEFINED BY algorithm OPTIONAL } 111 *``` 112 */ 113 public static override schema(parameters: AlgorithmIdentifierSchema = {}): any { 114 const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); 115 116 return (new asn1js.Sequence({ 117 name: (names.blockName || EMPTY_STRING), 118 optional: (names.optional || false), 119 value: [ 120 new asn1js.ObjectIdentifier({ name: (names.algorithmIdentifier || EMPTY_STRING) }), 121 new asn1js.Any({ name: (names.algorithmParams || EMPTY_STRING), optional: true }) 122 ] 123 })); 124 } 125 126 public fromSchema(schema: Schema.SchemaType): void { 127 // Clear input data first 128 pvutils.clearProps(schema, CLEAR_PROPS); 129 130 // Check the schema is valid 131 const asn1 = asn1js.compareSchema(schema, 132 schema, 133 AlgorithmIdentifier.schema({ 134 names: { 135 algorithmIdentifier: ALGORITHM, 136 algorithmParams: PARAMS 137 } 138 }) 139 ); 140 AsnError.assertSchema(asn1, this.className); 141 142 // Get internal properties from parsed schema 143 this.algorithmId = asn1.result.algorithm.valueBlock.toString(); 144 if (PARAMS in asn1.result) { 145 this.algorithmParams = asn1.result.params; 146 } 147 } 148 149 public toSchema(): asn1js.Sequence { 150 // Create array for output sequence 151 const outputArray = []; 152 outputArray.push(new asn1js.ObjectIdentifier({ value: this.algorithmId })); 153 if (this.algorithmParams && !(this.algorithmParams instanceof asn1js.Any)) { 154 outputArray.push(this.algorithmParams); 155 } 156 157 // Construct and return new ASN.1 schema for this object 158 return (new asn1js.Sequence({ 159 value: outputArray 160 })); 161 } 162 163 public toJSON(): AlgorithmIdentifierJson { 164 const object: AlgorithmIdentifierJson = { 165 algorithmId: this.algorithmId 166 }; 167 168 if (this.algorithmParams && !(this.algorithmParams instanceof asn1js.Any)) { 169 object.algorithmParams = this.algorithmParams.toJSON(); 170 } 171 172 return object; 173 } 174 175 /** 176 * Checks that two "AlgorithmIdentifiers" are equal 177 * @param algorithmIdentifier 178 */ 179 public isEqual(algorithmIdentifier: unknown): boolean { 180 //#region Check input type 181 if (!(algorithmIdentifier instanceof AlgorithmIdentifier)) { 182 return false; 183 } 184 //#endregion 185 186 //#region Check "algorithm_id" 187 if (this.algorithmId !== algorithmIdentifier.algorithmId) { 188 return false; 189 } 190 //#endregion 191 192 //#region Check "algorithm_params" 193 if (this.algorithmParams) { 194 if (algorithmIdentifier.algorithmParams) { 195 return JSON.stringify(this.algorithmParams) === JSON.stringify(algorithmIdentifier.algorithmParams); 196 } 197 198 return false; 199 } 200 201 if (algorithmIdentifier.algorithmParams) { 202 return false; 203 } 204 //#endregion 205 206 return true; 207 } 208 209 }