KEKRecipientInfo.ts (7498B)
1 import * as asn1js from "asn1js"; 2 import * as pvutils from "pvutils"; 3 import { KEKIdentifier, KEKIdentifierJson, KEKIdentifierSchema } from "./KEKIdentifier"; 4 import { AlgorithmIdentifier, AlgorithmIdentifierJson, AlgorithmIdentifierSchema } from "./AlgorithmIdentifier"; 5 import * as Schema from "./Schema"; 6 import { PkiObject, PkiObjectParameters } from "./PkiObject"; 7 import { AsnError } from "./errors"; 8 import { EMPTY_BUFFER, EMPTY_STRING } from "./constants"; 9 10 const VERSION = "version"; 11 const KEK_ID = "kekid"; 12 const KEY_ENCRYPTION_ALGORITHM = "keyEncryptionAlgorithm"; 13 const ENCRYPTED_KEY = "encryptedKey"; 14 const PER_DEFINED_KEK = "preDefinedKEK"; 15 const CLEAR_PROPS = [ 16 VERSION, 17 KEK_ID, 18 KEY_ENCRYPTION_ALGORITHM, 19 ENCRYPTED_KEY, 20 ]; 21 22 export interface IKEKRecipientInfo { 23 version: number; 24 kekid: KEKIdentifier; 25 keyEncryptionAlgorithm: AlgorithmIdentifier; 26 encryptedKey: asn1js.OctetString; 27 preDefinedKEK: ArrayBuffer; 28 } 29 30 export interface KEKRecipientInfoJson { 31 version: number; 32 kekid: KEKIdentifierJson; 33 keyEncryptionAlgorithm: AlgorithmIdentifierJson; 34 encryptedKey: asn1js.OctetStringJson; 35 } 36 37 export type KEKRecipientInfoParameters = PkiObjectParameters & Partial<IKEKRecipientInfo>; 38 39 /** 40 * Represents the KEKRecipientInfo structure described in [RFC5652](https://datatracker.ietf.org/doc/html/rfc5652) 41 */ 42 export class KEKRecipientInfo extends PkiObject implements IKEKRecipientInfo { 43 44 public static override CLASS_NAME = "KEKRecipientInfo"; 45 46 public version!: number; 47 public kekid!: KEKIdentifier; 48 public keyEncryptionAlgorithm!: AlgorithmIdentifier; 49 public encryptedKey!: asn1js.OctetString; 50 public preDefinedKEK!: ArrayBuffer; 51 52 /** 53 * Initializes a new instance of the {@link KEKRecipientInfo} class 54 * @param parameters Initialization parameters 55 */ 56 constructor(parameters: KEKRecipientInfoParameters = {}) { 57 super(); 58 59 this.version = pvutils.getParametersValue(parameters, VERSION, KEKRecipientInfo.defaultValues(VERSION)); 60 this.kekid = pvutils.getParametersValue(parameters, KEK_ID, KEKRecipientInfo.defaultValues(KEK_ID)); 61 this.keyEncryptionAlgorithm = pvutils.getParametersValue(parameters, KEY_ENCRYPTION_ALGORITHM, KEKRecipientInfo.defaultValues(KEY_ENCRYPTION_ALGORITHM)); 62 this.encryptedKey = pvutils.getParametersValue(parameters, ENCRYPTED_KEY, KEKRecipientInfo.defaultValues(ENCRYPTED_KEY)); 63 this.preDefinedKEK = pvutils.getParametersValue(parameters, PER_DEFINED_KEK, KEKRecipientInfo.defaultValues(PER_DEFINED_KEK)); 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 VERSION): number; 76 public static override defaultValues(memberName: typeof KEK_ID): KEKIdentifier; 77 public static override defaultValues(memberName: typeof KEY_ENCRYPTION_ALGORITHM): AlgorithmIdentifier; 78 public static override defaultValues(memberName: typeof ENCRYPTED_KEY): asn1js.OctetString; 79 public static override defaultValues(memberName: typeof PER_DEFINED_KEK): ArrayBuffer; 80 public static override defaultValues(memberName: string): any { 81 switch (memberName) { 82 case VERSION: 83 return 0; 84 case KEK_ID: 85 return new KEKIdentifier(); 86 case KEY_ENCRYPTION_ALGORITHM: 87 return new AlgorithmIdentifier(); 88 case ENCRYPTED_KEY: 89 return new asn1js.OctetString(); 90 case PER_DEFINED_KEK: 91 return EMPTY_BUFFER; 92 default: 93 return super.defaultValues(memberName); 94 } 95 } 96 97 /** 98 * Compare values with default values for all class members 99 * @param memberName String name for a class member 100 * @param memberValue Value to compare with default value 101 */ 102 public static compareWithDefault(memberName: string, memberValue: any): boolean { 103 switch (memberName) { 104 case "KEKRecipientInfo": 105 return (memberValue === KEKRecipientInfo.defaultValues(VERSION)); 106 case KEK_ID: 107 return ((memberValue.compareWithDefault("keyIdentifier", memberValue.keyIdentifier)) && 108 (("date" in memberValue) === false) && 109 (("other" in memberValue) === false)); 110 case KEY_ENCRYPTION_ALGORITHM: 111 return ((memberValue.algorithmId === EMPTY_STRING) && (("algorithmParams" in memberValue) === false)); 112 case ENCRYPTED_KEY: 113 return (memberValue.isEqual(KEKRecipientInfo.defaultValues(ENCRYPTED_KEY))); 114 case PER_DEFINED_KEK: 115 return (memberValue.byteLength === 0); 116 default: 117 return super.defaultValues(memberName); 118 } 119 } 120 121 /** 122 * @inheritdoc 123 * @asn ASN.1 schema 124 * ```asn 125 * KEKRecipientInfo ::= SEQUENCE { 126 * version CMSVersion, -- always set to 4 127 * kekid KEKIdentifier, 128 * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, 129 * encryptedKey EncryptedKey } 130 *``` 131 */ 132 public static override schema(parameters: Schema.SchemaParameters<{ 133 version?: string; 134 kekid?: KEKIdentifierSchema; 135 keyEncryptionAlgorithm?: AlgorithmIdentifierSchema; 136 encryptedKey?: string; 137 }> = {}): Schema.SchemaType { 138 /** 139 * @type {Object} 140 * @property {string} [blockName] 141 * @property {string} [version] 142 * @property {string} [kekid] 143 * @property {string} [keyEncryptionAlgorithm] 144 * @property {string} [encryptedKey] 145 */ 146 const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); 147 148 return (new asn1js.Sequence({ 149 name: (names.blockName || EMPTY_STRING), 150 value: [ 151 new asn1js.Integer({ name: (names.version || EMPTY_STRING) }), 152 KEKIdentifier.schema(names.kekid || {}), 153 AlgorithmIdentifier.schema(names.keyEncryptionAlgorithm || {}), 154 new asn1js.OctetString({ name: (names.encryptedKey || EMPTY_STRING) }) 155 ] 156 })); 157 } 158 159 public fromSchema(schema: Schema.SchemaType): void { 160 // Clear input data first 161 pvutils.clearProps(schema, CLEAR_PROPS); 162 163 // Check the schema is valid 164 const asn1 = asn1js.compareSchema(schema, 165 schema, 166 KEKRecipientInfo.schema({ 167 names: { 168 version: VERSION, 169 kekid: { 170 names: { 171 blockName: KEK_ID 172 } 173 }, 174 keyEncryptionAlgorithm: { 175 names: { 176 blockName: KEY_ENCRYPTION_ALGORITHM 177 } 178 }, 179 encryptedKey: ENCRYPTED_KEY 180 } 181 }) 182 ); 183 AsnError.assertSchema(asn1, this.className); 184 185 // Get internal properties from parsed schema 186 this.version = asn1.result.version.valueBlock.valueDec; 187 this.kekid = new KEKIdentifier({ schema: asn1.result.kekid }); 188 this.keyEncryptionAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.keyEncryptionAlgorithm }); 189 this.encryptedKey = asn1.result.encryptedKey; 190 } 191 192 public toSchema(): asn1js.Sequence { 193 // Construct and return new ASN.1 schema for this object 194 return (new asn1js.Sequence({ 195 value: [ 196 new asn1js.Integer({ value: this.version }), 197 this.kekid.toSchema(), 198 this.keyEncryptionAlgorithm.toSchema(), 199 this.encryptedKey 200 ] 201 })); 202 } 203 204 public toJSON(): KEKRecipientInfoJson { 205 return { 206 version: this.version, 207 kekid: this.kekid.toJSON(), 208 keyEncryptionAlgorithm: this.keyEncryptionAlgorithm.toJSON(), 209 encryptedKey: this.encryptedKey.toJSON(), 210 }; 211 } 212 213 }