/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Bytes, PrivateKey, Time, toHex } from "#general";
import {
  TestCert_PAA_NoVID_PrivateKey,
  TestCert_PAA_NoVID_PublicKey,
  TestCert_PAA_NoVID_SKID
} from "./ChipPAAuthorities.js";
import { Dac, Paa, Pai } from "./kinds/AttestationCertificates.js";
import { jsToMatterDate } from "./kinds/definitions/asn.js";
function getPaiCommonName(vendorId, productId) {
  return `node-matter Dev PAI 0x${vendorId.toString(16).toUpperCase()} ${productId === void 0 ? "no PID" : `0x${productId.toString(16).toUpperCase()}`}`;
}
function getDacCommonName(vendorId, productId) {
  return `node-matter Dev DAC 0x${vendorId.toString(16).toUpperCase()}/0x${productId.toString(16).toUpperCase()}`;
}
function getPaaCommonName() {
  return "Matter Test PAA";
}
class AttestationCertificateManager {
  paaCertId = BigInt(0);
  // We use the official PAA cert for now because else pairing with Chip tool do not work because
  // only this one is the Certificate store
  #paaKeyPair = PrivateKey(TestCert_PAA_NoVID_PrivateKey, {
    publicKey: TestCert_PAA_NoVID_PublicKey
  });
  #crypto;
  #vendorId;
  #paiKeyPair;
  #paiKeyIdentifier;
  #paaKeyIdentifier = TestCert_PAA_NoVID_SKID;
  #paiCertId = BigInt(1);
  #paiCertBytes;
  #nextCertificateId = 2;
  constructor(crypto, vendorId, paiKeyPair, paiKeyIdentifier) {
    this.#crypto = crypto;
    this.#vendorId = vendorId;
    this.#paiKeyPair = paiKeyPair;
    this.#paiKeyIdentifier = paiKeyIdentifier;
    this.#paiCertBytes = this.generatePAICert(vendorId);
  }
  static async create(crypto, vendorId) {
    const key = await crypto.createKeyPair();
    const identifier = Bytes.of(await crypto.computeHash(key.publicKey));
    return new AttestationCertificateManager(crypto, vendorId, key, identifier.slice(0, 20));
  }
  getPAICert() {
    return this.#paiCertBytes;
  }
  async getDACert(productId) {
    const dacKeyPair = await this.#crypto.createKeyPair();
    return {
      keyPair: dacKeyPair,
      dac: await this.generateDaCert(dacKeyPair.publicKey, this.#vendorId, productId)
    };
  }
  // Method unused for now because we use the official Matter Test PAA, but is functional
  // oxlint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  async generatePAACert(vendorId) {
    const now = Time.now;
    const cert = new Paa({
      serialNumber: Bytes.fromHex(toHex(this.paaCertId)),
      signatureAlgorithm: 1,
      publicKeyAlgorithm: 1,
      ellipticCurveIdentifier: 1,
      issuer: {
        commonName: getPaaCommonName(),
        vendorId
      },
      notBefore: jsToMatterDate(now, -1),
      notAfter: jsToMatterDate(now, 10),
      subject: {
        commonName: getPaaCommonName(),
        vendorId
      },
      ellipticCurvePublicKey: this.#paaKeyPair.publicKey,
      extensions: {
        basicConstraints: {
          isCa: true,
          pathLen: 1
        },
        keyUsage: {
          keyCertSign: true,
          cRLSign: true
        },
        subjectKeyIdentifier: this.#paaKeyIdentifier,
        authorityKeyIdentifier: this.#paaKeyIdentifier
      }
    });
    await cert.sign(this.#crypto, this.#paaKeyPair);
    return cert.asSignedDer();
  }
  async generatePAICert(vendorId, productId) {
    const now = Time.now;
    const cert = new Pai({
      serialNumber: Bytes.fromHex(toHex(this.#paiCertId)),
      signatureAlgorithm: 1,
      publicKeyAlgorithm: 1,
      ellipticCurveIdentifier: 1,
      issuer: {
        commonName: getPaaCommonName()
      },
      notBefore: jsToMatterDate(now, -1),
      notAfter: jsToMatterDate(now, 10),
      subject: {
        commonName: getPaiCommonName(vendorId, productId),
        vendorId,
        productId
      },
      ellipticCurvePublicKey: this.#paiKeyPair.publicKey,
      extensions: {
        basicConstraints: {
          isCa: true,
          pathLen: 0
        },
        keyUsage: {
          keyCertSign: true,
          cRLSign: true
        },
        subjectKeyIdentifier: this.#paiKeyIdentifier,
        authorityKeyIdentifier: this.#paaKeyIdentifier
      }
    });
    await cert.sign(this.#crypto, this.#paaKeyPair);
    return cert.asSignedDer();
  }
  async generateDaCert(publicKey, vendorId, productId) {
    const now = Time.now;
    const certId = this.#nextCertificateId++;
    const cert = new Dac({
      serialNumber: Bytes.fromHex(toHex(certId)),
      signatureAlgorithm: 1,
      publicKeyAlgorithm: 1,
      ellipticCurveIdentifier: 1,
      notBefore: jsToMatterDate(now, -1),
      notAfter: jsToMatterDate(now, 10),
      issuer: {
        commonName: getPaiCommonName(vendorId),
        vendorId
      },
      subject: {
        commonName: getDacCommonName(vendorId, productId),
        vendorId,
        productId
      },
      ellipticCurvePublicKey: publicKey,
      extensions: {
        basicConstraints: {
          isCa: false
        },
        keyUsage: {
          digitalSignature: true
        },
        subjectKeyIdentifier: Bytes.of(await this.#crypto.computeHash(publicKey)).slice(0, 20),
        authorityKeyIdentifier: this.#paiKeyIdentifier
      }
    });
    await cert.sign(this.#crypto, this.#paiKeyPair);
    return cert.asSignedDer();
  }
}
export {
  AttestationCertificateManager
};
//# sourceMappingURL=AttestationCertificateManager.js.map
