PasswordRecipientinfo.ts (8309B)
1 import * as asn1js from "asn1js"; 2 import * as pvutils from "pvutils"; 3 import { AlgorithmIdentifier, AlgorithmIdentifierJson, AlgorithmIdentifierSchema } from "./AlgorithmIdentifier"; 4 import { EMPTY_BUFFER, EMPTY_STRING } from "./constants"; 5 import { AsnError } from "./errors"; 6 import { PkiObject, PkiObjectParameters } from "./PkiObject"; 7 import * as Schema from "./Schema"; 8 9 const VERSION = "version"; 10 const KEY_DERIVATION_ALGORITHM = "keyDerivationAlgorithm"; 11 const KEY_ENCRYPTION_ALGORITHM = "keyEncryptionAlgorithm"; 12 const ENCRYPTED_KEY = "encryptedKey"; 13 const PASSWORD = "password"; 14 const CLEAR_PROPS = [ 15 VERSION, 16 KEY_DERIVATION_ALGORITHM, 17 KEY_ENCRYPTION_ALGORITHM, 18 ENCRYPTED_KEY 19 ]; 20 21 export interface IPasswordRecipientInfo { 22 version: number; 23 keyDerivationAlgorithm?: AlgorithmIdentifier; 24 keyEncryptionAlgorithm: AlgorithmIdentifier; 25 encryptedKey: asn1js.OctetString; 26 password: ArrayBuffer; 27 } 28 29 export interface PasswordRecipientInfoJson { 30 version: number; 31 keyDerivationAlgorithm?: AlgorithmIdentifierJson; 32 keyEncryptionAlgorithm: AlgorithmIdentifierJson; 33 encryptedKey: asn1js.OctetStringJson; 34 } 35 36 export type PasswordRecipientinfoParameters = PkiObjectParameters & Partial<IPasswordRecipientInfo>; 37 38 /** 39 * Represents the PasswordRecipientInfo structure described in [RFC5652](https://datatracker.ietf.org/doc/html/rfc5652) 40 */ 41 // TODO rename to PasswordRecipientInfo 42 export class PasswordRecipientinfo extends PkiObject implements IPasswordRecipientInfo { 43 44 public static override CLASS_NAME = "PasswordRecipientInfo"; 45 46 public version!: number; 47 public keyDerivationAlgorithm?: AlgorithmIdentifier; 48 public keyEncryptionAlgorithm!: AlgorithmIdentifier; 49 public encryptedKey!: asn1js.OctetString; 50 public password!: ArrayBuffer; 51 52 /** 53 * Initializes a new instance of the {@link PasswordRecipientinfo} class 54 * @param parameters Initialization parameters 55 */ 56 constructor(parameters: PasswordRecipientinfoParameters = {}) { 57 super(); 58 59 this.version = pvutils.getParametersValue(parameters, VERSION, PasswordRecipientinfo.defaultValues(VERSION)); 60 if (KEY_DERIVATION_ALGORITHM in parameters) { 61 this.keyDerivationAlgorithm = pvutils.getParametersValue(parameters, KEY_DERIVATION_ALGORITHM, PasswordRecipientinfo.defaultValues(KEY_DERIVATION_ALGORITHM)); 62 } 63 this.keyEncryptionAlgorithm = pvutils.getParametersValue(parameters, KEY_ENCRYPTION_ALGORITHM, PasswordRecipientinfo.defaultValues(KEY_ENCRYPTION_ALGORITHM)); 64 this.encryptedKey = pvutils.getParametersValue(parameters, ENCRYPTED_KEY, PasswordRecipientinfo.defaultValues(ENCRYPTED_KEY)); 65 this.password = pvutils.getParametersValue(parameters, PASSWORD, PasswordRecipientinfo.defaultValues(PASSWORD)); 66 67 if (parameters.schema) { 68 this.fromSchema(parameters.schema); 69 } 70 } 71 72 /** 73 * Returns default values for all class members 74 * @param memberName String name for a class member 75 * @returns Default value 76 */ 77 public static override defaultValues(memberName: typeof VERSION): number; 78 public static override defaultValues(memberName: typeof KEY_DERIVATION_ALGORITHM): AlgorithmIdentifier; 79 public static override defaultValues(memberName: typeof KEY_ENCRYPTION_ALGORITHM): AlgorithmIdentifier; 80 public static override defaultValues(memberName: typeof ENCRYPTED_KEY): asn1js.OctetString; 81 public static override defaultValues(memberName: typeof PASSWORD): ArrayBuffer; 82 public static override defaultValues(memberName: string): any { 83 switch (memberName) { 84 case VERSION: 85 return (-1); 86 case KEY_DERIVATION_ALGORITHM: 87 return new AlgorithmIdentifier(); 88 case KEY_ENCRYPTION_ALGORITHM: 89 return new AlgorithmIdentifier(); 90 case ENCRYPTED_KEY: 91 return new asn1js.OctetString(); 92 case PASSWORD: 93 return EMPTY_BUFFER; 94 default: 95 return super.defaultValues(memberName); 96 } 97 } 98 99 /** 100 * Compare values with default values for all class members 101 * @param memberName String name for a class member 102 * @param memberValue Value to compare with default value 103 */ 104 public static compareWithDefault(memberName: string, memberValue: any): boolean { 105 switch (memberName) { 106 case VERSION: 107 return (memberValue === (-1)); 108 case KEY_DERIVATION_ALGORITHM: 109 case KEY_ENCRYPTION_ALGORITHM: 110 return ((memberValue.algorithmId === EMPTY_STRING) && (("algorithmParams" in memberValue) === false)); 111 case ENCRYPTED_KEY: 112 return (memberValue.isEqual(PasswordRecipientinfo.defaultValues(ENCRYPTED_KEY))); 113 case PASSWORD: 114 return (memberValue.byteLength === 0); 115 default: 116 return super.defaultValues(memberName); 117 } 118 } 119 120 /** 121 * @inheritdoc 122 * @asn ASN.1 schema 123 * ```asn 124 * PasswordRecipientInfo ::= SEQUENCE { 125 * version CMSVersion, -- Always set to 0 126 * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, 127 * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, 128 * encryptedKey EncryptedKey } 129 *``` 130 */ 131 public static override schema(parameters: Schema.SchemaParameters<{ 132 version?: string; 133 keyDerivationAlgorithm?: string; 134 keyEncryptionAlgorithm?: AlgorithmIdentifierSchema; 135 encryptedKey?: string; 136 }> = {}): Schema.SchemaType { 137 const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); 138 139 return (new asn1js.Sequence({ 140 name: (names.blockName || EMPTY_STRING), 141 value: [ 142 new asn1js.Integer({ name: (names.version || EMPTY_STRING) }), 143 new asn1js.Constructed({ 144 name: (names.keyDerivationAlgorithm || EMPTY_STRING), 145 optional: true, 146 idBlock: { 147 tagClass: 3, // CONTEXT-SPECIFIC 148 tagNumber: 0 // [0] 149 }, 150 value: AlgorithmIdentifier.schema().valueBlock.value 151 }), 152 AlgorithmIdentifier.schema(names.keyEncryptionAlgorithm || {}), 153 new asn1js.OctetString({ name: (names.encryptedKey || EMPTY_STRING) }) 154 ] 155 })); 156 } 157 158 public fromSchema(schema: Schema.SchemaType): void { 159 // Clear input data first 160 pvutils.clearProps(schema, CLEAR_PROPS); 161 162 // Check the schema is valid 163 const asn1 = asn1js.compareSchema(schema, 164 schema, 165 PasswordRecipientinfo.schema({ 166 names: { 167 version: VERSION, 168 keyDerivationAlgorithm: KEY_DERIVATION_ALGORITHM, 169 keyEncryptionAlgorithm: { 170 names: { 171 blockName: KEY_ENCRYPTION_ALGORITHM 172 } 173 }, 174 encryptedKey: ENCRYPTED_KEY 175 } 176 }) 177 ); 178 AsnError.assertSchema(asn1, this.className); 179 180 // Get internal properties from parsed schema 181 this.version = asn1.result.version.valueBlock.valueDec; 182 183 if (KEY_DERIVATION_ALGORITHM in asn1.result) { 184 this.keyDerivationAlgorithm = new AlgorithmIdentifier({ 185 schema: new asn1js.Sequence({ 186 value: asn1.result.keyDerivationAlgorithm.valueBlock.value 187 }) 188 }); 189 } 190 this.keyEncryptionAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.keyEncryptionAlgorithm }); 191 this.encryptedKey = asn1.result.encryptedKey; 192 } 193 194 public toSchema(): asn1js.Sequence { 195 //#region Create output array for sequence 196 const outputArray = []; 197 198 outputArray.push(new asn1js.Integer({ value: this.version })); 199 200 if (this.keyDerivationAlgorithm) { 201 outputArray.push(new asn1js.Constructed({ 202 idBlock: { 203 tagClass: 3, // CONTEXT-SPECIFIC 204 tagNumber: 0 // [0] 205 }, 206 value: this.keyDerivationAlgorithm.toSchema().valueBlock.value 207 })); 208 } 209 210 outputArray.push(this.keyEncryptionAlgorithm.toSchema()); 211 outputArray.push(this.encryptedKey); 212 //#endregion 213 214 //#region Construct and return new ASN.1 schema for this object 215 return (new asn1js.Sequence({ 216 value: outputArray 217 })); 218 //#endregion 219 } 220 221 public toJSON(): PasswordRecipientInfoJson { 222 const res: PasswordRecipientInfoJson = { 223 version: this.version, 224 keyEncryptionAlgorithm: this.keyEncryptionAlgorithm.toJSON(), 225 encryptedKey: this.encryptedKey.toJSON(), 226 }; 227 228 if (this.keyDerivationAlgorithm) { 229 res.keyDerivationAlgorithm = this.keyDerivationAlgorithm.toJSON(); 230 } 231 232 return res; 233 } 234 235 }