

const require_rolldown_runtime = require('../../../_virtual/rolldown_runtime.js');
const require_CredoError = require('../../../error/CredoError.js');
require('../../../error/index.js');
require('../../../plugins/index.js');
const require_decorate = require('../../../_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js');
const require_array = require('../../../utils/array.js');
const require_TypedArrayEncoder = require('../../../utils/TypedArrayEncoder.js');
const require_MessageValidator = require('../../../utils/MessageValidator.js');
const require_JsonTransformer = require('../../../utils/JsonTransformer.js');
const require_timestamp = require('../../../utils/timestamp.js');
require('../../../utils/index.js');
const require_KeyManagementApi = require('../../kms/KeyManagementApi.js');
require('../../kms/index.js');
const require_JwtPayload = require('../../../crypto/jose/jwt/JwtPayload.js');
const require_keyDidMapping = require('../../dids/domain/key-type/keyDidMapping.js');
require('../../../crypto/index.js');
const require_W3cV2SdJwt = require('./W3cV2SdJwt.js');
const require_W3cV2SdJwtVerifiableCredential = require('./W3cV2SdJwtVerifiableCredential.js');
const require_utils = require('../../sd-jwt-vc/utils.js');
const require_W3cV2SdJwtVerifiablePresentation = require('./W3cV2SdJwtVerifiablePresentation.js');
const require_v2_jwt_utils = require('../v2-jwt-utils.js');
let __sd_jwt_core = require("@sd-jwt/core");
__sd_jwt_core = require_rolldown_runtime.__toESM(__sd_jwt_core);
let tsyringe = require("tsyringe");
tsyringe = require_rolldown_runtime.__toESM(tsyringe);

//#region src/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.ts
/**
* List of fields that cannot be selectively disclosed.
*
* @see https://www.w3.org/TR/vc-jose-cose/#securing-with-sd-jwt
* @see https://www.w3.org/TR/vc-jose-cose/#securing-vps-sd-jwt
*/
const NON_DISCLOSEABLE_FIELDS = [
	"@context",
	"type",
	"credentialStatus",
	"credentialSchema",
	"relatedResource"
];
let W3cV2SdJwtCredentialService = class W3cV2SdJwtCredentialService$1 {
	/**
	* Signs a credential
	*/
	async signCredential(agentContext, options) {
		require_MessageValidator.MessageValidator.validateSync(options.credential);
		const payload = require_JsonTransformer.JsonTransformer.toJSON(options.credential);
		payload.iat = require_timestamp.nowInSeconds();
		payload.cnf = options.holder ? (await require_utils.extractKeyFromHolderBinding(agentContext, options.holder)).cnf : void 0;
		const publicJwk = await require_v2_jwt_utils.validateAndResolveVerificationMethod(agentContext, options.verificationMethod, ["assertionMethod"]);
		const disclosureFrame = options.disclosureFrame;
		this.validateDisclosureFrame(disclosureFrame);
		const compact = await new __sd_jwt_core.SDJwtInstance({
			...this.getBaseSdJwtConfig(agentContext),
			signer: require_utils.getSdJwtSigner(agentContext, publicJwk),
			hashAlg: options.hashingAlgorithm ?? "sha-256",
			signAlg: options.alg
		}).issue(payload, disclosureFrame, { header: {
			typ: "vc+sd-jwt",
			alg: options.alg,
			kid: options.verificationMethod
		} });
		return require_W3cV2SdJwtVerifiableCredential.W3cV2SdJwtVerifiableCredential.fromCompact(compact);
	}
	/**
	* Verifies the signature(s) of a credential
	*
	* @param credential the credential to be verified
	* @returns the verification result
	*/
	async verifyCredential(agentContext, options) {
		const validationResults = {
			isValid: false,
			validations: {}
		};
		const sdJwt = new __sd_jwt_core.SDJwtInstance({ ...this.getBaseSdJwtConfig(agentContext) });
		try {
			let credential;
			try {
				if (options.credential instanceof require_W3cV2SdJwtVerifiableCredential.W3cV2SdJwtVerifiableCredential) options.credential.validate();
				credential = options.credential instanceof require_W3cV2SdJwtVerifiableCredential.W3cV2SdJwtVerifiableCredential ? options.credential : require_W3cV2SdJwtVerifiableCredential.W3cV2SdJwtVerifiableCredential.fromCompact(options.credential);
				require_JwtPayload.JwtPayload.fromJson(credential.sdJwt.payload).validate();
				validationResults.validations.dataModel = { isValid: true };
			} catch (error) {
				validationResults.validations.dataModel = {
					isValid: false,
					error
				};
				return validationResults;
			}
			const issuerVerificationMethod = await require_v2_jwt_utils.getVerificationMethodForJwt(agentContext, credential, ["assertionMethod"]);
			const issuerPublicKey = require_keyDidMapping.getPublicJwkFromVerificationMethod(issuerVerificationMethod);
			const holderBinding = require_utils.parseHolderBindingFromCredential(credential.sdJwt.prettyClaims);
			const holder = holderBinding ? await require_utils.extractKeyFromHolderBinding(agentContext, holderBinding) : void 0;
			sdJwt.config({
				verifier: require_utils.getSdJwtVerifier(agentContext, issuerPublicKey),
				kbVerifier: holder ? require_utils.getSdJwtVerifier(agentContext, holder.publicJwk) : void 0
			});
			try {
				await sdJwt.verify(credential.encoded);
				validationResults.validations.signature = { isValid: true };
			} catch (error) {
				validationResults.validations.signature = {
					isValid: false,
					error
				};
			}
			if (credential.resolvedCredential.issuerId !== issuerVerificationMethod.controller) validationResults.validations.issuerIsSigner = {
				isValid: false,
				error: new require_CredoError.CredoError(`Credential is signed using verification method ${issuerVerificationMethod.id}, while the issuer of the credential is '${credential.resolvedCredential.issuerId}'`)
			};
			else validationResults.validations.issuerIsSigner = { isValid: true };
			validationResults.isValid = Object.values(validationResults.validations).every((v) => v.isValid);
			return validationResults;
		} catch (error) {
			validationResults.error = error;
			return validationResults;
		}
	}
	/**
	* Signs a presentation including the credentials it includes
	*
	* @param presentation the presentation to be signed
	* @returns the signed presentation
	*/
	async signPresentation(agentContext, options) {
		require_MessageValidator.MessageValidator.validateSync(options.presentation);
		const payload = require_JsonTransformer.JsonTransformer.toJSON(options.presentation);
		payload.nonce = options.challenge;
		payload.aud = options.domain;
		const holder = await require_v2_jwt_utils.extractHolderFromPresentationCredentials(agentContext, options.presentation);
		const sdJwt = new __sd_jwt_core.SDJwtInstance({
			...this.getBaseSdJwtConfig(agentContext),
			signer: require_utils.getSdJwtSigner(agentContext, holder.publicJwk),
			hashAlg: options.hashingAlgorithm ?? "sha-256",
			signAlg: holder.alg
		});
		const disclosureFrame = options.disclosureFrame;
		this.validateDisclosureFrame(disclosureFrame);
		const compact = await sdJwt.issue(payload, disclosureFrame, { header: {
			typ: "vp+sd-jwt",
			alg: holder.alg,
			kid: holder?.cnf?.kid
		} });
		return require_W3cV2SdJwtVerifiablePresentation.W3cV2SdJwtVerifiablePresentation.fromCompact(compact);
	}
	/**
	* Verifies a presentation including the credentials it includes
	*
	* @param presentation the presentation to be verified
	* @returns the verification result
	*/
	async verifyPresentation(agentContext, options) {
		const validationResults = {
			isValid: false,
			validations: {}
		};
		const sdjwt = new __sd_jwt_core.SDJwtInstance({ ...this.getBaseSdJwtConfig(agentContext) });
		try {
			let presentation;
			try {
				if (options.presentation instanceof require_W3cV2SdJwtVerifiablePresentation.W3cV2SdJwtVerifiablePresentation) require_MessageValidator.MessageValidator.validateSync(options.presentation.resolvedPresentation);
				presentation = options.presentation instanceof require_W3cV2SdJwtVerifiablePresentation.W3cV2SdJwtVerifiablePresentation ? options.presentation : require_W3cV2SdJwtVerifiablePresentation.W3cV2SdJwtVerifiablePresentation.fromCompact(options.presentation);
				require_JwtPayload.JwtPayload.fromJson(presentation.sdJwt.payload).validate();
				validationResults.validations.dataModel = { isValid: true };
			} catch (error) {
				validationResults.validations.dataModel = {
					isValid: false,
					error
				};
				return validationResults;
			}
			const proverVerificationMethod = await require_v2_jwt_utils.getVerificationMethodForJwt(agentContext, presentation, ["authentication"]);
			const proverPublicKey = require_keyDidMapping.getPublicJwkFromVerificationMethod(proverVerificationMethod);
			const holderBinding = require_utils.parseHolderBindingFromCredential(presentation.sdJwt.prettyClaims);
			const holder = holderBinding ? await require_utils.extractKeyFromHolderBinding(agentContext, holderBinding) : void 0;
			sdjwt.config({
				verifier: require_utils.getSdJwtVerifier(agentContext, proverPublicKey),
				kbVerifier: holder ? require_utils.getSdJwtVerifier(agentContext, holder.publicJwk) : void 0
			});
			try {
				await sdjwt.verify(presentation.encoded);
				validationResults.validations.presentationSignature = { isValid: true };
			} catch (error) {
				validationResults.validations.presentationSignature = {
					isValid: false,
					error
				};
			}
			if (presentation.resolvedPresentation.holderId && proverVerificationMethod.controller !== presentation.resolvedPresentation.holderId) validationResults.validations.holderIsSigner = {
				isValid: false,
				error: new require_CredoError.CredoError(`Presentation is signed using verification method ${proverVerificationMethod.id}, while the holder of the presentation is '${presentation.resolvedPresentation.holderId}'`)
			};
			else validationResults.validations.holderIsSigner = { isValid: true };
			const credentials = require_array.asArray(presentation.resolvedPresentation.verifiableCredential);
			validationResults.validations.credentials = await Promise.all(credentials.map(async (credential) => {
				if (!(credential.envelopedCredential instanceof require_W3cV2SdJwtVerifiableCredential.W3cV2SdJwtVerifiableCredential)) return {
					isValid: false,
					error: new require_CredoError.CredoError("Credential is not of format SD-JWT. Presentations in SD-JWT format can only contain credentials in SD-JWT format."),
					validations: {}
				};
				const credentialResult = await this.verifyCredential(agentContext, { credential: credential.envelopedCredential });
				let credentialSubjectAuthentication;
				const credentialSubjectIds = credential.resolvedCredential.credentialSubjectIds;
				const presentationAuthenticatesCredentialSubject = credentialSubjectIds.some((subjectId) => proverVerificationMethod.controller === subjectId);
				if (credentialSubjectIds.length > 0 && !presentationAuthenticatesCredentialSubject) credentialSubjectAuthentication = {
					isValid: false,
					error: new require_CredoError.CredoError("Credential has one or more credentialSubject ids, but presentation does not authenticate credential subject")
				};
				else credentialSubjectAuthentication = { isValid: true };
				return {
					...credentialResult,
					isValid: credentialResult.isValid && credentialSubjectAuthentication.isValid,
					validations: {
						...credentialResult.validations,
						credentialSubjectAuthentication
					}
				};
			}));
			validationResults.isValid = Object.values(validationResults.validations).every((v) => Array.isArray(v) ? v.every((vv) => vv.isValid) : v.isValid);
			return validationResults;
		} catch (error) {
			validationResults.error = error;
			return validationResults;
		}
	}
	async present(agentContext, options) {
		const originalCompact = options.credential instanceof require_W3cV2SdJwtVerifiableCredential.W3cV2SdJwtVerifiableCredential ? options.credential.encoded : options.credential;
		const presentationFrame = options.presentationFrame;
		const disclosedCompact = await new __sd_jwt_core.SDJwtInstance(this.getBaseSdJwtConfig(agentContext)).present(originalCompact, presentationFrame);
		return require_W3cV2SdJwtVerifiableCredential.W3cV2SdJwtVerifiableCredential.fromCompact(disclosedCompact);
	}
	validateDisclosureFrame(disclosureFrame) {
		if (!disclosureFrame) return;
		for (const field of NON_DISCLOSEABLE_FIELDS) {
			if (disclosureFrame[field]) throw new require_CredoError.CredoError(`'${field}' property cannot be selectively disclosed`);
			if (Array.isArray(disclosureFrame._sd) && disclosureFrame._sd?.includes(field)) throw new require_CredoError.CredoError(`'${field}' property cannot be selectively disclosed`);
		}
	}
	getBaseSdJwtConfig(agentContext) {
		const kms = agentContext.resolve(require_KeyManagementApi.KeyManagementApi);
		return {
			hasher: require_W3cV2SdJwt.sdJwtVcHasher,
			saltGenerator: (length) => require_TypedArrayEncoder.TypedArrayEncoder.toBase64URL(kms.randomBytes({ length })).slice(0, length)
		};
	}
};
W3cV2SdJwtCredentialService = require_decorate.__decorate([(0, tsyringe.injectable)()], W3cV2SdJwtCredentialService);

//#endregion
Object.defineProperty(exports, 'W3cV2SdJwtCredentialService', {
  enumerable: true,
  get: function () {
    return W3cV2SdJwtCredentialService;
  }
});