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