RSASSAPSSParams.ts (8951B)
1 import * as asn1js from "asn1js"; 2 import * as pvutils from "pvutils"; 3 import { AlgorithmIdentifier, AlgorithmIdentifierJson, AlgorithmIdentifierSchema } from "./AlgorithmIdentifier"; 4 import { EMPTY_STRING } from "./constants"; 5 import { AsnError } from "./errors"; 6 import { PkiObject, PkiObjectParameters } from "./PkiObject"; 7 import * as Schema from "./Schema"; 8 9 const HASH_ALGORITHM = "hashAlgorithm"; 10 const MASK_GEN_ALGORITHM = "maskGenAlgorithm"; 11 const SALT_LENGTH = "saltLength"; 12 const TRAILER_FIELD = "trailerField"; 13 const CLEAR_PROPS = [ 14 HASH_ALGORITHM, 15 MASK_GEN_ALGORITHM, 16 SALT_LENGTH, 17 TRAILER_FIELD 18 ]; 19 20 export interface IRSASSAPSSParams { 21 /** 22 * Algorithms of hashing (DEFAULT sha1) 23 */ 24 hashAlgorithm: AlgorithmIdentifier; 25 /** 26 * Salt length (DEFAULT 20) 27 */ 28 maskGenAlgorithm: AlgorithmIdentifier; 29 /** 30 * Salt length (DEFAULT 20) 31 */ 32 saltLength: number; 33 /** 34 * (DEFAULT 1) 35 */ 36 trailerField: number; 37 } 38 39 export interface RSASSAPSSParamsJson { 40 hashAlgorithm?: AlgorithmIdentifierJson; 41 maskGenAlgorithm?: AlgorithmIdentifierJson; 42 saltLength?: number; 43 trailerField?: number; 44 } 45 46 export type RSASSAPSSParamsParameters = PkiObjectParameters & Partial<IRSASSAPSSParams>; 47 48 /** 49 * Represents the RSASSAPSSParams structure described in [RFC4055](https://datatracker.ietf.org/doc/html/rfc4055) 50 */ 51 export class RSASSAPSSParams extends PkiObject implements IRSASSAPSSParams { 52 53 public static override CLASS_NAME = "RSASSAPSSParams"; 54 55 public hashAlgorithm!: AlgorithmIdentifier; 56 public maskGenAlgorithm!: AlgorithmIdentifier; 57 public saltLength!: number; 58 public trailerField!: number; 59 60 /** 61 * Initializes a new instance of the {@link RSASSAPSSParams} class 62 * @param parameters Initialization parameters 63 */ 64 constructor(parameters: RSASSAPSSParamsParameters = {}) { 65 super(); 66 67 this.hashAlgorithm = pvutils.getParametersValue(parameters, HASH_ALGORITHM, RSASSAPSSParams.defaultValues(HASH_ALGORITHM)); 68 this.maskGenAlgorithm = pvutils.getParametersValue(parameters, MASK_GEN_ALGORITHM, RSASSAPSSParams.defaultValues(MASK_GEN_ALGORITHM)); 69 this.saltLength = pvutils.getParametersValue(parameters, SALT_LENGTH, RSASSAPSSParams.defaultValues(SALT_LENGTH)); 70 this.trailerField = pvutils.getParametersValue(parameters, TRAILER_FIELD, RSASSAPSSParams.defaultValues(TRAILER_FIELD)); 71 72 if (parameters.schema) { 73 this.fromSchema(parameters.schema); 74 } 75 } 76 77 /** 78 * Returns default values for all class members 79 * @param memberName String name for a class member 80 * @returns Default value 81 */ 82 public static override defaultValues(memberName: typeof HASH_ALGORITHM): AlgorithmIdentifier; 83 public static override defaultValues(memberName: typeof MASK_GEN_ALGORITHM): AlgorithmIdentifier; 84 public static override defaultValues(memberName: typeof SALT_LENGTH): number; 85 public static override defaultValues(memberName: typeof TRAILER_FIELD): number; 86 public static override defaultValues(memberName: string): any { 87 switch (memberName) { 88 case HASH_ALGORITHM: 89 return new AlgorithmIdentifier({ 90 algorithmId: "1.3.14.3.2.26", // SHA-1 91 algorithmParams: new asn1js.Null() 92 }); 93 case MASK_GEN_ALGORITHM: 94 return new AlgorithmIdentifier({ 95 algorithmId: "1.2.840.113549.1.1.8", // MGF1 96 algorithmParams: (new AlgorithmIdentifier({ 97 algorithmId: "1.3.14.3.2.26", // SHA-1 98 algorithmParams: new asn1js.Null() 99 })).toSchema() 100 }); 101 case SALT_LENGTH: 102 return 20; 103 case TRAILER_FIELD: 104 return 1; 105 default: 106 return super.defaultValues(memberName); 107 } 108 } 109 110 /** 111 * @inheritdoc 112 * @asn ASN.1 schema 113 * ```asn 114 * RSASSA-PSS-params ::= Sequence { 115 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, 116 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, 117 * saltLength [2] Integer DEFAULT 20, 118 * trailerField [3] Integer DEFAULT 1 } 119 *``` 120 */ 121 public static override schema(parameters: Schema.SchemaParameters<{ 122 hashAlgorithm?: AlgorithmIdentifierSchema; 123 maskGenAlgorithm?: AlgorithmIdentifierSchema; 124 saltLength?: string; 125 trailerField?: string; 126 }> = {}): Schema.SchemaType { 127 const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); 128 129 return (new asn1js.Sequence({ 130 name: (names.blockName || EMPTY_STRING), 131 value: [ 132 new asn1js.Constructed({ 133 idBlock: { 134 tagClass: 3, // CONTEXT-SPECIFIC 135 tagNumber: 0 // [0] 136 }, 137 optional: true, 138 value: [AlgorithmIdentifier.schema(names.hashAlgorithm || {})] 139 }), 140 new asn1js.Constructed({ 141 idBlock: { 142 tagClass: 3, // CONTEXT-SPECIFIC 143 tagNumber: 1 // [1] 144 }, 145 optional: true, 146 value: [AlgorithmIdentifier.schema(names.maskGenAlgorithm || {})] 147 }), 148 new asn1js.Constructed({ 149 idBlock: { 150 tagClass: 3, // CONTEXT-SPECIFIC 151 tagNumber: 2 // [2] 152 }, 153 optional: true, 154 value: [new asn1js.Integer({ name: (names.saltLength || EMPTY_STRING) })] 155 }), 156 new asn1js.Constructed({ 157 idBlock: { 158 tagClass: 3, // CONTEXT-SPECIFIC 159 tagNumber: 3 // [3] 160 }, 161 optional: true, 162 value: [new asn1js.Integer({ name: (names.trailerField || EMPTY_STRING) })] 163 }) 164 ] 165 })); 166 } 167 168 public fromSchema(schema: Schema.SchemaType): void { 169 // Clear input data first 170 pvutils.clearProps(schema, CLEAR_PROPS); 171 172 // Check the schema is valid 173 const asn1 = asn1js.compareSchema(schema, 174 schema, 175 RSASSAPSSParams.schema({ 176 names: { 177 hashAlgorithm: { 178 names: { 179 blockName: HASH_ALGORITHM 180 } 181 }, 182 maskGenAlgorithm: { 183 names: { 184 blockName: MASK_GEN_ALGORITHM 185 } 186 }, 187 saltLength: SALT_LENGTH, 188 trailerField: TRAILER_FIELD 189 } 190 }) 191 ); 192 AsnError.assertSchema(asn1, this.className); 193 194 // Get internal properties from parsed schema 195 if (HASH_ALGORITHM in asn1.result) 196 this.hashAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.hashAlgorithm }); 197 198 if (MASK_GEN_ALGORITHM in asn1.result) 199 this.maskGenAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.maskGenAlgorithm }); 200 201 if (SALT_LENGTH in asn1.result) 202 this.saltLength = asn1.result.saltLength.valueBlock.valueDec; 203 204 if (TRAILER_FIELD in asn1.result) 205 this.trailerField = asn1.result.trailerField.valueBlock.valueDec; 206 } 207 208 public toSchema(): asn1js.Sequence { 209 //#region Create array for output sequence 210 const outputArray = []; 211 212 if (!this.hashAlgorithm.isEqual(RSASSAPSSParams.defaultValues(HASH_ALGORITHM))) { 213 outputArray.push(new asn1js.Constructed({ 214 idBlock: { 215 tagClass: 3, // CONTEXT-SPECIFIC 216 tagNumber: 0 // [0] 217 }, 218 value: [this.hashAlgorithm.toSchema()] 219 })); 220 } 221 222 if (!this.maskGenAlgorithm.isEqual(RSASSAPSSParams.defaultValues(MASK_GEN_ALGORITHM))) { 223 outputArray.push(new asn1js.Constructed({ 224 idBlock: { 225 tagClass: 3, // CONTEXT-SPECIFIC 226 tagNumber: 1 // [1] 227 }, 228 value: [this.maskGenAlgorithm.toSchema()] 229 })); 230 } 231 232 if (this.saltLength !== RSASSAPSSParams.defaultValues(SALT_LENGTH)) { 233 outputArray.push(new asn1js.Constructed({ 234 idBlock: { 235 tagClass: 3, // CONTEXT-SPECIFIC 236 tagNumber: 2 // [2] 237 }, 238 value: [new asn1js.Integer({ value: this.saltLength })] 239 })); 240 } 241 242 if (this.trailerField !== RSASSAPSSParams.defaultValues(TRAILER_FIELD)) { 243 outputArray.push(new asn1js.Constructed({ 244 idBlock: { 245 tagClass: 3, // CONTEXT-SPECIFIC 246 tagNumber: 3 // [3] 247 }, 248 value: [new asn1js.Integer({ value: this.trailerField })] 249 })); 250 } 251 //#endregion 252 253 //#region Construct and return new ASN.1 schema for this object 254 return (new asn1js.Sequence({ 255 value: outputArray 256 })); 257 //#endregion 258 } 259 260 public toJSON(): RSASSAPSSParamsJson { 261 const res: RSASSAPSSParamsJson = {}; 262 263 if (!this.hashAlgorithm.isEqual(RSASSAPSSParams.defaultValues(HASH_ALGORITHM))) { 264 res.hashAlgorithm = this.hashAlgorithm.toJSON(); 265 } 266 267 if (!this.maskGenAlgorithm.isEqual(RSASSAPSSParams.defaultValues(MASK_GEN_ALGORITHM))) { 268 res.maskGenAlgorithm = this.maskGenAlgorithm.toJSON(); 269 } 270 271 if (this.saltLength !== RSASSAPSSParams.defaultValues(SALT_LENGTH)) { 272 res.saltLength = this.saltLength; 273 } 274 275 if (this.trailerField !== RSASSAPSSParams.defaultValues(TRAILER_FIELD)) { 276 res.trailerField = this.trailerField; 277 } 278 279 return res; 280 } 281 282 }