tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }