[INJIMOB-3532] add sd jwt vp support (#2082)

* [INJIMOB-3513] add sd jwt vp support

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3513] add bridge logic and sd-jwt signing for ovp

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3532] add: support of OVP share in iOS

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3532] add sd-jwt ovp ui

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3532] refactor: optimize wallet_metadata creation logic

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3532] refactor: fixed alignement issues and crash bug

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

---------

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
Co-authored-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
This commit is contained in:
abhip2565
2025-09-18 18:50:53 +05:30
committed by GitHub
parent 62b627242c
commit 0713bbb5c4
36 changed files with 1291 additions and 627 deletions

View File

@@ -139,3 +139,7 @@ export const createCacheObject = (response: any) => {
export const isCacheExpired = (timestamp: number) => {
return Date.now() - timestamp >= CACHE_TTL;
};
export function getVerifierKey(verifier: string): string {
return `trusted_verifier_${verifier}`;
}

View File

@@ -153,6 +153,15 @@ export function useOvpErrorModal({
showRetryButton: true,
});
generateAndStoreLogMessage('SEND_VP_ERROR');
} else if (error.includes('failed to update trusted verifier list')) {
setErrorModal({
show: true,
title: t('errors.trustedVerifierListUpdateError.title'),
message: t('errors.trustedVerifierListUpdateError.message'),
additionalMessage,
showRetryButton: false,
});
generateAndStoreLogMessage('TRUSTED_VERIFIER_LIST_UPDATE_ERROR');
} else if (error !== '') {
setErrorModal({
show: true,

View File

@@ -7,6 +7,8 @@ import {
import {walletMetadata} from './walletMetadata';
import {getWalletMetadata, isClientValidationRequired} from './OpenID4VPHelper';
import {parseJSON} from '../Utils';
import {VCFormat} from '../VCFormat';
import {VCMetadata} from '../VCMetadata';
export const OpenID4VP_Proof_Sign_Algo = 'EdDSA';
@@ -45,12 +47,16 @@ class OpenID4VP {
static async constructUnsignedVPToken(
selectedVCs: Record<string, VC[]>,
selectedDisclosuresByVc: any,
holderId: string,
signatureAlgorithm: string,
) {
const openID4VP = await OpenID4VP.getInstance();
const updatedSelectedVCs = openID4VP.processSelectedVCs(selectedVCs);
const updatedSelectedVCs = openID4VP.processSelectedVCs(
selectedVCs,
selectedDisclosuresByVc,
);
const unSignedVpTokens =
await openID4VP.InjiOpenID4VP.constructUnsignedVPToken(
updatedSelectedVCs,
@@ -76,12 +82,21 @@ class OpenID4VP {
});
}
private processSelectedVCs(selectedVCs: Record<string, VC[]>) {
private processSelectedVCs(
selectedVCs: Record<string, VC[]>,
selectedDisclosuresByVc: any,
) {
const selectedVcsData: SelectedCredentialsForVPSharing = {};
Object.entries(selectedVCs).forEach(([inputDescriptorId, vcsArray]) => {
vcsArray.forEach(vcData => {
const credentialFormat = vcData.vcMetadata.format;
const credential = vcData.verifiableCredential.credential;
const credential = this.extractCredential(
vcData,
credentialFormat,
selectedDisclosuresByVc[
VCMetadata.fromVcMetadataString(vcData.vcMetadata).getVcKey()
],
);
if (!selectedVcsData[inputDescriptorId]) {
selectedVcsData[inputDescriptorId] = {};
}
@@ -93,6 +108,55 @@ class OpenID4VP {
});
return selectedVcsData;
}
private extractCredential(
vcData: VC,
credentialFormat: string,
selectedDisclosures: any,
) {
if (
credentialFormat === VCFormat.mso_mdoc ||
credentialFormat === VCFormat.ldp_vc
) {
return vcData.verifiableCredential.credential;
}
if (
credentialFormat === VCFormat.vc_sd_jwt ||
credentialFormat === VCFormat.dc_sd_jwt
) {
return this.processSdJwtVcForSharing(vcData, selectedDisclosures);
}
}
private processSdJwtVcForSharing(
vcData: VC,
selectedDisclosures: string[],
): string {
if (!vcData?.verifiableCredential?.credential) {
throw new Error('Invalid VC: missing credential');
}
const compact = vcData.verifiableCredential.credential;
const [jwt] = compact.split('~');
const pathToDisclosures: Record<string, string[]> =
vcData.verifiableCredential?.processedCredential.pathToDisclosures || {};
const disclosureSet = new Set<string>();
selectedDisclosures?.forEach(path => {
const disclosures = pathToDisclosures[path];
if (disclosures) {
disclosures.forEach(d => disclosureSet.add(d));
}
});
const finalSdJwt =
disclosureSet.size > 0
? [jwt, ...disclosureSet].join('~') + '~'
: jwt + '~';
return finalSdJwt;
}
}
export default OpenID4VP;

View File

@@ -12,6 +12,9 @@ export const walletMetadata = {
mso_mdoc: {
alg_values_supported: ['ES256'],
},
"vc+sd-jwt": {
alg_values_supported: ['EdDSA','ES256'],
},
},
client_id_schemes_supported: ['redirect_uri', 'did', 'pre-registered'],
request_object_signing_alg_values_supported: ['EdDSA'],