summaryrefslogtreecommitdiffstats
path: root/third_party/js/PKI.js/src/PublicKeyInfo.ts
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/js/PKI.js/src/PublicKeyInfo.ts
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/js/PKI.js/src/PublicKeyInfo.ts')
-rw-r--r--third_party/js/PKI.js/src/PublicKeyInfo.ts274
1 files changed, 274 insertions, 0 deletions
diff --git a/third_party/js/PKI.js/src/PublicKeyInfo.ts b/third_party/js/PKI.js/src/PublicKeyInfo.ts
new file mode 100644
index 0000000000..468668bd64
--- /dev/null
+++ b/third_party/js/PKI.js/src/PublicKeyInfo.ts
@@ -0,0 +1,274 @@
+import * as asn1js from "asn1js";
+import * as pvutils from "pvutils";
+import * as common from "./common";
+import { AlgorithmIdentifier, AlgorithmIdentifierJson, AlgorithmIdentifierSchema } from "./AlgorithmIdentifier";
+import { ECPublicKey } from "./ECPublicKey";
+import { RSAPublicKey } from "./RSAPublicKey";
+import * as Schema from "./Schema";
+import { PkiObject, PkiObjectParameters } from "./PkiObject";
+import { AsnError } from "./errors";
+import { EMPTY_STRING } from "./constants";
+
+const ALGORITHM = "algorithm";
+const SUBJECT_PUBLIC_KEY = "subjectPublicKey";
+const CLEAR_PROPS = [ALGORITHM, SUBJECT_PUBLIC_KEY];
+
+export interface IPublicKeyInfo {
+ /**
+ * Algorithm identifier
+ */
+ algorithm: AlgorithmIdentifier;
+ /**
+ * Subject public key value
+ */
+ subjectPublicKey: asn1js.BitString;
+ /**
+ * Parsed public key value
+ */
+ parsedKey?: ECPublicKey | RSAPublicKey;
+}
+export type PublicKeyInfoParameters = PkiObjectParameters & Partial<IPublicKeyInfo> & { json?: JsonWebKey; };
+
+export interface PublicKeyInfoJson {
+ algorithm: AlgorithmIdentifierJson;
+ subjectPublicKey: asn1js.BitStringJson;
+}
+
+export type PublicKeyInfoSchema = Schema.SchemaParameters<{
+ algorithm?: AlgorithmIdentifierSchema;
+ subjectPublicKey?: string;
+}>;
+
+/**
+ * Represents the PublicKeyInfo structure described in [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)
+ */
+export class PublicKeyInfo extends PkiObject implements IPublicKeyInfo {
+
+ public static override CLASS_NAME = "PublicKeyInfo";
+
+ public algorithm!: AlgorithmIdentifier;
+ public subjectPublicKey!: asn1js.BitString;
+ private _parsedKey?: ECPublicKey | RSAPublicKey | null;
+ public get parsedKey(): ECPublicKey | RSAPublicKey | undefined {
+ if (this._parsedKey === undefined) {
+ switch (this.algorithm.algorithmId) {
+ // TODO Use fabric
+ case "1.2.840.10045.2.1": // ECDSA
+ if ("algorithmParams" in this.algorithm) {
+ if (this.algorithm.algorithmParams.constructor.blockName() === asn1js.ObjectIdentifier.blockName()) {
+ try {
+ this._parsedKey = new ECPublicKey({
+ namedCurve: this.algorithm.algorithmParams.valueBlock.toString(),
+ schema: this.subjectPublicKey.valueBlock.valueHexView
+ });
+ }
+ catch (ex) {
+ // nothing
+ } // Could be a problems during recognition of internal public key data here. Let's ignore them.
+ }
+ }
+ break;
+ case "1.2.840.113549.1.1.1": // RSA
+ {
+ const publicKeyASN1 = asn1js.fromBER(this.subjectPublicKey.valueBlock.valueHexView);
+ if (publicKeyASN1.offset !== -1) {
+ try {
+ this._parsedKey = new RSAPublicKey({ schema: publicKeyASN1.result });
+ }
+ catch (ex) {
+ // nothing
+ } // Could be a problems during recognition of internal public key data here. Let's ignore them.
+ }
+ }
+ break;
+ default:
+ }
+
+ this._parsedKey ||= null;
+ }
+
+ return this._parsedKey || undefined;
+ }
+ public set parsedKey(value: ECPublicKey | RSAPublicKey | undefined) {
+ this._parsedKey = value;
+ }
+
+ /**
+ * Initializes a new instance of the {@link PublicKeyInfo} class
+ * @param parameters Initialization parameters
+ */
+ constructor(parameters: PublicKeyInfoParameters = {}) {
+ super();
+
+ this.algorithm = pvutils.getParametersValue(parameters, ALGORITHM, PublicKeyInfo.defaultValues(ALGORITHM));
+ this.subjectPublicKey = pvutils.getParametersValue(parameters, SUBJECT_PUBLIC_KEY, PublicKeyInfo.defaultValues(SUBJECT_PUBLIC_KEY));
+ const parsedKey = pvutils.getParametersValue(parameters, "parsedKey", null);
+ if (parsedKey) {
+ this.parsedKey = parsedKey;
+ }
+
+ if (parameters.json) {
+ this.fromJSON(parameters.json);
+ }
+
+ 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 ALGORITHM): AlgorithmIdentifier;
+ public static override defaultValues(memberName: typeof SUBJECT_PUBLIC_KEY): asn1js.BitString;
+ public static override defaultValues(memberName: string): any {
+ switch (memberName) {
+ case ALGORITHM:
+ return new AlgorithmIdentifier();
+ case SUBJECT_PUBLIC_KEY:
+ return new asn1js.BitString();
+ default:
+ return super.defaultValues(memberName);
+ }
+ }
+
+ /**
+ * @inheritdoc
+ * @asn ASN.1 schema
+ * ```asn
+ * SubjectPublicKeyInfo ::= Sequence {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ *```
+ */
+ public static override schema(parameters: PublicKeyInfoSchema = {}): Schema.SchemaType {
+ const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {});
+
+ return (new asn1js.Sequence({
+ name: (names.blockName || EMPTY_STRING),
+ value: [
+ AlgorithmIdentifier.schema(names.algorithm || {}),
+ new asn1js.BitString({ name: (names.subjectPublicKey || EMPTY_STRING) })
+ ]
+ }));
+ }
+
+ public fromSchema(schema: Schema.SchemaType): void {
+ // Clear input data first
+ pvutils.clearProps(schema, CLEAR_PROPS);
+
+ // Check the schema is valid
+ const asn1 = asn1js.compareSchema(schema,
+ schema,
+ PublicKeyInfo.schema({
+ names: {
+ algorithm: {
+ names: {
+ blockName: ALGORITHM
+ }
+ },
+ subjectPublicKey: SUBJECT_PUBLIC_KEY
+ }
+ })
+ );
+ AsnError.assertSchema(asn1, this.className);
+
+ //#region Get internal properties from parsed schema
+ this.algorithm = new AlgorithmIdentifier({ schema: asn1.result.algorithm });
+ this.subjectPublicKey = asn1.result.subjectPublicKey;
+ //#endregion
+ }
+
+ public toSchema(): asn1js.Sequence {
+ return (new asn1js.Sequence({
+ value: [
+ this.algorithm.toSchema(),
+ this.subjectPublicKey
+ ]
+ }));
+ }
+
+ public toJSON(): PublicKeyInfoJson | JsonWebKey {
+ //#region Return common value in case we do not have enough info fo making JWK
+ if (!this.parsedKey) {
+ return {
+ algorithm: this.algorithm.toJSON(),
+ subjectPublicKey: this.subjectPublicKey.toJSON(),
+ };
+ }
+ //#endregion
+
+ //#region Making JWK
+ const jwk: JsonWebKey = {};
+
+ switch (this.algorithm.algorithmId) {
+ case "1.2.840.10045.2.1": // ECDSA
+ jwk.kty = "EC";
+ break;
+ case "1.2.840.113549.1.1.1": // RSA
+ jwk.kty = "RSA";
+ break;
+ default:
+ }
+
+ const publicKeyJWK = this.parsedKey.toJSON();
+ Object.assign(jwk, publicKeyJWK);
+
+ return jwk;
+ //#endregion
+ }
+
+ /**
+ * Converts JSON value into current object
+ * @param json JSON object
+ */
+ public fromJSON(json: any): void {
+ if ("kty" in json) {
+ switch (json.kty.toUpperCase()) {
+ case "EC":
+ this.parsedKey = new ECPublicKey({ json });
+
+ this.algorithm = new AlgorithmIdentifier({
+ algorithmId: "1.2.840.10045.2.1",
+ algorithmParams: new asn1js.ObjectIdentifier({ value: this.parsedKey.namedCurve })
+ });
+ break;
+ case "RSA":
+ this.parsedKey = new RSAPublicKey({ json });
+
+ this.algorithm = new AlgorithmIdentifier({
+ algorithmId: "1.2.840.113549.1.1.1",
+ algorithmParams: new asn1js.Null()
+ });
+ break;
+ default:
+ throw new Error(`Invalid value for "kty" parameter: ${json.kty}`);
+ }
+
+ this.subjectPublicKey = new asn1js.BitString({ valueHex: this.parsedKey.toSchema().toBER(false) });
+ }
+ }
+
+ public async importKey(publicKey: CryptoKey, crypto = common.getCrypto(true)): Promise<void> {
+ try {
+ if (!publicKey) {
+ throw new Error("Need to provide publicKey input parameter");
+ }
+
+ const exportedKey = await crypto.exportKey("spki", publicKey);
+ const asn1 = asn1js.fromBER(exportedKey);
+ try {
+ this.fromSchema(asn1.result);
+ }
+ catch (exception) {
+ throw new Error("Error during initializing object from schema");
+ }
+ } catch (e) {
+ const message = e instanceof Error ? e.message : `${e}`;
+ throw new Error(`Error during exporting public key: ${message}`);
+ }
+ }
+
+}