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