mirror of
https://github.com/mosip/inji-wallet.git
synced 2026-01-09 21:48:04 -05:00
[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:
@@ -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}`;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'],
|
||||
|
||||
Reference in New Issue
Block a user