tor-browser

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

RecipientInfo.ts (7402B)


      1 import * as asn1js from "asn1js";
      2 import * as pvutils from "pvutils";
      3 import { KeyTransRecipientInfo, KeyTransRecipientInfoJson } from "./KeyTransRecipientInfo";
      4 import { KeyAgreeRecipientInfo, KeyAgreeRecipientInfoJson } from "./KeyAgreeRecipientInfo";
      5 import { KEKRecipientInfo, KEKRecipientInfoJson } from "./KEKRecipientInfo";
      6 import { PasswordRecipientinfo, PasswordRecipientInfoJson } from "./PasswordRecipientinfo";
      7 import { OtherRecipientInfo, OtherRecipientInfoJson } from "./OtherRecipientInfo";
      8 import * as Schema from "./Schema";
      9 import { AsnError, ParameterError } from "./errors";
     10 import { PkiObject, PkiObjectParameters } from "./PkiObject";
     11 import { EMPTY_STRING } from "./constants";
     12 
     13 const VARIANT = "variant";
     14 const VALUE = "value";
     15 const CLEAR_PROPS = [
     16  "blockName"
     17 ];
     18 
     19 export interface IRecipientInfo {
     20  variant: number;
     21  value?: RecipientInfoValue;
     22 }
     23 
     24 export interface RecipientInfoJson {
     25  variant: number;
     26  value?: RecipientInfoValueJson;
     27 }
     28 
     29 export type RecipientInfoValue = KeyTransRecipientInfo | KeyAgreeRecipientInfo | KEKRecipientInfo | PasswordRecipientinfo | OtherRecipientInfo;
     30 export type RecipientInfoValueJson = KeyTransRecipientInfoJson | KeyAgreeRecipientInfoJson | KEKRecipientInfoJson | PasswordRecipientInfoJson | OtherRecipientInfoJson;
     31 
     32 export type RecipientInfoParameters = PkiObjectParameters & Partial<IRecipientInfo>;
     33 
     34 /**
     35 * Represents the RecipientInfo structure described in [RFC5652](https://datatracker.ietf.org/doc/html/rfc5652)
     36 */
     37 export class RecipientInfo extends PkiObject implements IRecipientInfo {
     38 
     39  public static override CLASS_NAME = "RecipientInfo";
     40 
     41  public variant!: number;
     42  public value?: RecipientInfoValue;
     43 
     44  /**
     45   * Initializes a new instance of the {@link RecipientInfo} class
     46   * @param parameters Initialization parameters
     47   */
     48  constructor(parameters: RecipientInfoParameters = {}) {
     49    super();
     50 
     51    this.variant = pvutils.getParametersValue(parameters, VARIANT, RecipientInfo.defaultValues(VARIANT));
     52    if (VALUE in parameters) {
     53      this.value = pvutils.getParametersValue(parameters, VALUE, RecipientInfo.defaultValues(VALUE));
     54    }
     55 
     56    if (parameters.schema) {
     57      this.fromSchema(parameters.schema);
     58    }
     59  }
     60 
     61  /**
     62   * Returns default values for all class members
     63   * @param memberName String name for a class member
     64   * @returns Default value
     65   */
     66  public static override defaultValues(memberName: typeof VARIANT): number;
     67  public static override defaultValues(memberName: typeof VALUE): RecipientInfoValue;
     68  public static override defaultValues(memberName: string): any {
     69    switch (memberName) {
     70      case VARIANT:
     71        return (-1);
     72      case VALUE:
     73        return {};
     74      default:
     75        return super.defaultValues(memberName);
     76    }
     77  }
     78 
     79  /**
     80   * Compare values with default values for all class members
     81   * @param memberName String name for a class member
     82   * @param memberValue Value to compare with default value
     83   */
     84  public static compareWithDefault(memberName: string, memberValue: any): boolean {
     85    switch (memberName) {
     86      case VARIANT:
     87        return (memberValue === RecipientInfo.defaultValues(memberName));
     88      case VALUE:
     89        return (Object.keys(memberValue).length === 0);
     90      default:
     91        return super.defaultValues(memberName);
     92    }
     93  }
     94 
     95  /**
     96   * @inheritdoc
     97   * @asn ASN.1 schema
     98   * ```asn
     99   * RecipientInfo ::= CHOICE {
    100   *    ktri KeyTransRecipientInfo,
    101   *    kari [1] KeyAgreeRecipientInfo,
    102   *    kekri [2] KEKRecipientInfo,
    103   *    pwri [3] PasswordRecipientinfo,
    104   *    ori [4] OtherRecipientInfo }
    105   *```
    106   */
    107  public static override schema(parameters: Schema.SchemaParameters = {}): Schema.SchemaType {
    108    const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {});
    109 
    110    return (new asn1js.Choice({
    111      value: [
    112        KeyTransRecipientInfo.schema({
    113          names: {
    114            blockName: (names.blockName || EMPTY_STRING)
    115          }
    116        }),
    117        new asn1js.Constructed({
    118          name: (names.blockName || EMPTY_STRING),
    119          idBlock: {
    120            tagClass: 3, // CONTEXT-SPECIFIC
    121            tagNumber: 1 // [1]
    122          },
    123          value: KeyAgreeRecipientInfo.schema().valueBlock.value
    124        }),
    125        new asn1js.Constructed({
    126          name: (names.blockName || EMPTY_STRING),
    127          idBlock: {
    128            tagClass: 3, // CONTEXT-SPECIFIC
    129            tagNumber: 2 // [2]
    130          },
    131          value: KEKRecipientInfo.schema().valueBlock.value
    132        }),
    133        new asn1js.Constructed({
    134          name: (names.blockName || EMPTY_STRING),
    135          idBlock: {
    136            tagClass: 3, // CONTEXT-SPECIFIC
    137            tagNumber: 3 // [3]
    138          },
    139          value: PasswordRecipientinfo.schema().valueBlock.value
    140        }),
    141        new asn1js.Constructed({
    142          name: (names.blockName || EMPTY_STRING),
    143          idBlock: {
    144            tagClass: 3, // CONTEXT-SPECIFIC
    145            tagNumber: 4 // [4]
    146          },
    147          value: OtherRecipientInfo.schema().valueBlock.value
    148        })
    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      RecipientInfo.schema({
    161        names: {
    162          blockName: "blockName"
    163        }
    164      })
    165    );
    166    AsnError.assertSchema(asn1, this.className);
    167 
    168    // Get internal properties from parsed schema
    169    if (asn1.result.blockName.idBlock.tagClass === 1) {
    170      this.variant = 1;
    171      this.value = new KeyTransRecipientInfo({ schema: asn1.result.blockName });
    172    } else {
    173      // Create "SEQUENCE" from "ASN1_CONSTRUCTED"
    174      const blockSequence = new asn1js.Sequence({
    175        value: asn1.result.blockName.valueBlock.value
    176      });
    177 
    178      switch (asn1.result.blockName.idBlock.tagNumber) {
    179        case 1:
    180          this.variant = 2;
    181          this.value = new KeyAgreeRecipientInfo({ schema: blockSequence });
    182          break;
    183        case 2:
    184          this.variant = 3;
    185          this.value = new KEKRecipientInfo({ schema: blockSequence });
    186          break;
    187        case 3:
    188          this.variant = 4;
    189          this.value = new PasswordRecipientinfo({ schema: blockSequence });
    190          break;
    191        case 4:
    192          this.variant = 5;
    193          this.value = new OtherRecipientInfo({ schema: blockSequence });
    194          break;
    195        default:
    196          throw new Error("Incorrect structure of RecipientInfo block");
    197      }
    198    }
    199  }
    200 
    201  public toSchema(): asn1js.BaseBlock<any> {
    202    // Construct and return new ASN.1 schema for this object
    203    ParameterError.assertEmpty(this.value, "value", "RecipientInfo");
    204    const _schema = this.value.toSchema();
    205 
    206    switch (this.variant) {
    207      case 1:
    208        return _schema;
    209      case 2:
    210      case 3:
    211      case 4:
    212        // Create "ASN1_CONSTRUCTED" from "SEQUENCE"
    213        _schema.idBlock.tagClass = 3; // CONTEXT-SPECIFIC
    214        _schema.idBlock.tagNumber = (this.variant - 1);
    215 
    216        return _schema;
    217      default:
    218        return new asn1js.Any() as any;
    219    }
    220  }
    221 
    222  public toJSON(): RecipientInfoJson {
    223    const res: RecipientInfoJson = {
    224      variant: this.variant
    225    };
    226 
    227    if (this.value && (this.variant >= 1) && (this.variant <= 4)) {
    228      res.value = this.value.toJSON();
    229    }
    230 
    231    return res;
    232  }
    233 
    234 }