

const require_CredoError = require('../../../error/CredoError.js');
require('../../../error/index.js');
const require_KeyManagementError = require('../error/KeyManagementError.js');
const require_TypedArrayEncoder = require('../../../utils/TypedArrayEncoder.js');
const require_MultiBaseEncoder = require('../../../utils/MultiBaseEncoder.js');
const require_VarintEncoder = require('../../../utils/VarintEncoder.js');
require('../../../utils/index.js');
const require_humanDescription = require('./humanDescription.js');
const require_equals = require('./equals.js');
const require_zod = require('../../../utils/zod.js');
const require_knownJwk = require('./knownJwk.js');
const require_P256PublicJwk = require('./kty/ec/P256PublicJwk.js');
const require_P384PublicJwk = require('./kty/ec/P384PublicJwk.js');
const require_P521PublicJwk = require('./kty/ec/P521PublicJwk.js');
const require_Secp256k1PublicJwk = require('./kty/ec/Secp256k1PublicJwk.js');
const require_X25519PublicJwk = require('./kty/okp/X25519PublicJwk.js');
const require_Ed25519PublicJwk = require('./kty/okp/Ed25519PublicJwk.js');
const require_RsaPublicJwk = require('./kty/rsa/RsaPublicJwk.js');
require('./kty/index.js');
const require_legacy = require('../legacy.js');
const require_jwkThumbprint = require('./jwkThumbprint.js');

//#region src/modules/kms/jwk/PublicJwk.ts
const SupportedPublicJwks = [
	require_Ed25519PublicJwk.Ed25519PublicJwk,
	require_P256PublicJwk.P256PublicJwk,
	require_P384PublicJwk.P384PublicJwk,
	require_P521PublicJwk.P521PublicJwk,
	require_RsaPublicJwk.RsaPublicJwk,
	require_Secp256k1PublicJwk.Secp256k1PublicJwk,
	require_X25519PublicJwk.X25519PublicJwk
];
var PublicJwk = class PublicJwk {
	constructor(jwk) {
		this.jwk = jwk;
	}
	static fromUnknown(jwkJson) {
		const publicJwk = require_knownJwk.publicJwkFromPrivateJwk(require_zod.zParseWithErrorHandling(require_knownJwk.zKmsJwkPublic, jwkJson, "jwk is not a valid jwk"));
		require_knownJwk.assertJwkAsymmetric(publicJwk);
		let jwkInstance;
		if (publicJwk.kty === "RSA") jwkInstance = new require_RsaPublicJwk.RsaPublicJwk(publicJwk);
		else if (publicJwk.kty === "EC") if (publicJwk.crv === "P-256") jwkInstance = new require_P256PublicJwk.P256PublicJwk({
			...publicJwk,
			crv: publicJwk.crv
		});
		else if (publicJwk.crv === "P-384") jwkInstance = new require_P384PublicJwk.P384PublicJwk({
			...publicJwk,
			crv: publicJwk.crv
		});
		else if (publicJwk.crv === "P-521") jwkInstance = new require_P521PublicJwk.P521PublicJwk({
			...publicJwk,
			crv: publicJwk.crv
		});
		else if (publicJwk.crv === "secp256k1") jwkInstance = new require_Secp256k1PublicJwk.Secp256k1PublicJwk({
			...publicJwk,
			crv: publicJwk.crv
		});
		else throw new require_KeyManagementError.KeyManagementError(`Unsupported kty '${publicJwk.kty}' with crv '${publicJwk.crv}' for creating jwk instance`);
		else if (publicJwk.crv === "Ed25519") jwkInstance = new require_Ed25519PublicJwk.Ed25519PublicJwk({
			...publicJwk,
			crv: publicJwk.crv
		});
		else if (publicJwk.crv === "X25519") jwkInstance = new require_X25519PublicJwk.X25519PublicJwk({
			...publicJwk,
			crv: publicJwk.crv
		});
		else throw new require_KeyManagementError.KeyManagementError(`Unsupported kty '${publicJwk.kty}' for creating jwk instance`);
		return new PublicJwk(jwkInstance);
	}
	static fromPublicJwk(jwk) {
		return PublicJwk.fromUnknown(jwk);
	}
	toJson({ includeKid = true } = {}) {
		if (includeKid) return this.jwk.jwk;
		const { kid,...jwk } = this.jwk.jwk;
		return jwk;
	}
	get supportedSignatureAlgorithms() {
		return this.jwk.supportedSignatureAlgorithms ?? [];
	}
	get supportdEncryptionKeyAgreementAlgorithms() {
		return this.jwk.supportdEncryptionKeyAgreementAlgorithms ?? [];
	}
	/**
	* key type as defined in [JWA Specification](https://tools.ietf.org/html/rfc7518#section-6.1)
	*/
	get kty() {
		return this.jwk.jwk.kty;
	}
	/**
	* Get the key id for a public jwk. If the public jwk does not have
	*/
	get keyId() {
		if (this.jwk.jwk.kid) return this.jwk.jwk.kid;
		throw new require_KeyManagementError.KeyManagementError("Unable to determine keyId for jwk");
	}
	get hasKeyId() {
		return this.jwk.jwk.kid !== void 0;
	}
	set keyId(keyId) {
		this.jwk.jwk.kid = keyId;
	}
	get legacyKeyId() {
		return require_legacy.legacyKeyIdFromPublicJwk(this);
	}
	get publicKey() {
		return this.jwk.publicKey;
	}
	/**
	* Return the compressed public key. If the key type does not support compressed public keys, it will return null
	*/
	get compressedPublicKey() {
		return this.jwk.compressedPublicKey;
	}
	get JwkClass() {
		return this.jwk.constructor;
	}
	/**
	* SHA-256 jwk thumbprint
	*/
	getJwkThumbprint(hashAlgorithm = "sha-256") {
		return require_jwkThumbprint.calculateJwkThumbprint({
			jwk: this.jwk.jwk,
			hashAlgorithm
		});
	}
	/**
	* Get the signature algorithm to use with this jwk. If the jwk has an `alg` field defined
	* it will use that alg, and otherwise fall back to the first supported signature algorithm.
	*
	* If no algorithm is supported it will throw an error
	*/
	get signatureAlgorithm() {
		if (this.jwk.jwk.alg) {
			if (!this.supportedSignatureAlgorithms.includes(this.jwk.jwk.alg)) throw new require_KeyManagementError.KeyManagementError(`${require_humanDescription.getJwkHumanDescription(this.jwk.jwk)} defines alg '${this.jwk.jwk.alg}' but this alg is not supported.`);
			return this.jwk.jwk.alg;
		}
		const alg = this.supportedSignatureAlgorithms[0];
		if (!alg) throw new require_KeyManagementError.KeyManagementError(`${require_humanDescription.getJwkHumanDescription(this.jwk.jwk)} has no supported signature algorithms`);
		return alg;
	}
	static fromPublicKey(publicKey) {
		let jwkInstance;
		if (publicKey.kty === "RSA") jwkInstance = require_RsaPublicJwk.RsaPublicJwk.fromPublicKey(publicKey);
		else if (publicKey.kty === "EC") if (publicKey.crv === "P-256") jwkInstance = require_P256PublicJwk.P256PublicJwk.fromPublicKey(publicKey.publicKey);
		else if (publicKey.crv === "P-384") jwkInstance = require_P384PublicJwk.P384PublicJwk.fromPublicKey(publicKey.publicKey);
		else if (publicKey.crv === "P-521") jwkInstance = require_P521PublicJwk.P521PublicJwk.fromPublicKey(publicKey.publicKey);
		else if (publicKey.crv === "secp256k1") jwkInstance = require_Secp256k1PublicJwk.Secp256k1PublicJwk.fromPublicKey(publicKey.publicKey);
		else throw new require_KeyManagementError.KeyManagementError(`Unsupported kty '${publicKey.kty}' with crv '${publicKey.crv}' for creating jwk instance based on public key bytes`);
		else if (publicKey.crv === "X25519") jwkInstance = require_X25519PublicJwk.X25519PublicJwk.fromPublicKey(publicKey.publicKey);
		else if (publicKey.crv === "Ed25519") jwkInstance = require_Ed25519PublicJwk.Ed25519PublicJwk.fromPublicKey(publicKey.publicKey);
		else throw new require_KeyManagementError.KeyManagementError(`Unsupported kty '${publicKey.kty}' for creating jwk instance based on public key bytes`);
		return new PublicJwk(jwkInstance);
	}
	/**
	* Returns the jwk encoded a Base58 multibase encoded multicodec key
	*/
	get fingerprint() {
		const prefixBytes = require_VarintEncoder.VarintEncoder.encode(this.jwk.multicodecPrefix);
		const prefixedPublicKey = new Uint8Array([...prefixBytes, ...this.jwk.multicodec]);
		return `z${require_TypedArrayEncoder.TypedArrayEncoder.toBase58(prefixedPublicKey)}`;
	}
	/**
	* Create a jwk instance based on a Base58 multibase encoded multicodec key
	*/
	static fromFingerprint(fingerprint) {
		const { data } = require_MultiBaseEncoder.MultiBaseEncoder.decode(fingerprint);
		const [code, byteLength] = require_VarintEncoder.VarintEncoder.decode(data);
		const publicKey = data.slice(byteLength);
		const PublicJwkClass = SupportedPublicJwks.find((JwkClass) => JwkClass.multicodecPrefix === code);
		if (!PublicJwkClass) throw new require_KeyManagementError.KeyManagementError(`Unsupported multicodec public key with prefix '${code}'`);
		return new PublicJwk(PublicJwkClass.fromMulticodec(publicKey));
	}
	/**
	* Check whether this PublicJwk instance is of a specific type
	*/
	is(jwkType1, jwkType2, jwkType3) {
		return [
			jwkType1,
			jwkType2,
			jwkType3
		].filter(Boolean).some((type) => this.jwk.constructor === type);
	}
	/**
	* Convert the PublicJwk to another type.
	*
	* NOTE: only supportedf or Ed25519 to X25519 at the moment
	*/
	convertTo(type) {
		if (!this.is(require_Ed25519PublicJwk.Ed25519PublicJwk) || type !== require_X25519PublicJwk.X25519PublicJwk) throw new require_KeyManagementError.KeyManagementError("Unsupported key conversion. Only Ed25519 to X25519 is supported.");
		return PublicJwk.fromPublicJwk(this.jwk.toX25519PublicJwk());
	}
	/**
	* Check whether this jwk instance is the same as another jwk instance.
	* It does this by comparing the key types and public keys, not other fields
	* of the JWK such as keyId, use, etc..
	*/
	equals(other) {
		return require_equals.assymetricPublicJwkMatches(this.toJson(), other.toJson());
	}
	/**
	* Get human description of a jwk type. This does
	* not include the (public) key material
	*/
	get jwkTypehumanDescription() {
		return require_humanDescription.getJwkHumanDescription(this.toJson());
	}
	static supportedPublicJwkClassForSignatureAlgorithm(alg) {
		const supportedPublicJwkClass = SupportedPublicJwks.find((JwkClass) => JwkClass.supportedSignatureAlgorithms.includes(alg));
		if (!supportedPublicJwkClass) throw new require_CredoError.CredoError(`Could not determine supported public jwk class for alg '${alg}'`);
		return supportedPublicJwkClass;
	}
};

//#endregion
exports.PublicJwk = PublicJwk;