summaryrefslogtreecommitdiffstats
path: root/third_party/js/PKI.js/src/GeneralName.ts
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/js/PKI.js/src/GeneralName.ts')
-rw-r--r--third_party/js/PKI.js/src/GeneralName.ts642
1 files changed, 642 insertions, 0 deletions
diff --git a/third_party/js/PKI.js/src/GeneralName.ts b/third_party/js/PKI.js/src/GeneralName.ts
new file mode 100644
index 0000000000..7deba00891
--- /dev/null
+++ b/third_party/js/PKI.js/src/GeneralName.ts
@@ -0,0 +1,642 @@
+import * as asn1js from "asn1js";
+import * as pvutils from "pvutils";
+import { EMPTY_STRING } from "./constants";
+import { AsnError } from "./errors";
+import { PkiObject, PkiObjectParameters } from "./PkiObject";
+import { RelativeDistinguishedNames } from "./RelativeDistinguishedNames";
+import * as Schema from "./Schema";
+
+export const TYPE = "type";
+export const VALUE = "value";
+
+//#region Additional asn1js schema elements existing inside GeneralName schema
+
+/**
+ * Schema for "builtInStandardAttributes" of "ORAddress"
+ * @param parameters
+ * @property names
+ * @param optional
+ * @returns
+ */
+function builtInStandardAttributes(parameters: Schema.SchemaParameters<{
+ country_name?: string;
+ administration_domain_name?: string;
+ network_address?: string;
+ terminal_identifier?: string;
+ private_domain_name?: string;
+ organization_name?: string;
+ numeric_user_identifier?: string;
+ personal_name?: string;
+ organizational_unit_names?: string;
+}> = {}, optional = false) {
+ //builtInStandardAttributes ::= Sequence {
+ // country-name CountryName OPTIONAL,
+ // administration-domain-name AdministrationDomainName OPTIONAL,
+ // network-address [0] IMPLICIT NetworkAddress OPTIONAL,
+ // terminal-identifier [1] IMPLICIT TerminalIdentifier OPTIONAL,
+ // private-domain-name [2] PrivateDomainName OPTIONAL,
+ // organization-name [3] IMPLICIT OrganizationName OPTIONAL,
+ // numeric-user-identifier [4] IMPLICIT NumericUserIdentifier OPTIONAL,
+ // personal-name [5] IMPLICIT PersonalName OPTIONAL,
+ // organizational-unit-names [6] IMPLICIT OrganizationalUnitNames OPTIONAL }
+ const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {});
+
+ return (new asn1js.Sequence({
+ optional,
+ value: [
+ new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 2, // APPLICATION-SPECIFIC
+ tagNumber: 1 // [1]
+ },
+ name: (names.country_name || EMPTY_STRING),
+ value: [
+ new asn1js.Choice({
+ value: [
+ new asn1js.NumericString(),
+ new asn1js.PrintableString()
+ ]
+ })
+ ]
+ }),
+ new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 2, // APPLICATION-SPECIFIC
+ tagNumber: 2 // [2]
+ },
+ name: (names.administration_domain_name || EMPTY_STRING),
+ value: [
+ new asn1js.Choice({
+ value: [
+ new asn1js.NumericString(),
+ new asn1js.PrintableString()
+ ]
+ })
+ ]
+ }),
+ new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+ },
+ name: (names.network_address || EMPTY_STRING),
+ isHexOnly: true
+ }),
+ new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+ },
+ name: (names.terminal_identifier || EMPTY_STRING),
+ isHexOnly: true
+ }),
+ new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+ },
+ name: (names.private_domain_name || EMPTY_STRING),
+ value: [
+ new asn1js.Choice({
+ value: [
+ new asn1js.NumericString(),
+ new asn1js.PrintableString()
+ ]
+ })
+ ]
+ }),
+ new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+ },
+ name: (names.organization_name || EMPTY_STRING),
+ isHexOnly: true
+ }),
+ new asn1js.Primitive({
+ optional: true,
+ name: (names.numeric_user_identifier || EMPTY_STRING),
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 4 // [4]
+ },
+ isHexOnly: true
+ }),
+ new asn1js.Constructed({
+ optional: true,
+ name: (names.personal_name || EMPTY_STRING),
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 5 // [5]
+ },
+ value: [
+ new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+ },
+ isHexOnly: true
+ }),
+ new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+ },
+ isHexOnly: true
+ }),
+ new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+ },
+ isHexOnly: true
+ }),
+ new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+ },
+ isHexOnly: true
+ })
+ ]
+ }),
+ new asn1js.Constructed({
+ optional: true,
+ name: (names.organizational_unit_names || EMPTY_STRING),
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 6 // [6]
+ },
+ value: [
+ new asn1js.Repeated({
+ value: new asn1js.PrintableString()
+ })
+ ]
+ })
+ ]
+ }));
+}
+
+/**
+ * Schema for "builtInDomainDefinedAttributes" of "ORAddress"
+ * @param optional
+ */
+function builtInDomainDefinedAttributes(optional = false): Schema.SchemaType {
+ return (new asn1js.Sequence({
+ optional,
+ value: [
+ new asn1js.PrintableString(),
+ new asn1js.PrintableString()
+ ]
+ }));
+}
+
+/**
+ * Schema for "builtInDomainDefinedAttributes" of "ORAddress"
+ * @param optional
+ */
+function extensionAttributes(optional = false): Schema.SchemaType {
+ return (new asn1js.Set({
+ optional,
+ value: [
+ new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+ },
+ isHexOnly: true
+ }),
+ new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+ },
+ value: [new asn1js.Any()]
+ })
+ ]
+ }));
+}
+
+//#endregion
+
+export interface IGeneralName {
+ /**
+ * value type - from a tagged value (0 for "otherName", 1 for "rfc822Name" etc.)
+ */
+ type: number;
+ /**
+ * ASN.1 object having GeneralName value (type depends on TYPE value)
+ */
+ value: any;
+}
+
+export type GeneralNameParameters = PkiObjectParameters & Partial<{ type: 1 | 2 | 6; value: string; } | { type: 0 | 3 | 4 | 7 | 8; value: any; }>;
+
+export interface GeneralNameSchema {
+ names?: {
+ blockName?: string;
+ directoryName?: object;
+ builtInStandardAttributes?: object;
+ otherName?: string;
+ rfc822Name?: string;
+ dNSName?: string;
+ x400Address?: string;
+ ediPartyName?: string;
+ uniformResourceIdentifier?: string;
+ iPAddress?: string;
+ registeredID?: string;
+ };
+}
+
+export interface GeneralNameJson {
+ type: number;
+ value: string;
+}
+
+/**
+ * Represents the GeneralName structure described in [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)
+ */
+export class GeneralName extends PkiObject implements IGeneralName {
+
+ public static override CLASS_NAME = "GeneralName";
+
+ public type!: number;
+ public value: any;
+
+ /**
+ * Initializes a new instance of the {@link GeneralName} class
+ * @param parameters Initialization parameters
+ */
+ constructor(parameters: GeneralNameParameters = {}) {
+ super();
+
+ this.type = pvutils.getParametersValue(parameters, TYPE, GeneralName.defaultValues(TYPE));
+ this.value = pvutils.getParametersValue(parameters, VALUE, GeneralName.defaultValues(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 TYPE): number;
+ public static override defaultValues(memberName: typeof VALUE): any;
+ public static override defaultValues(memberName: string): any {
+ switch (memberName) {
+ case TYPE:
+ return 9;
+ case VALUE:
+ return {};
+ default:
+ return super.defaultValues(memberName);
+ }
+ }
+
+ /**
+ * Compares 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 TYPE:
+ return (memberValue === GeneralName.defaultValues(memberName));
+ case VALUE:
+ return (Object.keys(memberValue).length === 0);
+ default:
+ return super.defaultValues(memberName);
+ }
+ }
+
+ /**
+ * @inheritdoc
+ * @asn ASN.1 schema
+ * ```asn
+ * GeneralName ::= Choice {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] value,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER }
+ *```
+ */
+ static override schema(parameters: GeneralNameSchema = {}): asn1js.Choice {
+ const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {});
+
+ return (new asn1js.Choice({
+ value: [
+ new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+ },
+ name: (names.blockName || EMPTY_STRING),
+ value: [
+ new asn1js.ObjectIdentifier(),
+ new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+ },
+ value: [new asn1js.Any()]
+ })
+ ]
+ }),
+ new asn1js.Primitive({
+ name: (names.blockName || EMPTY_STRING),
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+ }
+ }),
+ new asn1js.Primitive({
+ name: (names.blockName || EMPTY_STRING),
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+ }
+ }),
+ new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+ },
+ name: (names.blockName || EMPTY_STRING),
+ value: [
+ builtInStandardAttributes((names.builtInStandardAttributes || {}), false),
+ builtInDomainDefinedAttributes(true),
+ extensionAttributes(true)
+ ]
+ }),
+ new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 4 // [4]
+ },
+ name: (names.blockName || EMPTY_STRING),
+ value: [RelativeDistinguishedNames.schema(names.directoryName || {})]
+ }),
+ new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 5 // [5]
+ },
+ name: (names.blockName || EMPTY_STRING),
+ value: [
+ new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+ },
+ value: [
+ new asn1js.Choice({
+ value: [
+ new asn1js.TeletexString(),
+ new asn1js.PrintableString(),
+ new asn1js.UniversalString(),
+ new asn1js.Utf8String(),
+ new asn1js.BmpString()
+ ]
+ })
+ ]
+ }),
+ new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+ },
+ value: [
+ new asn1js.Choice({
+ value: [
+ new asn1js.TeletexString(),
+ new asn1js.PrintableString(),
+ new asn1js.UniversalString(),
+ new asn1js.Utf8String(),
+ new asn1js.BmpString()
+ ]
+ })
+ ]
+ })
+ ]
+ }),
+ new asn1js.Primitive({
+ name: (names.blockName || EMPTY_STRING),
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 6 // [6]
+ }
+ }),
+ new asn1js.Primitive({
+ name: (names.blockName || EMPTY_STRING),
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 7 // [7]
+ }
+ }),
+ new asn1js.Primitive({
+ name: (names.blockName || EMPTY_STRING),
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 8 // [8]
+ }
+ })
+ ]
+ }));
+ }
+
+ public fromSchema(schema: Schema.SchemaType): void {
+ //#region Clear input data first
+ pvutils.clearProps(schema, [
+ "blockName",
+ "otherName",
+ "rfc822Name",
+ "dNSName",
+ "x400Address",
+ "directoryName",
+ "ediPartyName",
+ "uniformResourceIdentifier",
+ "iPAddress",
+ "registeredID"
+ ]);
+ //#endregion
+
+ //#region Check the schema is valid
+ const asn1 = asn1js.compareSchema(schema,
+ schema,
+ GeneralName.schema({
+ names: {
+ blockName: "blockName",
+ otherName: "otherName",
+ rfc822Name: "rfc822Name",
+ dNSName: "dNSName",
+ x400Address: "x400Address",
+ directoryName: {
+ names: {
+ blockName: "directoryName"
+ }
+ },
+ ediPartyName: "ediPartyName",
+ uniformResourceIdentifier: "uniformResourceIdentifier",
+ iPAddress: "iPAddress",
+ registeredID: "registeredID"
+ }
+ })
+ );
+
+ AsnError.assertSchema(asn1, this.className);
+ //#endregion
+
+ //#region Get internal properties from parsed schema
+ this.type = asn1.result.blockName.idBlock.tagNumber;
+
+ switch (this.type) {
+ case 0: // otherName
+ this.value = asn1.result.blockName;
+ break;
+ case 1: // rfc822Name + dNSName + uniformResourceIdentifier
+ case 2:
+ case 6:
+ {
+ const value = asn1.result.blockName;
+
+ value.idBlock.tagClass = 1; // UNIVERSAL
+ value.idBlock.tagNumber = 22; // IA5STRING
+
+ const valueBER = value.toBER(false);
+
+ const asnValue = asn1js.fromBER(valueBER);
+ AsnError.assert(asnValue, "GeneralName value");
+
+ this.value = (asnValue.result as asn1js.BaseStringBlock).valueBlock.value;
+ }
+ break;
+ case 3: // x400Address
+ this.value = asn1.result.blockName;
+ break;
+ case 4: // directoryName
+ this.value = new RelativeDistinguishedNames({ schema: asn1.result.directoryName });
+ break;
+ case 5: // ediPartyName
+ this.value = asn1.result.ediPartyName;
+ break;
+ case 7: // iPAddress
+ this.value = new asn1js.OctetString({ valueHex: asn1.result.blockName.valueBlock.valueHex });
+ break;
+ case 8: // registeredID
+ {
+ const value = asn1.result.blockName;
+
+ value.idBlock.tagClass = 1; // UNIVERSAL
+ value.idBlock.tagNumber = 6; // ObjectIdentifier
+
+ const valueBER = value.toBER(false);
+
+ const asnValue = asn1js.fromBER(valueBER);
+ AsnError.assert(asnValue, "GeneralName registeredID");
+ this.value = asnValue.result.valueBlock.toString(); // Getting a string representation of the ObjectIdentifier
+ }
+ break;
+ default:
+ }
+ //#endregion
+ }
+
+ public toSchema(): asn1js.Constructed | asn1js.IA5String | asn1js.ObjectIdentifier | asn1js.Choice {
+ //#region Construct and return new ASN.1 schema for this object
+ switch (this.type) {
+ case 0:
+ case 3:
+ case 5:
+ return new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: this.type
+ },
+ value: [
+ this.value
+ ]
+ });
+ case 1:
+ case 2:
+ case 6:
+ {
+ const value = new asn1js.IA5String({ value: this.value });
+
+ value.idBlock.tagClass = 3;
+ value.idBlock.tagNumber = this.type;
+
+ return value;
+ }
+ case 4:
+ return new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3, // CONTEXT-SPECIFIC
+ tagNumber: 4
+ },
+ value: [this.value.toSchema()]
+ });
+ case 7:
+ {
+ const value = this.value;
+
+ value.idBlock.tagClass = 3;
+ value.idBlock.tagNumber = this.type;
+
+ return value;
+ }
+ case 8:
+ {
+ const value = new asn1js.ObjectIdentifier({ value: this.value });
+
+ value.idBlock.tagClass = 3;
+ value.idBlock.tagNumber = this.type;
+
+ return value;
+ }
+ default:
+ return GeneralName.schema();
+ }
+ //#endregion
+ }
+
+ public toJSON(): GeneralNameJson {
+ const _object = {
+ type: this.type,
+ value: EMPTY_STRING
+ } as GeneralNameJson;
+
+ if ((typeof this.value) === "string")
+ _object.value = this.value;
+ else {
+ try {
+ _object.value = this.value.toJSON();
+ }
+ catch (ex) {
+ // nothing
+ }
+ }
+
+ return _object;
+ }
+
+}