Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/js/PKI.js/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 13 kB image not shown  

Quelle  AuthenticatedSafe.ts   Sprache: unbekannt

 
Untersuchungsergebnis.ts Download desUnknown {[0] [0] [0]}zum Wurzelverzeichnis wechseln

import * as asn1js from "asn1js";
import * as pvutils from "pvutils";
import { ContentInfo, ContentInfoJson } from "./ContentInfo";
import { SafeContents } from "./SafeContents";
import { EnvelopedData } from "./EnvelopedData";
import { EncryptedData } from "./EncryptedData";
import * as Schema from "./Schema";
import { id_ContentType_Data, id_ContentType_EncryptedData, id_ContentType_EnvelopedData } from "./ObjectIdentifiers";
import { ArgumentError, AsnError, ParameterError } from "./errors";
import { PkiObject, PkiObjectParameters } from "./PkiObject";
import { EMPTY_STRING } from "./constants";
import * as common from "./common";

const SAFE_CONTENTS = "safeContents";
const PARSED_VALUE = "parsedValue";
const CONTENT_INFOS = "contentInfos";

export interface IAuthenticatedSafe {
  safeContents: ContentInfo[];
  parsedValue: any;
}

export type AuthenticatedSafeParameters = PkiObjectParameters & Partial<IAuthenticatedSafe>;

export interface AuthenticatedSafeJson {
  safeContents: ContentInfoJson[];
}

export type SafeContent = ContentInfo | EncryptedData | EnvelopedData | object;

/**
 * Represents the AuthenticatedSafe structure described in [RFC7292](https://datatracker.ietf.org/doc/html/rfc7292)
 */
export class AuthenticatedSafe extends PkiObject implements IAuthenticatedSafe {

  public static override CLASS_NAME = "AuthenticatedSafe";

  public safeContents!: ContentInfo[];
  public parsedValue: any;

  /**
   * Initializes a new instance of the {@link AuthenticatedSafe} class
   * @param parameters Initialization parameters
   */
  constructor(parameters: AuthenticatedSafeParameters = {}) {
    super();

    this.safeContents = pvutils.getParametersValue(parameters, SAFE_CONTENTS, AuthenticatedSafe.defaultValues(SAFE_CONTENTS));
    if (PARSED_VALUE in parameters) {
      this.parsedValue = pvutils.getParametersValue(parameters, PARSED_VALUE, AuthenticatedSafe.defaultValues(PARSED_VALUE));
    }

    if (parameters.schema) {
      this.fromSchema(parameters.schema);
    }
  }

  /**
   * Returns default values for all class members
   * @param memberName String name for a class member
   * @returns Default value
   */
  public static override defaultValues(memberName: typeof SAFE_CONTENTS): ContentInfo[];
  public static override defaultValues(memberName: typeof PARSED_VALUE): any;
  public static override defaultValues(memberName: string): any {
    switch (memberName) {
      case SAFE_CONTENTS:
        return [];
      case PARSED_VALUE:
        return {};
      default:
        return super.defaultValues(memberName);
    }
  }

  /**
   * Compare values with default values for all class members
   * @param memberName String name for a class member
   * @param memberValue Value to compare with default value
   */
  public static compareWithDefault(memberName: string, memberValue: any): boolean {
    switch (memberName) {
      case SAFE_CONTENTS:
        return (memberValue.length === 0);
      case PARSED_VALUE:
        return ((memberValue instanceof Object) && (Object.keys(memberValue).length === 0));
      default:
        return super.defaultValues(memberName);
    }
  }

  /**
   * @inheritdoc
   * @asn ASN.1 schema
   * ```asn
   * AuthenticatedSafe ::= SEQUENCE OF ContentInfo
   * -- Data if unencrypted
   * -- EncryptedData if password-encrypted
   * -- EnvelopedData if public key-encrypted
   *```
   */
  public static override schema(parameters: Schema.SchemaParameters<{
    contentInfos?: string;
  }> = {}): Schema.SchemaType {
    const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {});

    return (new asn1js.Sequence({
      name: (names.blockName || EMPTY_STRING),
      value: [
        new asn1js.Repeated({
          name: (names.contentInfos || EMPTY_STRING),
          value: ContentInfo.schema()
        })
      ]
    }));
  }

  public fromSchema(schema: Schema.SchemaType): void {
    // Clear input data first
    pvutils.clearProps(schema, [
      CONTENT_INFOS
    ]);

    // Check the schema is valid
    const asn1 = asn1js.compareSchema(schema,
      schema,
      AuthenticatedSafe.schema({
        names: {
          contentInfos: CONTENT_INFOS
        }
      })
    );
    AsnError.assertSchema(asn1, this.className);

    // Get internal properties from parsed schema
    this.safeContents = Array.from(asn1.result.contentInfos, element => new ContentInfo({ schema: element }));
  }

  public toSchema(): asn1js.Sequence {
    return (new asn1js.Sequence({
      value: Array.from(this.safeContents, o => o.toSchema())
    }));
  }

  public toJSON(): AuthenticatedSafeJson {
    return {
      safeContents: Array.from(this.safeContents, o => o.toJSON())
    };
  }

  public async parseInternalValues(parameters: { safeContents: SafeContent[]; }, crypto = common.getCrypto(true)): Promise<void> {
    //#region Check input data from "parameters"
    ParameterError.assert(parameters, SAFE_CONTENTS);
    ArgumentError.assert(parameters.safeContents, SAFE_CONTENTS, "Array");
    if (parameters.safeContents.length !== this.safeContents.length) {
      throw new ArgumentError("Length of \"parameters.safeContents\" must be equal to \"this.safeContents.length\"");
    }
    //#endregion

    //#region Create value for "this.parsedValue.authenticatedSafe"
    this.parsedValue = {
      safeContents: [] as any[],
    };

    for (const [index, content] of this.safeContents.entries()) {
      const safeContent = parameters.safeContents[index];
      const errorTarget = `parameters.safeContents[${index}]`;
      switch (content.contentType) {
        //#region data
        case id_ContentType_Data:
          {
            // Check that we do have OCTET STRING as "content"
            ArgumentError.assert(content.content, "this.safeContents[j].content", asn1js.OctetString);

            //#region Check we have "constructive encoding" for AuthSafe content
            const authSafeContent = content.content.getValue();
            //#endregion

            //#region Finally initialize initial values of SAFE_CONTENTS type
            this.parsedValue.safeContents.push({
              privacyMode: 0, // No privacy, clear data
              value: SafeContents.fromBER(authSafeContent)
            });
            //#endregion
          }
          break;
        //#endregion
        //#region envelopedData
        case id_ContentType_EnvelopedData:
          {
            //#region Initial variables
            const cmsEnveloped = new EnvelopedData({ schema: content.content });
            //#endregion

            //#region Check mandatory parameters
            ParameterError.assert(errorTarget, safeContent, "recipientCertificate", "recipientKey");
            const envelopedData = safeContent as any;
            const recipientCertificate = envelopedData.recipientCertificate;
            const recipientKey = envelopedData.recipientKey;
            //#endregion

            //#region Decrypt CMS EnvelopedData using first recipient information
            const decrypted = await cmsEnveloped.decrypt(0, {
              recipientCertificate,
              recipientPrivateKey: recipientKey
            }, crypto);

            this.parsedValue.safeContents.push({
              privacyMode: 2, // Public-key privacy mode
              value: SafeContents.fromBER(decrypted),
            });
            //#endregion
          }
          break;
        //#endregion
        //#region encryptedData
        case id_ContentType_EncryptedData:
          {
            //#region Initial variables
            const cmsEncrypted = new EncryptedData({ schema: content.content });
            //#endregion

            //#region Check mandatory parameters
            ParameterError.assert(errorTarget, safeContent, "password");

            const password = (safeContent as any).password;
            //#endregion

            //#region Decrypt CMS EncryptedData using password
            const decrypted = await cmsEncrypted.decrypt({
              password
            }, crypto);
            //#endregion

            //#region Initialize internal data
            this.parsedValue.safeContents.push({
              privacyMode: 1, // Password-based privacy mode
              value: SafeContents.fromBER(decrypted),
            });
            //#endregion
          }
          break;
        //#endregion
        //#region default
        default:
          throw new Error(`Unknown "contentType" for AuthenticatedSafe: " ${content.contentType}`);
        //#endregion
      }
    }
    //#endregion
  }
  public async makeInternalValues(parameters: {
    safeContents: any[];
  }, crypto = common.getCrypto(true)): Promise<this> {
    //#region Check data in PARSED_VALUE
    if (!(this.parsedValue)) {
      throw new Error("Please run \"parseValues\" first or add \"parsedValue\" manually");
    }
    ArgumentError.assert(this.parsedValue, "this.parsedValue", "object");
    ArgumentError.assert(this.parsedValue.safeContents, "this.parsedValue.safeContents", "Array");

    //#region Check input data from "parameters"
    ArgumentError.assert(parameters, "parameters", "object");
    ParameterError.assert(parameters, "safeContents");
    ArgumentError.assert(parameters.safeContents, "parameters.safeContents", "Array");
    if (parameters.safeContents.length !== this.parsedValue.safeContents.length) {
      throw new ArgumentError("Length of \"parameters.safeContents\" must be equal to \"this.parsedValue.safeContents\"");
    }
    //#endregion

    //#region Create internal values from already parsed values
    this.safeContents = [];

    for (const [index, content] of this.parsedValue.safeContents.entries()) {
      //#region Check current "content" value
      ParameterError.assert("content", content, "privacyMode", "value");
      ArgumentError.assert(content.value, "content.value", SafeContents);
      //#endregion

      switch (content.privacyMode) {
        //#region No privacy
        case 0:
          {
            const contentBuffer = content.value.toSchema().toBER(false);

            this.safeContents.push(new ContentInfo({
              contentType: "1.2.840.113549.1.7.1",
              content: new asn1js.OctetString({ valueHex: contentBuffer })
            }));
          }
          break;
        //#endregion
        //#region Privacy with password
        case 1:
          {
            //#region Initial variables
            const cmsEncrypted = new EncryptedData();

            const currentParameters = parameters.safeContents[index];
            currentParameters.contentToEncrypt = content.value.toSchema().toBER(false);
            //#endregion

            //#region Encrypt CMS EncryptedData using password
            await cmsEncrypted.encrypt(currentParameters);
            //#endregion

            //#region Store result content in CMS_CONTENT_INFO type
            this.safeContents.push(new ContentInfo({
              contentType: "1.2.840.113549.1.7.6",
              content: cmsEncrypted.toSchema()
            }));
            //#endregion
          }
          break;
        //#endregion
        //#region Privacy with public key
        case 2:
          {
            //#region Initial variables
            const cmsEnveloped = new EnvelopedData();
            const contentToEncrypt = content.value.toSchema().toBER(false);
            const safeContent = parameters.safeContents[index];
            //#endregion

            //#region Check mandatory parameters
            ParameterError.assert(`parameters.safeContents[${index}]`, safeContent, "encryptingCertificate", "encryptionAlgorithm");

            switch (true) {
              case (safeContent.encryptionAlgorithm.name.toLowerCase() === "aes-cbc"):
              case (safeContent.encryptionAlgorithm.name.toLowerCase() === "aes-gcm"):
                break;
              default:
                throw new Error(`Incorrect parameter "encryptionAlgorithm" in "parameters.safeContents[i]": ${safeContent.encryptionAlgorithm}`);
            }

            switch (true) {
              case (safeContent.encryptionAlgorithm.length === 128):
              case (safeContent.encryptionAlgorithm.length === 192):
              case (safeContent.encryptionAlgorithm.length === 256):
                break;
              default:
                throw new Error(`Incorrect parameter "encryptionAlgorithm.length" in "parameters.safeContents[i]": ${safeContent.encryptionAlgorithm.length}`);
            }
            //#endregion

            //#region Making correct "encryptionAlgorithm" variable
            const encryptionAlgorithm = safeContent.encryptionAlgorithm;
            //#endregion

            //#region Append recipient for enveloped data
            cmsEnveloped.addRecipientByCertificate(safeContent.encryptingCertificate, {}, undefined, crypto);
            //#endregion

            //#region Making encryption
            await cmsEnveloped.encrypt(encryptionAlgorithm, contentToEncrypt, crypto);

            this.safeContents.push(new ContentInfo({
              contentType: "1.2.840.113549.1.7.3",
              content: cmsEnveloped.toSchema()
            }));
            //#endregion
          }
          break;
        //#endregion
        //#region default
        default:
          throw new Error(`Incorrect value for "content.privacyMode": ${content.privacyMode}`);
        //#endregion
      }
    }
    //#endregion

    //#region Return result of the function
    return this;
    //#endregion
  }

}


[ zur Elbe Produktseite wechseln0.59Quellennavigators  ]