diff --git a/machines/Issuers/IssuersService.ts b/machines/Issuers/IssuersService.ts index cd890b3948..5100172f1b 100644 --- a/machines/Issuers/IssuersService.ts +++ b/machines/Issuers/IssuersService.ts @@ -1,6 +1,12 @@ -import Cloud from '../../shared/CloudBackupAndRestoreUtils'; -import {CACHED_API} from '../../shared/api'; import NetInfo from '@react-native-community/netinfo'; +import { NativeModules } from 'react-native'; +import { authorize } from 'react-native-app-auth'; +import Cloud from '../../shared/CloudBackupAndRestoreUtils'; +import { CACHED_API } from '../../shared/api'; +import { + fetchKeyPair, + generateKeyPair, +} from '../../shared/cryptoutil/cryptoUtil'; import { constructAuthorizationConfiguration, constructIssuerMetaData, @@ -9,26 +15,14 @@ import { OIDCErrors, updateCredentialInformation, vcDownloadTimeout, + verifyCredentialData } from '../../shared/openId4VCI/Utils'; -import {authorize} from 'react-native-app-auth'; -import { - fetchKeyPair, - generateKeyPair, -} from '../../shared/cryptoutil/cryptoUtil'; -import {NativeModules} from 'react-native'; -import { - VerificationErrorMessage, - VerificationErrorType, - verifyCredential, -} from '../../shared/vcjs/verifyCredential'; +import { TelemetryConstants } from '../../shared/telemetry/TelemetryConstants'; import { getImpressionEventData, sendImpressionEvent, } from '../../shared/telemetry/TelemetryUtils'; -import {TelemetryConstants} from '../../shared/telemetry/TelemetryConstants'; -import {VciClient} from '../../shared/vciClient/VciClient'; -import {isMockVC} from '../../shared/Utils'; -import {VCFormat} from '../../shared/VCFormat'; +import { VciClient } from '../../shared/vciClient/VciClient'; export const IssuersService = () => { return { @@ -151,26 +145,15 @@ export const IssuersService = () => { }, verifyCredential: async (context: any) => { - //TODO: Remove bypassing verification of mock VCs once mock VCs are verifiable - if ( - context.selectedCredentialType.format === VCFormat.mso_mdoc || - !isMockVC(context.selectedIssuerId) - ) { - const verificationResult = await verifyCredential( - context.verifiableCredential?.credential, - context.selectedCredentialType.format, - ); - if (!verificationResult.isVerified) { + const verificationResult = await verifyCredentialData( + context.verifiableCredential?.credential, + context.selectedCredentialType.format, + context.selectedIssuerId + ); + if(!verificationResult.isVerified) { throw new Error(verificationResult.verificationErrorCode); } return verificationResult; - } else { - return { - isVerified: true, - verificationMessage: VerificationErrorMessage.NO_ERROR, - verificationErrorCode: VerificationErrorType.NO_ERROR, - }; - } }, }; }; diff --git a/machines/VerifiableCredential/VCItemMachine/VCItemMachine.typegen.ts b/machines/VerifiableCredential/VCItemMachine/VCItemMachine.typegen.ts index c01016c68a..08e7beeb08 100644 --- a/machines/VerifiableCredential/VCItemMachine/VCItemMachine.typegen.ts +++ b/machines/VerifiableCredential/VCItemMachine/VCItemMachine.typegen.ts @@ -1,484 +1,147 @@ -// This file was automatically generated. Edits will be overwritten -export interface Typegen0 { - '@@xstate/typegen': true; - internalEvents: { - '': {type: ''}; - 'done.invoke.checkStatus': { - type: 'done.invoke.checkStatus'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.downloadCredential': { - type: 'done.invoke.downloadCredential'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]': { - type: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.vc-item-machine.verifyState.verifyingCredential:invocation[0]': { - type: 'done.invoke.vc-item-machine.verifyState.verifyingCredential:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'error.platform.checkStatus': { - type: 'error.platform.checkStatus'; - data: unknown; - }; - 'error.platform.downloadCredential': { - type: 'error.platform.downloadCredential'; - data: unknown; - }; - 'error.platform.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]': { - type: 'error.platform.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]'; - data: unknown; - }; - 'error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]': { - type: 'error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]'; - data: unknown; - }; - 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]': { - type: 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]'; - data: unknown; - }; - 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]': { - type: 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]'; - data: unknown; - }; - 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]': { - type: 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]'; - data: unknown; - }; - 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]': { - type: 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]'; - data: unknown; - }; - 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]': { - type: 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]'; - data: unknown; - }; - 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]': { - type: 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - data: unknown; - }; - 'error.platform.vc-item-machine.verifyState.verifyingCredential:invocation[0]': { - type: 'error.platform.vc-item-machine.verifyState.verifyingCredential:invocation[0]'; - data: unknown; - }; - 'xstate.after(500)#vc-item-machine.verifyState.verifyingCredential': { - type: 'xstate.after(500)#vc-item-machine.verifyState.verifyingCredential'; - }; - 'xstate.init': {type: 'xstate.init'}; - 'xstate.stop': {type: 'xstate.stop'}; - }; - invokeSrcNameMap: { - addWalletBindingId: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]'; - checkDownloadExpiryLimit: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]'; - checkStatus: 'done.invoke.checkStatus'; - downloadCredential: 'done.invoke.downloadCredential'; - fetchIssuerWellknown: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]'; - fetchKeyPair: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]'; - generateKeypairAndStore: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]'; - isUserSignedAlready: - | 'done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]'; - loadDownloadLimitConfig: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]'; - requestBindingOTP: - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]'; - updatePrivateKey: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - verifyCredential: - | 'done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]' - | 'done.invoke.vc-item-machine.verifyState.verifyingCredential:invocation[0]'; - }; - missingImplementations: { - actions: - | 'addVcToInProgressDownloads' - | 'closeViewVcModal' - | 'incrementDownloadCounter' - | 'logDownloaded' - | 'logRemovedVc' - | 'logWalletBindingFailure' - | 'logWalletBindingSuccess' - | 'refreshAllVcs' - | 'removeVcFromInProgressDownloads' - | 'removeVcItem' - | 'removeVcMetaDataFromStorage' - | 'removeVcMetaDataFromVcMachineContext' - | 'removeVerificationStatusFromVcMeta' - | 'requestVcContext' - | 'resetIsMachineInKebabPopupState' - | 'resetIsVerified' - | 'resetPrivateKey' - | 'resetVerificationStatus' - | 'sendActivationStartEvent' - | 'sendActivationSuccessEvent' - | 'sendBackupEvent' - | 'sendDownloadLimitExpire' - | 'sendDownloadingFailedToVcMeta' - | 'sendTelemetryEvents' - | 'sendUserCancelledActivationFailedEndEvent' - | 'sendVerificationError' - | 'sendVerificationStatusToVcMeta' - | 'sendWalletBindingErrorEvent' - | 'sendWalletBindingSuccess' - | 'setCommunicationDetails' - | 'setContext' - | 'setDownloadInterval' - | 'setErrorAsVerificationError' - | 'setErrorAsWalletBindingError' - | 'setIsVerified' - | 'setMaxDownloadCount' - | 'setOTP' - | 'setPinCard' - | 'setPrivateKey' - | 'setPublicKey' - | 'setThumbprintForWalletBindingId' - | 'setVcKey' - | 'setVcMetadata' - | 'setVerificationStatus' - | 'setWalletBindingResponse' - | 'showVerificationBannerStatus' - | 'storeContext' - | 'storeVcInContext' - | 'unSetBindingTransactionId' - | 'unSetError' - | 'unSetOTP' - | 'updateVcMetadata' - | 'updateWellknownResponse'; - delays: never; - guards: - | 'hasCredential' - | 'hasCredentialAndWellknown' - | 'hasKeyPair' - | 'isCustomSecureKeystore' - | 'isDownloadAllowed' - | 'isSignedIn' - | 'isVerificationPendingBecauseOfNetworkIssue'; - services: - | 'addWalletBindingId' - | 'checkDownloadExpiryLimit' - | 'checkStatus' - | 'downloadCredential' - | 'fetchIssuerWellknown' - | 'fetchKeyPair' - | 'generateKeypairAndStore' - | 'isUserSignedAlready' - | 'loadDownloadLimitConfig' - | 'requestBindingOTP' - | 'updatePrivateKey' - | 'verifyCredential'; - }; - eventsCausingActions: { - addVcToInProgressDownloads: 'GET_VC_RESPONSE'; - closeViewVcModal: 'CLOSE_VC_MODAL' | 'STORE_RESPONSE'; - incrementDownloadCounter: - | 'POLL' - | 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]'; - logDownloaded: 'STORE_RESPONSE'; - logRemovedVc: 'STORE_RESPONSE'; - logWalletBindingFailure: - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - logWalletBindingSuccess: - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - refreshAllVcs: - | 'STORE_RESPONSE' - | 'done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]'; - removeVcFromInProgressDownloads: - | 'STORE_RESPONSE' - | 'error.platform.downloadCredential' - | 'error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]'; - removeVcItem: 'CONFIRM'; - removeVcMetaDataFromStorage: - | 'STORE_ERROR' - | 'error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]'; - removeVcMetaDataFromVcMachineContext: 'DISMISS'; - removeVerificationStatusFromVcMeta: 'RESET_VERIFICATION_STATUS'; - requestVcContext: 'DISMISS' | 'REFRESH' | 'STORE_ERROR' | 'xstate.init'; - resetIsMachineInKebabPopupState: - | '' - | 'ADD_WALLET_BINDING_ID' - | 'CANCEL' - | 'CLOSE_VC_MODAL' - | 'DISMISS' - | 'REFRESH' - | 'REMOVE' - | 'SHOW_ACTIVITY' - | 'done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]' - | 'xstate.stop'; - resetIsVerified: - | 'error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]' - | 'error.platform.vc-item-machine.verifyState.verifyingCredential:invocation[0]'; - resetPrivateKey: - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - resetVerificationStatus: - | 'REMOVE_VERIFICATION_STATUS_BANNER' - | 'RESET_VERIFICATION_STATUS'; - sendActivationStartEvent: 'CONFIRM'; - sendActivationSuccessEvent: - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - sendBackupEvent: - | 'done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]'; - sendDownloadLimitExpire: - | 'FAILED' - | 'error.platform.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]'; - sendDownloadingFailedToVcMeta: 'error.platform.downloadCredential'; - sendTelemetryEvents: 'STORE_RESPONSE'; - sendUserCancelledActivationFailedEndEvent: 'DISMISS'; - sendVerificationError: 'STORE_RESPONSE'; - sendVerificationStatusToVcMeta: 'STORE_RESPONSE'; - sendWalletBindingErrorEvent: - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - sendWalletBindingSuccess: 'SHOW_BINDING_STATUS'; - setCommunicationDetails: - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]'; - setContext: 'CREDENTIAL_DOWNLOADED' | 'GET_VC_RESPONSE'; - setDownloadInterval: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]'; - setErrorAsVerificationError: 'error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]'; - setErrorAsWalletBindingError: - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - setIsVerified: - | 'done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]' - | 'done.invoke.vc-item-machine.verifyState.verifyingCredential:invocation[0]'; - setMaxDownloadCount: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]'; - setOTP: 'INPUT_OTP'; - setPinCard: 'PIN_CARD'; - setPrivateKey: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]'; - setPublicKey: - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]'; - setThumbprintForWalletBindingId: - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - setVcKey: 'REMOVE'; - setVcMetadata: 'UPDATE_VC_METADATA'; - setVerificationStatus: - | 'SET_VERIFICATION_STATUS' - | 'SHOW_VERIFICATION_STATUS_BANNER' - | 'STORE_RESPONSE'; - setWalletBindingResponse: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]'; - showVerificationBannerStatus: - | 'SHOW_VERIFICATION_STATUS_BANNER' - | 'STORE_RESPONSE' - | 'xstate.after(500)#vc-item-machine.verifyState.verifyingCredential'; - storeContext: - | 'done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]' - | 'done.invoke.vc-item-machine.verifyState.verifyingCredential:invocation[0]' - | 'error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]' - | 'error.platform.vc-item-machine.verifyState.verifyingCredential:invocation[0]'; - storeVcInContext: - | 'STORE_RESPONSE' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - unSetBindingTransactionId: 'DISMISS'; - unSetError: - | 'CANCEL' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]'; - unSetOTP: - | 'DISMISS' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]'; - updateVcMetadata: 'PIN_CARD' | 'STORE_RESPONSE'; - updateWellknownResponse: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]'; - }; - eventsCausingDelays: {}; - eventsCausingGuards: { - hasCredential: 'GET_VC_RESPONSE'; - hasCredentialAndWellknown: 'GET_VC_RESPONSE'; - hasKeyPair: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]'; - isCustomSecureKeystore: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]'; - isDownloadAllowed: 'POLL'; - isSignedIn: - | 'done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]'; - isVerificationPendingBecauseOfNetworkIssue: - | 'error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]' - | 'error.platform.vc-item-machine.verifyState.verifyingCredential:invocation[0]'; - }; - eventsCausingServices: { - addWalletBindingId: - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]' - | 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]'; - checkDownloadExpiryLimit: - | 'POLL' - | 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]'; - checkStatus: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]'; - downloadCredential: 'DOWNLOAD_READY'; - fetchIssuerWellknown: 'GET_VC_RESPONSE'; - fetchKeyPair: 'INPUT_OTP'; - generateKeypairAndStore: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]'; - isUserSignedAlready: 'STORE_RESPONSE'; - loadDownloadLimitConfig: 'GET_VC_RESPONSE' | 'STORE_ERROR'; - requestBindingOTP: 'CONFIRM' | 'RESEND_OTP'; - updatePrivateKey: never; - verifyCredential: 'CREDENTIAL_DOWNLOADED' | 'VERIFY'; - }; - matchesStates: - | 'vcUtilitiesState' - | 'vcUtilitiesState.idle' - | 'vcUtilitiesState.kebabPopUp' - | 'vcUtilitiesState.kebabPopUp.idle' - | 'vcUtilitiesState.kebabPopUp.pinCard' - | 'vcUtilitiesState.kebabPopUp.removeWallet' - | 'vcUtilitiesState.kebabPopUp.removingVc' - | 'vcUtilitiesState.kebabPopUp.showActivities' - | 'vcUtilitiesState.kebabPopUp.triggerAutoBackup' - | 'vcUtilitiesState.loadVc' - | 'vcUtilitiesState.loadVc.loadVcFromContext' - | 'vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown' - | 'vcUtilitiesState.loadVc.loadVcFromContext.idle' - | 'vcUtilitiesState.loadVc.loadVcFromServer' - | 'vcUtilitiesState.loadVc.loadVcFromServer.checkingStatus' - | 'vcUtilitiesState.loadVc.loadVcFromServer.downloadingCredential' - | 'vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig' - | 'vcUtilitiesState.loadVc.loadVcFromServer.savingFailed' - | 'vcUtilitiesState.loadVc.loadVcFromServer.savingFailed.idle' - | 'vcUtilitiesState.loadVc.loadVcFromServer.savingFailed.viewingVc' - | 'vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry' - | 'vcUtilitiesState.verifyingCredential' - | 'vcUtilitiesState.verifyingCredential.handleVCVerificationFailure' - | 'vcUtilitiesState.verifyingCredential.idle' - | 'vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload' - | 'vcUtilitiesState.walletBinding' - | 'vcUtilitiesState.walletBinding.acceptingBindingOTP' - | 'vcUtilitiesState.walletBinding.acceptingBindingOTP.idle' - | 'vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP' - | 'vcUtilitiesState.walletBinding.addKeyPair' - | 'vcUtilitiesState.walletBinding.addingWalletBindingId' - | 'vcUtilitiesState.walletBinding.generateKeyPair' - | 'vcUtilitiesState.walletBinding.requestingBindingOTP' - | 'vcUtilitiesState.walletBinding.showBindingWarning' - | 'vcUtilitiesState.walletBinding.showingWalletBindingError' - | 'vcUtilitiesState.walletBinding.updatingContextVariables' - | 'vcUtilitiesState.walletBinding.updatingPrivateKey' - | 'verifyState' - | 'verifyState.idle' - | 'verifyState.verificationCompleted' - | 'verifyState.verifyingCredential' - | { - vcUtilitiesState?: - | 'idle' - | 'kebabPopUp' - | 'loadVc' - | 'verifyingCredential' - | 'walletBinding' - | { - kebabPopUp?: - | 'idle' - | 'pinCard' - | 'removeWallet' - | 'removingVc' - | 'showActivities' - | 'triggerAutoBackup'; - loadVc?: - | 'loadVcFromContext' - | 'loadVcFromServer' - | { - loadVcFromContext?: 'fetchWellknown' | 'idle'; - loadVcFromServer?: - | 'checkingStatus' - | 'downloadingCredential' - | 'loadDownloadLimitConfig' - | 'savingFailed' - | 'verifyingDownloadLimitExpiry' - | {savingFailed?: 'idle' | 'viewingVc'}; - }; - verifyingCredential?: - | 'handleVCVerificationFailure' - | 'idle' - | 'triggerAutoBackupForVcDownload'; - walletBinding?: - | 'acceptingBindingOTP' - | 'addKeyPair' - | 'addingWalletBindingId' - | 'generateKeyPair' - | 'requestingBindingOTP' - | 'showBindingWarning' - | 'showingWalletBindingError' - | 'updatingContextVariables' - | 'updatingPrivateKey' - | {acceptingBindingOTP?: 'idle' | 'resendOTP'}; - }; - verifyState?: 'idle' | 'verificationCompleted' | 'verifyingCredential'; - }; - tags: never; -} + // This file was automatically generated. Edits will be overwritten + + export interface Typegen0 { + '@@xstate/typegen': true; + internalEvents: { + "": { type: "" }; +"done.invoke.checkStatus": { type: "done.invoke.checkStatus"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.downloadCredential": { type: "done.invoke.downloadCredential"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]": { type: "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.vc-item-machine.verifyState.verifyingCredential:invocation[0]": { type: "done.invoke.vc-item-machine.verifyState.verifyingCredential:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"error.platform.checkStatus": { type: "error.platform.checkStatus"; data: unknown }; +"error.platform.downloadCredential": { type: "error.platform.downloadCredential"; data: unknown }; +"error.platform.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]": { type: "error.platform.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]"; data: unknown }; +"error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]": { type: "error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]"; data: unknown }; +"error.platform.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]": { type: "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]"; data: unknown }; +"error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]": { type: "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]"; data: unknown }; +"error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]": { type: "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]"; data: unknown }; +"error.platform.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]": { type: "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]"; data: unknown }; +"error.platform.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]": { type: "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]"; data: unknown }; +"error.platform.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]": { type: "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; data: unknown }; +"error.platform.vc-item-machine.verifyState.verifyingCredential:invocation[0]": { type: "error.platform.vc-item-machine.verifyState.verifyingCredential:invocation[0]"; data: unknown }; +"xstate.after(500)#vc-item-machine.verifyState.verifyingCredential": { type: "xstate.after(500)#vc-item-machine.verifyState.verifyingCredential" }; +"xstate.init": { type: "xstate.init" }; +"xstate.stop": { type: "xstate.stop" }; + }; + invokeSrcNameMap: { + "addWalletBindingId": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]"; +"checkDownloadExpiryLimit": "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]"; +"checkStatus": "done.invoke.checkStatus"; +"downloadCredential": "done.invoke.downloadCredential"; +"fetchIssuerWellknown": "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]"; +"fetchKeyPair": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]"; +"generateKeypairAndStore": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]"; +"isUserSignedAlready": "done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]"; +"loadDownloadLimitConfig": "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]"; +"requestBindingOTP": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]"; +"updatePrivateKey": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; +"verifyCredential": "done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]" | "done.invoke.vc-item-machine.verifyState.verifyingCredential:invocation[0]"; + }; + missingImplementations: { + actions: "addVcToInProgressDownloads" | "closeViewVcModal" | "incrementDownloadCounter" | "logDownloaded" | "logRemovedVc" | "logWalletBindingFailure" | "logWalletBindingSuccess" | "refreshAllVcs" | "removeVcFromInProgressDownloads" | "removeVcItem" | "removeVcMetaDataFromStorage" | "removeVcMetaDataFromVcMachineContext" | "removeVerificationStatusFromVcMeta" | "requestVcContext" | "resetIsMachineInKebabPopupState" | "resetIsVerified" | "resetPrivateKey" | "resetVerificationStatus" | "sendActivationStartEvent" | "sendActivationSuccessEvent" | "sendBackupEvent" | "sendDownloadLimitExpire" | "sendDownloadingFailedToVcMeta" | "sendTelemetryEvents" | "sendUserCancelledActivationFailedEndEvent" | "sendVerificationError" | "sendVerificationStatusToVcMeta" | "sendWalletBindingErrorEvent" | "sendWalletBindingSuccess" | "setCommunicationDetails" | "setContext" | "setDownloadInterval" | "setErrorAsVerificationError" | "setErrorAsWalletBindingError" | "setIsVerified" | "setMaxDownloadCount" | "setOTP" | "setPinCard" | "setPrivateKey" | "setPublicKey" | "setThumbprintForWalletBindingId" | "setVcKey" | "setVcMetadata" | "setVerificationStatus" | "setWalletBindingResponse" | "showVerificationBannerStatus" | "storeContext" | "storeVcInContext" | "unSetBindingTransactionId" | "unSetError" | "unSetOTP" | "updateVcMetadata" | "updateWellknownResponse"; + delays: never; + guards: "hasCredential" | "hasCredentialAndWellknown" | "hasKeyPair" | "isCustomSecureKeystore" | "isDownloadAllowed" | "isSignedIn" | "isVerificationPendingBecauseOfNetworkIssue"; + services: "addWalletBindingId" | "checkDownloadExpiryLimit" | "checkStatus" | "downloadCredential" | "fetchIssuerWellknown" | "fetchKeyPair" | "generateKeypairAndStore" | "isUserSignedAlready" | "loadDownloadLimitConfig" | "requestBindingOTP" | "updatePrivateKey" | "verifyCredential"; + }; + eventsCausingActions: { + "addVcToInProgressDownloads": "GET_VC_RESPONSE"; +"closeViewVcModal": "CLOSE_VC_MODAL" | "STORE_RESPONSE"; +"incrementDownloadCounter": "POLL" | "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]"; +"logDownloaded": "STORE_RESPONSE"; +"logRemovedVc": "STORE_RESPONSE"; +"logWalletBindingFailure": "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; +"logWalletBindingSuccess": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; +"refreshAllVcs": "STORE_RESPONSE" | "done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]"; +"removeVcFromInProgressDownloads": "STORE_RESPONSE" | "error.platform.downloadCredential" | "error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]"; +"removeVcItem": "CONFIRM"; +"removeVcMetaDataFromStorage": "STORE_ERROR" | "error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]"; +"removeVcMetaDataFromVcMachineContext": "DISMISS"; +"removeVerificationStatusFromVcMeta": "RESET_VERIFICATION_STATUS"; +"requestVcContext": "DISMISS" | "REFRESH" | "STORE_ERROR" | "xstate.init"; +"resetIsMachineInKebabPopupState": "" | "ADD_WALLET_BINDING_ID" | "CANCEL" | "CLOSE_VC_MODAL" | "DISMISS" | "REFRESH" | "REMOVE" | "SHOW_ACTIVITY" | "done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]" | "xstate.stop"; +"resetIsVerified": "error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]" | "error.platform.vc-item-machine.verifyState.verifyingCredential:invocation[0]"; +"resetPrivateKey": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; +"resetVerificationStatus": "REMOVE_VERIFICATION_STATUS_BANNER" | "RESET_VERIFICATION_STATUS"; +"sendActivationStartEvent": "CONFIRM"; +"sendActivationSuccessEvent": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; +"sendBackupEvent": "done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]"; +"sendDownloadLimitExpire": "FAILED" | "error.platform.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]"; +"sendDownloadingFailedToVcMeta": "error.platform.downloadCredential"; +"sendTelemetryEvents": "STORE_RESPONSE"; +"sendUserCancelledActivationFailedEndEvent": "DISMISS"; +"sendVerificationError": "STORE_RESPONSE"; +"sendVerificationStatusToVcMeta": "STORE_RESPONSE"; +"sendWalletBindingErrorEvent": "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; +"sendWalletBindingSuccess": "SHOW_BINDING_STATUS"; +"setCommunicationDetails": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]"; +"setContext": "CREDENTIAL_DOWNLOADED" | "GET_VC_RESPONSE"; +"setDownloadInterval": "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]"; +"setErrorAsVerificationError": "error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]"; +"setErrorAsWalletBindingError": "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; +"setIsVerified": "done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]" | "done.invoke.vc-item-machine.verifyState.verifyingCredential:invocation[0]"; +"setMaxDownloadCount": "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]"; +"setOTP": "INPUT_OTP"; +"setPinCard": "PIN_CARD"; +"setPrivateKey": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]"; +"setPublicKey": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]"; +"setThumbprintForWalletBindingId": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; +"setVcKey": "REMOVE"; +"setVcMetadata": "UPDATE_VC_METADATA"; +"setVerificationStatus": "SET_VERIFICATION_STATUS" | "SHOW_VERIFICATION_STATUS_BANNER" | "STORE_RESPONSE"; +"setWalletBindingResponse": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]"; +"showVerificationBannerStatus": "SHOW_VERIFICATION_STATUS_BANNER" | "STORE_RESPONSE" | "xstate.after(500)#vc-item-machine.verifyState.verifyingCredential"; +"storeContext": "done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]" | "done.invoke.vc-item-machine.verifyState.verifyingCredential:invocation[0]" | "error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]" | "error.platform.vc-item-machine.verifyState.verifyingCredential:invocation[0]"; +"storeVcInContext": "STORE_RESPONSE" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; +"unSetBindingTransactionId": "DISMISS"; +"unSetError": "CANCEL" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.updatingPrivateKey:invocation[0]"; +"unSetOTP": "DISMISS" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]"; +"updateVcMetadata": "PIN_CARD" | "STORE_RESPONSE"; +"updateWellknownResponse": "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]"; + }; + eventsCausingDelays: { + + }; + eventsCausingGuards: { + "hasCredential": "GET_VC_RESPONSE"; +"hasCredentialAndWellknown": "GET_VC_RESPONSE"; +"hasKeyPair": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]"; +"isCustomSecureKeystore": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]"; +"isDownloadAllowed": "POLL"; +"isSignedIn": "done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]"; +"isVerificationPendingBecauseOfNetworkIssue": "error.platform.vc-item-machine.vcUtilitiesState.verifyingCredential:invocation[0]" | "error.platform.vc-item-machine.verifyState.verifyingCredential:invocation[0]"; + }; + eventsCausingServices: { + "addWalletBindingId": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]" | "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.generateKeyPair:invocation[0]"; +"checkDownloadExpiryLimit": "POLL" | "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]"; +"checkStatus": "done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]"; +"downloadCredential": "DOWNLOAD_READY"; +"fetchIssuerWellknown": "GET_VC_RESPONSE"; +"fetchKeyPair": "INPUT_OTP"; +"generateKeypairAndStore": "done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]"; +"isUserSignedAlready": "STORE_RESPONSE"; +"loadDownloadLimitConfig": "GET_VC_RESPONSE" | "STORE_ERROR"; +"requestBindingOTP": "CONFIRM" | "RESEND_OTP"; +"updatePrivateKey": never; +"verifyCredential": "CREDENTIAL_DOWNLOADED" | "VERIFY"; + }; + matchesStates: "vcUtilitiesState" | "vcUtilitiesState.idle" | "vcUtilitiesState.kebabPopUp" | "vcUtilitiesState.kebabPopUp.idle" | "vcUtilitiesState.kebabPopUp.pinCard" | "vcUtilitiesState.kebabPopUp.removeWallet" | "vcUtilitiesState.kebabPopUp.removingVc" | "vcUtilitiesState.kebabPopUp.showActivities" | "vcUtilitiesState.kebabPopUp.triggerAutoBackup" | "vcUtilitiesState.loadVc" | "vcUtilitiesState.loadVc.loadVcFromContext" | "vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown" | "vcUtilitiesState.loadVc.loadVcFromContext.idle" | "vcUtilitiesState.loadVc.loadVcFromServer" | "vcUtilitiesState.loadVc.loadVcFromServer.checkingStatus" | "vcUtilitiesState.loadVc.loadVcFromServer.downloadingCredential" | "vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig" | "vcUtilitiesState.loadVc.loadVcFromServer.savingFailed" | "vcUtilitiesState.loadVc.loadVcFromServer.savingFailed.idle" | "vcUtilitiesState.loadVc.loadVcFromServer.savingFailed.viewingVc" | "vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry" | "vcUtilitiesState.verifyingCredential" | "vcUtilitiesState.verifyingCredential.handleVCVerificationFailure" | "vcUtilitiesState.verifyingCredential.idle" | "vcUtilitiesState.verifyingCredential.triggerAutoBackupForVcDownload" | "vcUtilitiesState.walletBinding" | "vcUtilitiesState.walletBinding.acceptingBindingOTP" | "vcUtilitiesState.walletBinding.acceptingBindingOTP.idle" | "vcUtilitiesState.walletBinding.acceptingBindingOTP.resendOTP" | "vcUtilitiesState.walletBinding.addKeyPair" | "vcUtilitiesState.walletBinding.addingWalletBindingId" | "vcUtilitiesState.walletBinding.generateKeyPair" | "vcUtilitiesState.walletBinding.requestingBindingOTP" | "vcUtilitiesState.walletBinding.showBindingWarning" | "vcUtilitiesState.walletBinding.showingWalletBindingError" | "vcUtilitiesState.walletBinding.updatingContextVariables" | "vcUtilitiesState.walletBinding.updatingPrivateKey" | "verifyState" | "verifyState.idle" | "verifyState.verificationCompleted" | "verifyState.verifyingCredential" | { "vcUtilitiesState"?: "idle" | "kebabPopUp" | "loadVc" | "verifyingCredential" | "walletBinding" | { "kebabPopUp"?: "idle" | "pinCard" | "removeWallet" | "removingVc" | "showActivities" | "triggerAutoBackup"; +"loadVc"?: "loadVcFromContext" | "loadVcFromServer" | { "loadVcFromContext"?: "fetchWellknown" | "idle"; +"loadVcFromServer"?: "checkingStatus" | "downloadingCredential" | "loadDownloadLimitConfig" | "savingFailed" | "verifyingDownloadLimitExpiry" | { "savingFailed"?: "idle" | "viewingVc"; }; }; +"verifyingCredential"?: "handleVCVerificationFailure" | "idle" | "triggerAutoBackupForVcDownload"; +"walletBinding"?: "acceptingBindingOTP" | "addKeyPair" | "addingWalletBindingId" | "generateKeyPair" | "requestingBindingOTP" | "showBindingWarning" | "showingWalletBindingError" | "updatingContextVariables" | "updatingPrivateKey" | { "acceptingBindingOTP"?: "idle" | "resendOTP"; }; }; +"verifyState"?: "idle" | "verificationCompleted" | "verifyingCredential"; }; + tags: never; + } + \ No newline at end of file diff --git a/machines/VerifiableCredential/VCItemMachine/VCItemServices.ts b/machines/VerifiableCredential/VCItemMachine/VCItemServices.ts index 63483fb808..962eb53565 100644 --- a/machines/VerifiableCredential/VCItemMachine/VCItemServices.ts +++ b/machines/VerifiableCredential/VCItemMachine/VCItemServices.ts @@ -1,27 +1,19 @@ -import {NativeModules} from 'react-native'; -import Cloud from '../../../shared/CloudBackupAndRestoreUtils'; +import { NativeModules } from 'react-native'; import getAllConfigurations, { API_URLS, CACHED_API, DownloadProps, } from '../../../shared/api'; +import Cloud from '../../../shared/CloudBackupAndRestoreUtils'; +import { isIOS } from '../../../shared/constants'; import { fetchKeyPair, generateKeyPair, } from '../../../shared/cryptoutil/cryptoUtil'; -import {CredentialDownloadResponse, request} from '../../../shared/request'; -import {WalletBindingResponse} from '../VCMetaMachine/vc'; -import { - VerificationErrorMessage, - VerificationErrorType, - verifyCredential, -} from '../../../shared/vcjs/verifyCredential'; -import {getVerifiableCredential} from './VCItemSelectors'; -import {getMatchingCredentialIssuerMetadata} from '../../../shared/openId4VCI/Utils'; -import {isIOS} from '../../../shared/constants'; -import {VCMetadata} from '../../../shared/VCMetadata'; -import {VCFormat} from '../../../shared/VCFormat'; -import {isMockVC} from '../../../shared/Utils'; +import { getMatchingCredentialIssuerMetadata, verifyCredentialData } from '../../../shared/openId4VCI/Utils'; +import { CredentialDownloadResponse, request } from '../../../shared/request'; +import { WalletBindingResponse } from '../VCMetaMachine/vc'; +import { getVerifiableCredential } from './VCItemSelectors'; const {RNSecureKeystoreModule} = NativeModules; export const VCItemServices = model => { @@ -199,26 +191,16 @@ export const VCItemServices = model => { }, verifyCredential: async (context: any) => { - if (context.verifiableCredential) { - //TODO: Remove bypassing verification of mock VCs once mock VCs are verifiable - if ( - context.selectedCredentialType.format === VCFormat.mso_mdoc || - !isMockVC(context.selectedIssuerId) - ) { - const verificationResult = await verifyCredential( - getVerifiableCredential(context.verifiableCredential), - (context.vcMetadata as VCMetadata).format, - ); - if (!verificationResult.isVerified) { + if(context.verifiableCredential){ + const verificationResult = await verifyCredentialData( + getVerifiableCredential(context.verifiableCredential), + context.selectedCredentialType.format, + context.selectedIssuerId + ); + if(!verificationResult.isVerified) { throw new Error(verificationResult.verificationErrorCode); } - } else { - return { - isVerified: true, - verificationMessage: VerificationErrorMessage.NO_ERROR, - verificationErrorCode: VerificationErrorType.NO_ERROR, - }; - } + return verificationResult; } }, }; diff --git a/machines/backupAndRestore/restore/restoreService.ts b/machines/backupAndRestore/restore/restoreService.ts index 5862e5be2e..31a00f5986 100644 --- a/machines/backupAndRestore/restore/restoreService.ts +++ b/machines/backupAndRestore/restore/restoreService.ts @@ -1,6 +1,6 @@ import NetInfo from '@react-native-community/netinfo'; import Cloud from '../../../shared/CloudBackupAndRestoreUtils'; -import Storage from '../../../shared/storage'; +import { isMinimumStorageLimitReached } from '../../../shared/storage'; import fileStorage, { getBackupFilePath, unZipAndRemoveFile, @@ -11,7 +11,7 @@ export const restoreService = model => { checkInternet: async () => await NetInfo.fetch(), checkStorageAvailability: () => async () => { - return await Storage.isMinimumLimitReached('minStorageRequired'); + return await isMinimumStorageLimitReached('minStorageRequired'); }, downloadLatestBackup: () => async () => { diff --git a/machines/bleShare/request/requestMachine.ts b/machines/bleShare/request/requestMachine.ts index 90eb99eaaf..5a5491f2ec 100644 --- a/machines/bleShare/request/requestMachine.ts +++ b/machines/bleShare/request/requestMachine.ts @@ -23,7 +23,7 @@ import {VcMetaEvents} from '../../VerifiableCredential/VCMetaMachine/VCMetaMachi import {subscribe} from '../../../shared/openIdBLE/verifierEventHandler'; import {VerifierDataEvent} from '../../../shared/tuvali/types/events'; import {BLEError} from '../types'; -import Storage from '../../../shared/storage'; +import Storage, { isMinimumStorageLimitReached } from '../../../shared/storage'; import {VCMetadata} from '../../../shared/VCMetadata'; import { getEndEventData, @@ -885,9 +885,7 @@ export const requestMachine = }, checkStorageAvailability: () => async () => { - return Promise.resolve( - Storage.isMinimumLimitReached('minStorageRequired'), - ); + return Promise.resolve(isMinimumStorageLimitReached('minStorageRequired')); }, }, diff --git a/machines/bleShare/scan/scanServices.ts b/machines/bleShare/scan/scanServices.ts index ba0bb3856f..3aa21665ae 100644 --- a/machines/bleShare/scan/scanServices.ts +++ b/machines/bleShare/scan/scanServices.ts @@ -1,5 +1,5 @@ import {isLocationEnabled} from 'react-native-device-info'; -import Storage from '../../../shared/storage'; +import Storage, { isMinimumStorageLimitReached } from '../../../shared/storage'; import BluetoothStateManager from 'react-native-bluetooth-state-manager'; import { check, @@ -188,9 +188,7 @@ export const ScanServices = (model: any) => { }, checkStorageAvailability: () => async () => { - return Promise.resolve( - Storage.isMinimumLimitReached('minStorageRequiredForAuditEntry'), - ); + return Promise.resolve(isMinimumStorageLimitReached('minStorageRequiredForAuditEntry')); }, }; }; diff --git a/machines/store.ts b/machines/store.ts index 2b67f53332..f967d2ec4f 100644 --- a/machines/store.ts +++ b/machines/store.ts @@ -1,5 +1,4 @@ import Storage, {MMKV} from '../shared/storage'; -import binaryToBase64 from 'react-native/Libraries/Utilities/binaryToBase64'; import { EventFrom, Receiver, @@ -36,6 +35,7 @@ import { } from '../shared/telemetry/TelemetryUtils'; import {Buffer} from 'buffer'; import {VC} from './VerifiableCredential/VCMetaMachine/vc'; +import { isVCStorageInitialised } from '../shared/fileStorage'; export const keyinvalidatedString = 'Key Invalidated due to biometric enrollment'; @@ -276,16 +276,17 @@ export const storeMachine = BIOMETRIC_CANCELLED: { actions: [ send( - (_, event) => model.events.BIOMETRIC_CANCELLED(event.requester), + (_, event) => + model.events.BIOMETRIC_CANCELLED(event.requester), { to: (_, event) => event.requester, }, ), sendUpdate(), - sendParent('BIOMETRIC_CANCELLED') + sendParent('BIOMETRIC_CANCELLED'), ], target: 'checkFreshInstall', - } + }, }, }, }, @@ -303,10 +304,10 @@ export const storeMachine = }, BIOMETRIC_CANCELLED: { actions: [sendParent('BIOMETRIC_CANCELLED')], - target: 'checkFreshInstall' + target: 'checkFreshInstall', + }, }, }, - }, { actions: { notifyParent: sendParent(model.events.READY()), @@ -334,11 +335,10 @@ export const storeMachine = return; }, checkFreshInstall: () => async callback => { - try{ - return await getItem('auth', null, ''); - } - catch(e){ - if(e instanceof BiometricCancellationError){ + try { + return await getItem('auth', null, ''); + } catch (e) { + if (e instanceof BiometricCancellationError) { callback(model.events.BIOMETRIC_CANCELLED()); } else { callback(model.events.STORE_ERROR(e)); @@ -363,7 +363,7 @@ export const storeMachine = base64EncodedString, ); } catch (e) { - if(e instanceof BiometricCancellationError){ + if (e instanceof BiometricCancellationError) { callback(model.events.BIOMETRIC_CANCELLED(event.requester)); } sendErrorEvent(getErrorEventData('ENCRYPTION', '', e)); @@ -394,7 +394,7 @@ export const storeMachine = }, checkStorageInitialisedOrNot: () => async callback => { - const isDirectoryExist = await Storage.isVCStorageInitialised(); + const isDirectoryExist = await isVCStorageInitialised(); if (!isDirectoryExist) { callback(model.events.READY()); } else { @@ -422,7 +422,7 @@ export const storeMachine = break; } case 'EXPORT': { - response = await exportData(context.encryptionKey); + response = await backupAndExportData(context.encryptionKey); break; } case 'GET_VCS_DATA': { @@ -431,10 +431,7 @@ export const storeMachine = } case 'RESTORE_BACKUP': { // the backup data is in plain text - response = await loadBackupData( - event.data, - context.encryptionKey, - ); + await restoreBackedUpData(event.data, context.encryptionKey); break; } case 'SET': { @@ -622,12 +619,12 @@ export async function setItem( } } -export async function exportData(encryptionKey: string) { - return Storage.exportData(encryptionKey); +export async function backupAndExportData(encryptionKey: string) { + return Storage.backupData(encryptionKey); } -export async function loadBackupData(data, encryptionKey) { - await Storage.loadBackupData(data, encryptionKey); +export async function restoreBackedUpData(data, encryptionKey) { + await Storage.restoreBackUpData(data, encryptionKey); } export async function fetchAllWellknownConfig(encryptionKey: string) { diff --git a/machines/store.typegen.ts b/machines/store.typegen.ts index 1b326c7dea..6d6f0df048 100644 --- a/machines/store.typegen.ts +++ b/machines/store.typegen.ts @@ -1,90 +1,54 @@ -// This file was automatically generated. Edits will be overwritten -export interface Typegen0 { - '@@xstate/typegen': true; - internalEvents: { - 'done.invoke._store': { - type: 'done.invoke._store'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.store.checkFreshInstall:invocation[0]': { - type: 'done.invoke.store.checkFreshInstall:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'done.invoke.store.resettingStorage:invocation[0]': { - type: 'done.invoke.store.resettingStorage:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'error.platform._store': {type: 'error.platform._store'; data: unknown}; - 'xstate.init': {type: 'xstate.init'}; - }; - invokeSrcNameMap: { - checkFreshInstall: 'done.invoke.store.checkFreshInstall:invocation[0]'; - checkStorageInitialisedOrNot: 'done.invoke.store.checkStorageInitialisation:invocation[0]'; - clear: 'done.invoke.store.resettingStorage:invocation[0]'; - clearKeys: 'done.invoke.store.clearIosKeys:invocation[0]'; - generateEncryptionKey: 'done.invoke.store.generatingEncryptionKey:invocation[0]'; - getEncryptionKey: 'done.invoke.store.gettingEncryptionKey:invocation[0]'; - hasEncryptionKey: 'done.invoke.store.checkEncryptionKey:invocation[0]'; - store: 'done.invoke._store'; - }; - missingImplementations: { - actions: never; - delays: never; - guards: never; - services: never; - }; - eventsCausingActions: { - forwardStoreRequest: - | 'APPEND' - | 'CLEAR' - | 'EXPORT' - | 'FETCH_ALL_WELLKNOWN_CONFIG' - | 'GET' - | 'GET_VCS_DATA' - | 'PREPEND' - | 'REMOVE' - | 'REMOVE_ITEMS' - | 'REMOVE_VC_METADATA' - | 'RESTORE_BACKUP' - | 'SET' - | 'UPDATE'; - notifyParent: - | 'KEY_RECEIVED' - | 'READY' - | 'done.invoke.store.resettingStorage:invocation[0]'; - setEncryptionKey: 'KEY_RECEIVED'; - }; - eventsCausingDelays: {}; - eventsCausingGuards: { - hasData: 'done.invoke.store.checkFreshInstall:invocation[0]'; - isCustomSecureKeystore: 'KEY_RECEIVED'; - }; - eventsCausingServices: { - checkFreshInstall: 'xstate.init'; - checkStorageInitialisedOrNot: 'ERROR'; - clear: 'KEY_RECEIVED'; - clearKeys: 'done.invoke.store.checkFreshInstall:invocation[0]'; - generateEncryptionKey: 'ERROR' | 'IGNORE' | 'READY'; - getEncryptionKey: 'TRY_AGAIN'; - hasEncryptionKey: never; - store: - | 'KEY_RECEIVED' - | 'READY' - | 'done.invoke.store.resettingStorage:invocation[0]'; - }; - matchesStates: - | 'checkEncryptionKey' - | 'checkFreshInstall' - | 'checkStorageInitialisation' - | 'clearIosKeys' - | 'failedReadingKey' - | 'generatingEncryptionKey' - | 'gettingEncryptionKey' - | 'ready' - | 'resettingStorage'; - tags: never; -} + // This file was automatically generated. Edits will be overwritten + + export interface Typegen0 { + '@@xstate/typegen': true; + internalEvents: { + "done.invoke._store": { type: "done.invoke._store"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.store.checkFreshInstall:invocation[0]": { type: "done.invoke.store.checkFreshInstall:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"done.invoke.store.resettingStorage:invocation[0]": { type: "done.invoke.store.resettingStorage:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"error.platform._store": { type: "error.platform._store"; data: unknown }; +"xstate.init": { type: "xstate.init" }; + }; + invokeSrcNameMap: { + "checkFreshInstall": "done.invoke.store.checkFreshInstall:invocation[0]"; +"checkStorageInitialisedOrNot": "done.invoke.store.checkStorageInitialisation:invocation[0]"; +"clear": "done.invoke.store.resettingStorage:invocation[0]"; +"clearKeys": "done.invoke.store.clearIosKeys:invocation[0]"; +"generateEncryptionKey": "done.invoke.store.generatingEncryptionKey:invocation[0]"; +"getEncryptionKey": "done.invoke.store.gettingEncryptionKey:invocation[0]"; +"hasEncryptionKey": "done.invoke.store.checkEncryptionKey:invocation[0]"; +"store": "done.invoke._store"; + }; + missingImplementations: { + actions: never; + delays: never; + guards: never; + services: never; + }; + eventsCausingActions: { + "forwardStoreRequest": "APPEND" | "CLEAR" | "EXPORT" | "FETCH_ALL_WELLKNOWN_CONFIG" | "GET" | "GET_VCS_DATA" | "PREPEND" | "REMOVE" | "REMOVE_ITEMS" | "REMOVE_VC_METADATA" | "RESTORE_BACKUP" | "SET" | "UPDATE"; +"notifyParent": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]"; +"setEncryptionKey": "KEY_RECEIVED"; + }; + eventsCausingDelays: { + + }; + eventsCausingGuards: { + "hasData": "done.invoke.store.checkFreshInstall:invocation[0]"; +"isCustomSecureKeystore": "KEY_RECEIVED"; + }; + eventsCausingServices: { + "checkFreshInstall": "BIOMETRIC_CANCELLED" | "xstate.init"; +"checkStorageInitialisedOrNot": "ERROR"; +"clear": "KEY_RECEIVED"; +"clearKeys": "done.invoke.store.checkFreshInstall:invocation[0]"; +"generateEncryptionKey": "ERROR" | "IGNORE" | "READY"; +"getEncryptionKey": "TRY_AGAIN"; +"hasEncryptionKey": never; +"store": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]"; + }; + matchesStates: "checkEncryptionKey" | "checkFreshInstall" | "checkStorageInitialisation" | "clearIosKeys" | "failedReadingKey" | "generatingEncryptionKey" | "gettingEncryptionKey" | "ready" | "resettingStorage"; + tags: never; + } + \ No newline at end of file diff --git a/screens/Home/HomeScreenMachine.ts b/screens/Home/HomeScreenMachine.ts index bc53600fee..8371c4341d 100644 --- a/screens/Home/HomeScreenMachine.ts +++ b/screens/Home/HomeScreenMachine.ts @@ -7,7 +7,7 @@ import { ReceivedVcsTabMachine, } from './ReceivedVcsTabMachine'; import {IssuersMachine} from '../../machines/Issuers/IssuersMachine'; -import Storage from '../../shared/storage'; +import Storage, { isMinimumStorageLimitReached } from '../../shared/storage'; import {VCItemMachine} from '../../machines/VerifiableCredential/VCItemMachine/VCItemMachine'; const model = createModel( @@ -173,7 +173,7 @@ export const HomeScreenMachine = model.createMachine( services: { checkStorageAvailability: () => async () => { return Promise.resolve( - Storage.isMinimumLimitReached('minStorageRequired'), + isMinimumStorageLimitReached('minStorageRequired'), ); }, }, diff --git a/shared/Utils.ts b/shared/Utils.ts index b7abd0dbaa..a83da8c373 100644 --- a/shared/Utils.ts +++ b/shared/Utils.ts @@ -1,7 +1,7 @@ -import {VCMetadata} from './VCMetadata'; -import {NETWORK_REQUEST_FAILED} from './constants'; -import {groupBy} from './javascript'; -import {Issuers} from './openId4VCI/Utils'; +import { VCMetadata } from './VCMetadata'; +import { NETWORK_REQUEST_FAILED } from './constants'; +import { groupBy } from './javascript'; +import { Issuers } from './openId4VCI/Utils'; export const getVCsOrderedByPinStatus = (vcMetadatas: VCMetadata[]) => { const [pinned, unpinned] = groupBy( @@ -53,4 +53,4 @@ export const parseJSON = (input: any) => { export const isNetworkError = (error: string) => { return error.includes(NETWORK_REQUEST_FAILED); -}; \ No newline at end of file +}; diff --git a/shared/backupUtils/backupData.ts b/shared/backupUtils/backupData.ts new file mode 100644 index 0000000000..7d8d2406ad --- /dev/null +++ b/shared/backupUtils/backupData.ts @@ -0,0 +1,158 @@ +import { MY_VCS_STORE_KEY } from "../constants"; +import { decryptJson } from "../cryptoutil/cryptoUtil"; +import Storage, { MMKV } from "../storage"; +import { TelemetryConstants } from "../telemetry/TelemetryConstants"; +import { getErrorEventData, sendErrorEvent } from "../telemetry/TelemetryUtils"; +import { VCMetadata } from "../VCMetadata"; + + + +/** + * Main method to export data with clear, separated concerns + */ +export async function exportData(encryptionKey: string): Promise> { + try { + const allKeysInDB = await getAllDatabaseKeys(); + const dataFromDB = await extractConfigAndStoreData(allKeysInDB, encryptionKey); + const vcRecords = await extractVerifiableCredentials(allKeysInDB, encryptionKey, dataFromDB); + return { + VC_Records: vcRecords, + dataFromDB + }; + } catch (error) { + sendErrorEvent( + getErrorEventData( + TelemetryConstants.FlowType.dataBackup, + error.message, + error.stack, + ), + ); + console.error('exporting data is failed due to this error:', error); + throw error; + } +} + +/** + * Retrieve all keys from the database + */ +async function getAllDatabaseKeys(): Promise { + return await MMKV.indexer.strings.getKeys(); +} + +/** + * Extract configuration and store data + */ +async function extractConfigAndStoreData( + allKeysInDB: string[], + encryptionKey: string +): Promise> { + const keysToBeExported = [ + ...allKeysInDB.filter(key => key.includes('CACHE_FETCH_ISSUER_WELLKNOWN_CONFIG_')), + MY_VCS_STORE_KEY + ]; + + const dataFromDB: Record = await fetchAndDecryptData( + keysToBeExported, + encryptionKey + ); + + return processVCMetadata(dataFromDB); +} + +/** + * Fetch and decrypt data for given keys + */ +async function fetchAndDecryptData( + keys: string[], + encryptionKey: string +): Promise> { + const dataFromDB: Record = {}; + + // Fetch encrypted data concurrently + const encryptedDataList = await Promise.all( + keys.map(key => MMKV.getItem(key)) + ); + + // Decrypt each item + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const encryptedData = encryptedDataList[i]; + + if (encryptedData) { + const decryptedData = await decryptJson(encryptionKey, encryptedData); + dataFromDB[key] = JSON.parse(decryptedData); + } + } + return dataFromDB; +} + +/** + * Process and modify VC metadata + */ +function processVCMetadata( + dataFromDB: Record +): Record { + if (dataFromDB[MY_VCS_STORE_KEY]) { + dataFromDB[MY_VCS_STORE_KEY] = dataFromDB[MY_VCS_STORE_KEY].map( + myVcMetadata => ({ ...myVcMetadata, isPinned: false }) + ); + } + return dataFromDB; +} + +/** + * Extract Verifiable Credentials + */ +async function extractVerifiableCredentials( + allKeysInDB: string[], + encryptionKey: string, + dataFromDB: Record +): Promise> { + const vcRecords: Record = {}; + const vcKeys = allKeysInDB.filter(key => key.startsWith('VC_')); + + // Process each VC key + for (const key of vcKeys) { + try { + const vc = await Storage.getItem(key, encryptionKey); + + if (vc) { + const decryptedVCData = await decryptJson(encryptionKey, vc); + const deactivatedVC = removeWalletBindingDataBeforeBackup(decryptedVCData); + vcRecords[key] = deactivatedVC; + } else { + removeNonExistentVCMetadata(dataFromDB, key); + } + } catch (error) { + throw error; + } + } + + return vcRecords; +} + +/** + * Remove metadata for non-existent VCs + */ +function removeNonExistentVCMetadata( + dataFromDB: Record, + key: string +) { + if (dataFromDB.myVCs) { + dataFromDB.myVCs = dataFromDB.myVCs.filter( + vcMetaData => + VCMetadata.fromVcMetadataString(vcMetaData).getVcKey() !== key + ); + } +} + +/** + * Remove wallet binding details from the VC + */ +function removeWalletBindingDataBeforeBackup(data: string) { + const vcData = JSON.parse(data); + vcData.walletBindingResponse = null; + vcData.publicKey = null; + vcData.privateKey = null; + return vcData; + } diff --git a/shared/backupUtils/restoreData.ts b/shared/backupUtils/restoreData.ts new file mode 100644 index 0000000000..72c6f8af21 --- /dev/null +++ b/shared/backupUtils/restoreData.ts @@ -0,0 +1,254 @@ +import { DocumentDirectoryPath } from "react-native-fs"; +import { MY_VCS_STORE_KEY } from "../constants"; +import { decryptJson, encryptJson } from "../cryptoutil/cryptoUtil"; +import fileStorage from "../fileStorage"; +import Storage, { MMKV } from "../storage"; +import { TelemetryConstants } from "../telemetry/TelemetryConstants"; +import { getErrorEventData, sendErrorEvent } from "../telemetry/TelemetryUtils"; +import { VCMetadata } from "../VCMetadata"; +import { verifyCredentialData } from "../openId4VCI/Utils"; + +export async function loadBackupData( + data: string, + encryptionKey: string, + ): Promise { + const PREV_BACKUP_STATE_PATH = `${DocumentDirectoryPath}/.prev`; + try { + await handlePreviousBackup(PREV_BACKUP_STATE_PATH, encryptionKey); + const completeBackupData = JSON.parse(data); + const backupStartState = Date.now().toString(); + await fileStorage.writeFile(PREV_BACKUP_STATE_PATH, backupStartState); + const dataFromDB = await loadVCs(completeBackupData, encryptionKey); + await updateWellKnownConfigs(dataFromDB, encryptionKey); + } catch (error) { + console.error('Error while loading backup data:', error); + throw error; + } + } + +/** + * Handle cleanup of previous backup state + * @param prevBackupStatePath Path to previous backup state file + * @param encryptionKey Encryption key + * @returns Previous restore timestamp + */ +async function handlePreviousBackup( + prevBackupStatePath: string, + encryptionKey: string, + ) { + const previousBackupExists = await fileStorage.exists(prevBackupStatePath); + if (previousBackupExists) { + const previousRestoreTimestamp = await fileStorage.readFile( + prevBackupStatePath, + ); + const timestampNum = parseInt(previousRestoreTimestamp.trim()); + await unloadVCs(encryptionKey, timestampNum); + } + } + + /** + * Unload Verifiable Credentials based on a cutoff timestamp + * @param encryptionKey Encryption key + * @param cutOffTimestamp Timestamp to use as cutoff + */ + async function unloadVCs( + encryptionKey: string, + cutOffTimestamp: number, + ) { + try { + await removeOldVCFiles(cutOffTimestamp); + await removeVCMetadataFromDB(encryptionKey, cutOffTimestamp); + } catch (error) { + console.error('Error while unloading VCs:', error); + sendErrorEvent( + getErrorEventData( + TelemetryConstants.FlowType.dataRestore, + TelemetryConstants.ErrorId.failure, + error.message, + ), + ); + throw error; + } + } + + /** + * Remove VC files created after the cutoff timestamp + * @param cutOffTimestamp Timestamp to use as cutoff + */ + async function removeOldVCFiles(cutOffTimestamp: number) { + const vcDirectory = `${DocumentDirectoryPath}/inji/VC/`; + const files = await fileStorage.getAllFilesInDirectory(vcDirectory); + + const filesToRemove = files.filter(file => { + const fileName = file.name.split('.')[0]; + const fileTimestamp = parseInt(fileName.split('_')[1]); + return fileTimestamp >= cutOffTimestamp; + }); + + await Promise.all( + filesToRemove.map(file => fileStorage.removeItem(file.path)), + ); + } + + /** + * Update MMKV store to remove VCs after cutoff timestamp + * @param encryptionKey Encryption key + * @param cutOffTimestamp Timestamp to use as cutoff + */ + async function removeVCMetadataFromDB( + encryptionKey: any, + cutOffTimestamp: number, + ) { + const myVCsEnc = await MMKV.getItem(MY_VCS_STORE_KEY, encryptionKey); + + if (myVCsEnc === null) return; + + const mmkvVCs = await decryptJson(encryptionKey, myVCsEnc); + const vcList: VCMetadata[] = JSON.parse(mmkvVCs); + const newVCList = vcList.filter( + vc => !vc.timestamp || parseInt(vc.timestamp) < cutOffTimestamp, + ); + const finalVC = await encryptJson(encryptionKey, JSON.stringify(newVCList)); + await MMKV.setItem(MY_VCS_STORE_KEY, finalVC); + } + + /** + * Handle cleanup of previous backup state + * @param completeBackupData Entire Backup data to be loaded + * @param encryptionKey Encryption key + * @returns Previous + */ + async function loadVCs( + completeBackupData: Record, + encryptionKey: string, + ): Promise | undefined> { + try { + const {VC_Records: allVCs, dataFromDB: dataFromDB} = completeBackupData; + + await processAndStoreVCs(allVCs, dataFromDB, encryptionKey); + await updateMyVcList(dataFromDB, encryptionKey); + await fileStorage.removeItemIfExist(`${DocumentDirectoryPath}/.prev`); + return dataFromDB; + } catch (error) { + console.error('Error while loading VCs:', error); + sendErrorEvent( + getErrorEventData( + TelemetryConstants.FlowType.dataBackup, + TelemetryConstants.ErrorId.failure, + error.message, + ), + ); + throw error; + } + } + + /** + * Process and store individual Verifiable Credentials + * @param allVCs All Verifiable Credentials from backup + * @param dataFromDB Database data containing VC metadata + * @param encryptionKey Encryption key + */ + async function processAndStoreVCs( + allVCs: Record, + dataFromDB: Record, + encryptionKey: string, + ) { + const vcKeys = Object.keys(allVCs); + + await Promise.all( + vcKeys.map(async key => { + const vcData = allVCs[key]; + // Add randomness to timestamp to maintain uniqueness + const timestamp = Date.now() + Math.random().toString().substring(2, 10); + const prevUnixTimeStamp = vcData.vcMetadata.timestamp; + + //verify the credential and update the metadata + const verifiableCredential = vcData.verifiableCredential?.credential || vcData.verifiableCredential; + const verificationResult = await verifyCredentialData(verifiableCredential, vcData.vcMetadata.format, vcData.vcMetadata.issuer) + const isVerified = verificationResult.isVerified; + + vcData.vcMetadata.timestamp = timestamp; + vcData.vcMetadata.isVerified = isVerified; + + //update the vcMetadata + dataFromDB.myVCs.forEach(myVcMetadata => { + if ( + myVcMetadata.requestId === vcData.vcMetadata.requestId && + myVcMetadata.timestamp === prevUnixTimeStamp + ) { + myVcMetadata.timestamp = timestamp; + myVcMetadata.isVerified = isVerified; + } + }); + + // Encrypt and store the VC + const updatedVcKey = new VCMetadata(vcData.vcMetadata).getVcKey(); + const encryptedVC = await encryptJson( + encryptionKey, + JSON.stringify(vcData), + ); + await Storage.setItem(updatedVcKey, encryptedVC, encryptionKey); + }), + ); + } + + /** + * Update MMKV store with new VC metadata + * @param dataFromDB Database data containing VC metadata + * @param encryptionKey Encryption key + */ + async function updateMyVcList( + dataFromDB: Record, + encryptionKey: string, + ) { + const dataFromMyVCKey = dataFromDB[MY_VCS_STORE_KEY]; + const encryptedMyVCKeyFromMMKV = await MMKV.getItem(MY_VCS_STORE_KEY); + + let newDataForMyVCKey: VCMetadata[]; + + if (encryptedMyVCKeyFromMMKV != null) { + const myVCKeyFromMMKV = await decryptJson( + encryptionKey, + encryptedMyVCKeyFromMMKV, + ); + + newDataForMyVCKey = [...JSON.parse(myVCKeyFromMMKV), ...dataFromMyVCKey]; + } else { + newDataForMyVCKey = dataFromMyVCKey; + } + const encryptedDataForMyVCKey = await encryptJson( + encryptionKey, + JSON.stringify(newDataForMyVCKey), + ); + + await Storage.setItem( + MY_VCS_STORE_KEY, + encryptedDataForMyVCKey, + encryptionKey, + ); + } + + /** + * Update Well Known configs for cached issuers + * @param dataFromDB Database data + * @param encryptionKey Encryption key + */ + async function updateWellKnownConfigs( + dataFromDB: Record, + encryptionKey: string, + ) { + const cacheKeys = Object.keys(dataFromDB).filter(key => + key.includes('CACHE_FETCH_ISSUER_WELLKNOWN_CONFIG_'), + ); + + await Promise.all( + cacheKeys.map(async key => { + const value = dataFromDB[key]; + const encryptedValue = await encryptJson( + encryptionKey, + JSON.stringify(value), + ); + await Storage.setItem(key, encryptedValue, encryptionKey); + }), + ); +} \ No newline at end of file diff --git a/shared/fileStorage.ts b/shared/fileStorage.ts index 7b57cf2f16..7a5798b18f 100644 --- a/shared/fileStorage.ts +++ b/shared/fileStorage.ts @@ -147,3 +147,12 @@ export async function writeToBackupFile(data: any): Promise { await writeFile(path, JSON.stringify(data)); return fileName; } + +export async function isVCStorageInitialised() : Promise { + try { + const res = await new FileStorage().getInfo(vcDirectoryPath); + return res.isDirectory(); + } catch (_) { + return false; + } +}; diff --git a/shared/openId4VCI/Utils.ts b/shared/openId4VCI/Utils.ts index 4a12c73800..fab447a4ac 100644 --- a/shared/openId4VCI/Utils.ts +++ b/shared/openId4VCI/Utils.ts @@ -1,32 +1,35 @@ -import jwtDecode from 'jwt-decode'; -import jose from 'node-jose'; -import {isIOS} from '../constants'; -import {displayType, issuerType} from '../../machines/Issuers/IssuersMachine'; -import getAllConfigurations, {CACHED_API} from '../api'; import base64url from 'base64url'; import i18next from 'i18next'; -import {getJWT, replaceCharactersInB64} from '../cryptoutil/cryptoUtil'; +import jwtDecode from 'jwt-decode'; +import jose from 'node-jose'; +import { NativeModules } from 'react-native'; +import { vcVerificationBannerDetails } from '../../components/BannerNotificationContainer'; +import { VCProcessor } from '../../components/VC/common/VCProcessor'; +import { + BOTTOM_SECTION_FIELDS_WITH_DETAILED_ADDRESS_FIELDS, + DETAIL_VIEW_ADD_ON_FIELDS, + getCredentialTypeFromWellKnown, +} from '../../components/VC/common/VCUtils'; import i18n from '../../i18n'; +import { displayType, issuerType } from '../../machines/Issuers/IssuersMachine'; +import { getVerifiableCredential } from '../../machines/VerifiableCredential/VCItemMachine/VCItemSelectors'; import { + Credential, CredentialTypes, CredentialWrapper, VerifiableCredential, } from '../../machines/VerifiableCredential/VCMetaMachine/vc'; -import { - BOTTOM_SECTION_FIELDS_WITH_DETAILED_ADDRESS_FIELDS, - DETAIL_VIEW_ADD_ON_FIELDS, - getCredentialTypeFromWellKnown, -} from '../../components/VC/common/VCUtils'; -import {getVerifiableCredential} from '../../machines/VerifiableCredential/VCItemMachine/VCItemSelectors'; -import {vcVerificationBannerDetails} from '../../components/BannerNotificationContainer'; -import {getErrorEventData, sendErrorEvent} from '../telemetry/TelemetryUtils'; -import {TelemetryConstants} from '../telemetry/TelemetryConstants'; -import {NativeModules} from 'react-native'; -import {KeyTypes} from '../cryptoutil/KeyTypes'; -import {VCFormat} from '../VCFormat'; -import {UnsupportedVcFormat} from '../error/UnsupportedVCFormat'; -import {VCMetadata} from '../VCMetadata'; -import {VCProcessor} from '../../components/VC/common/VCProcessor'; +import getAllConfigurations, { CACHED_API } from '../api'; +import { isIOS } from '../constants'; +import { getJWT } from '../cryptoutil/cryptoUtil'; +import { KeyTypes } from '../cryptoutil/KeyTypes'; +import { UnsupportedVcFormat } from '../error/UnsupportedVCFormat'; +import { TelemetryConstants } from '../telemetry/TelemetryConstants'; +import { getErrorEventData, sendErrorEvent } from '../telemetry/TelemetryUtils'; +import { isMockVC } from '../Utils'; +import { VCFormat } from '../VCFormat'; +import { VerificationErrorMessage, VerificationErrorType, verifyCredential } from '../vcjs/verifyCredential'; +import { VCMetadata } from '../VCMetadata'; export const Protocols = { OpenId4VCI: 'OpenId4VCI', @@ -438,3 +441,21 @@ export function getMatchingCredentialIssuerMetadata( `Selected credential type - ${credentialConfigurationId} is not available in wellknown config supported credentials list`, ); } + +export async function verifyCredentialData( + credential: Credential, + credentialFormat: string, + issuerId: string +) { + + if (credentialFormat === VCFormat.mso_mdoc || !isMockVC(issuerId)) { + const verificationResult = await verifyCredential(credential, credentialFormat); + return verificationResult; + } else { + return { + isVerified: true, + verificationMessage: VerificationErrorMessage.NO_ERROR, + verificationErrorCode: VerificationErrorType.NO_ERROR, + }; + } +} \ No newline at end of file diff --git a/shared/storage.ts b/shared/storage.ts index 120268db88..800c7b6b25 100644 --- a/shared/storage.ts +++ b/shared/storage.ts @@ -1,10 +1,20 @@ -import {MMKVLoader} from 'react-native-mmkv-storage'; -import getAllConfigurations from './api'; +import { NativeModules } from 'react-native'; import { getFreeDiskStorageOldSync, getFreeDiskStorageSync, } from 'react-native-device-info'; -import {NativeModules} from 'react-native'; +import { MMKVLoader } from 'react-native-mmkv-storage'; +import getAllConfigurations from './api'; +import { exportData } from './backupUtils/backupData'; +import { loadBackupData } from './backupUtils/restoreData'; +import { BYTES_IN_MEGABYTE } from './commonUtil'; +import { + androidVersion, + API_CACHED_STORAGE_KEYS, + ENOENT, + isAndroid, + SETTINGS_STORE_KEY +} from './constants'; import { decryptJson, encryptJson, @@ -12,34 +22,18 @@ import { hmacSHA, isHardwareKeystoreExists, } from './cryptoutil/cryptoUtil'; -import {VCMetadata} from './VCMetadata'; -import { - androidVersion, - isAndroid, - MY_VCS_STORE_KEY, - SETTINGS_STORE_KEY, - ENOENT, - API_CACHED_STORAGE_KEYS, - BASE_36, -} from './constants'; import FileStorage, { - getFilePath, getDirectorySize, + getFilePath, vcDirectoryPath, } from './fileStorage'; -import {__AppId} from './GlobalVariables'; -import {getErrorEventData, sendErrorEvent} from './telemetry/TelemetryUtils'; -import {TelemetryConstants} from './telemetry/TelemetryConstants'; -import {BYTES_IN_MEGABYTE} from './commonUtil'; -import fileStorage from './fileStorage'; -import {DocumentDirectoryPath, ReadDirItem} from 'react-native-fs'; -import {verifyCredential} from './vcjs/verifyCredential'; -import {Credential} from '../machines/VerifiableCredential/VCMetaMachine/vc'; -import {VCFormat} from './VCFormat'; -import {isMockVC} from './Utils'; +import { __AppId } from './GlobalVariables'; +import { TelemetryConstants } from './telemetry/TelemetryConstants'; +import { getErrorEventData, sendErrorEvent } from './telemetry/TelemetryUtils'; +import { VCMetadata } from './VCMetadata'; export const MMKV = new MMKVLoader().initialize(); -const {RNSecureKeystoreModule} = NativeModules; +const { RNSecureKeystoreModule } = NativeModules; async function generateHmac( encryptionKey: string, @@ -52,111 +46,14 @@ async function generateHmac( } class Storage { - static exportData = async (encryptionKey: string) => { - try { - const completeBackupData = {}; - let dataFromDB: Record = {}; - - const allKeysInDB = await MMKV.indexer.strings.getKeys(); - const keysToBeExported = allKeysInDB.filter(key => - key.includes('CACHE_FETCH_ISSUER_WELLKNOWN_CONFIG_'), - ); - keysToBeExported?.push(MY_VCS_STORE_KEY); - - const encryptedDataPromises = keysToBeExported.map(key => - MMKV.getItem(key), - ); - const encryptedDataList = await Promise.all(encryptedDataPromises); - for (let index = 0; index < keysToBeExported.length; index++) { - const key = keysToBeExported[index]; - let encryptedData = encryptedDataList[index]; - if (encryptedData != null) { - const decryptedData = await decryptJson(encryptionKey, encryptedData); - dataFromDB[key] = JSON.parse(decryptedData); - } - } - dataFromDB[MY_VCS_STORE_KEY].map(myVcMetadata => { - myVcMetadata.isPinned = false; - }); - - completeBackupData['VC_Records'] = {}; - - let vcKeys = allKeysInDB.filter(key => key.indexOf('VC_') === 0); - for (let ind in vcKeys) { - const key = vcKeys[ind]; - const vc = await this.getItem(key, encryptionKey); - - if (vc) { - const decryptedVCData = await decryptJson(encryptionKey, vc); - const deactivatedVC = - removeWalletBindingDataBeforeBackup(decryptedVCData); - completeBackupData['VC_Records'][key] = deactivatedVC; - } else { - dataFromDB.myVCs = dataFromDB.myVCs.filter(vcMetaData => { - return ( - VCMetadata.fromVcMetadataString(vcMetaData).getVcKey() !== key - ); - }); - } - } - completeBackupData['dataFromDB'] = dataFromDB; - - return completeBackupData; - } catch (error) { - sendErrorEvent( - getErrorEventData( - TelemetryConstants.FlowType.dataBackup, - error.message, - error.stack, - ), - ); - console.error('exporting data is failed due to this error:', error); - throw error; - } + static backupData = async (encryptionKey: string) => { + return await exportData(encryptionKey) }; - static loadBackupData = async (data, encryptionKey) => { - try { - // 0. check for previous backup states - const prevBkpState = `${DocumentDirectoryPath}/.prev`; - const previousBackupExists = await fileStorage.exists(prevBkpState); - let previousRestoreTimestamp: string = ''; - if (previousBackupExists) { - // 0. Remove partial restored files - previousRestoreTimestamp = await fileStorage.readFile(prevBkpState); - previousRestoreTimestamp = previousRestoreTimestamp.trim(); - this.unloadVCs(encryptionKey, parseInt(previousRestoreTimestamp)); - } - // 1. opening the file - const completeBackupData = JSON.parse(data); - // 2. Load and store VC_records & MMKV things - const backupStartState = Date.now().toString(); - // record the state to help with cleanup activities post partial backup - await fileStorage.writeFile(prevBkpState, backupStartState); - const dataFromDB = await Storage.loadVCs( - completeBackupData, - encryptionKey, - ); - // 3. Update the Well Known configs of the VCs - const allKeysFromDB = Object.keys(dataFromDB); - const cacheKeys = allKeysFromDB.filter(key => - key.includes('CACHE_FETCH_ISSUER_WELLKNOWN_CONFIG_'), - ); - cacheKeys.forEach(async key => { - const value = dataFromDB[key]; - const encryptedValue = await encryptJson( - encryptionKey, - JSON.stringify(value), - ); - await this.setItem(key, encryptedValue, encryptionKey); - return true; - }); - } catch (error) { - console.error('Error while loading backup data ', error); - return error; - } - }; + static async restoreBackUpData(data: string, encryptionKey: string): Promise { + return await loadBackupData(data, encryptionKey) + } static fetchAllWellknownConfig = async (encryptionKey: string) => { let wellknownConfigData: Record = {}; @@ -177,15 +74,6 @@ class Storage { return wellknownConfigData; }; - static isVCStorageInitialised = async (): Promise => { - try { - const res = await FileStorage.getInfo(vcDirectoryPath); - return res.isDirectory(); - } catch (_) { - return false; - } - }; - static setItem = async ( key: string, data: string, @@ -265,157 +153,32 @@ class Storage { } }; - /** - * unloadVCs will remove a set of VCs against a particular time range - * - * @param cutOffTimestamp the timestamp of the VC backup start time to current time - */ - private static async unloadVCs(encryptionKey: any, cutOffTimestamp: number) { - try { - // 1. Find the VCs in the inji directory which have the said timestamp - const file: ReadDirItem[] = await fileStorage.getAllFilesInDirectory( - `${DocumentDirectoryPath}/inji/VC/`, - ); - const isGreaterThanEq = function (fName: string, ts: number): boolean { - fName = fName.split('.')[0]; - const curr = fName.split('_')[1]; - return parseInt(curr) >= ts; - }; - for (let i = 0; i < file.length; i++) { - const f = file[i]; - if (isGreaterThanEq(f.name, cutOffTimestamp)) { - await fileStorage.removeItem(f.path); - } - } - // TODO: should this be done via the Store state machine to avoid popups? - // 3. Remove the keys from MMKV which have the same timestamp - let myVCsEnc = await MMKV.getItem(MY_VCS_STORE_KEY, encryptionKey); - if (myVCsEnc !== null) { - let mmkvVCs = await decryptJson(encryptionKey, myVCsEnc); - let vcList: VCMetadata[] = JSON.parse(mmkvVCs); - let newVCList: VCMetadata[] = []; - vcList.forEach(d => { - if (d.timestamp && parseInt(d.timestamp) < cutOffTimestamp) { - newVCList.push(d); - } - }); - const finalVC = await encryptJson( - encryptionKey, - JSON.stringify(newVCList), - ); - await MMKV.setItem(MY_VCS_STORE_KEY, finalVC); + static removeItem = async (key: string) => { + if (VCMetadata.isVCKey(key)) { + const path = getFilePath(key); + const isFileExists = await FileStorage.exists(path); + if (isFileExists) { + return await FileStorage.removeItem(path); + } else { + console.warn('file not exist`s'); } - } catch (e) { - console.error('error while unloadVcs:', e); - sendErrorEvent( - getErrorEventData( - TelemetryConstants.FlowType.dataRestore, - TelemetryConstants.ErrorId.failure, - e.message, - ), - ); } - } - - private static async verifyCredential( - verifiableCredential: Credential, - format: string, - issuer: string, - ) { - let isVerified = true; - //TODO: Remove bypassing verification of mock VCs once mock VCs are verifiable - if (format === VCFormat.mso_mdoc || !isMockVC(issuer)) { - const verificationResult = await verifyCredential( - verifiableCredential, - format, - ); - isVerified = verificationResult.isVerified; - } - return isVerified; - } + MMKV.removeItem(key); + }; - private static async loadVCs(completeBackupData: {}, encryptionKey: any) { + static clear = async () => { try { - const allVCs = completeBackupData['VC_Records']; - const allVCKeys = Object.keys(allVCs); - const dataFromDB = completeBackupData['dataFromDB']; - - // 0. Check for VC presense in the store - // 1. store the VCs and the HMAC - // 2. Verify the VC and update the result - - await Promise.all( - allVCKeys.map(async key => { - const vc = allVCs[key]; - const ts = - Date.now() + Math.random().toString(BASE_36).substring(2, 7); - const prevUnixTimeStamp = vc.vcMetadata.timestamp; - - const isVerified = await Storage.verifyCredential( - vc.verifiableCredential?.credential || vc.verifiableCredential, - vc.vcMetadata.format, - vc.vcMetadata.issuer, - ); - vc.vcMetadata.timestamp = ts; - vc.vcMetadata.isVerified = isVerified; - - dataFromDB.myVCs.map(async myVcMetadata => { - if ( - myVcMetadata.requestId === vc.vcMetadata.requestId && - myVcMetadata.timestamp === prevUnixTimeStamp - ) { - myVcMetadata.timestamp = ts; - } - myVcMetadata.isVerified = isVerified; - }); - const updatedVcKey = new VCMetadata(vc.vcMetadata).getVcKey(); - - const encryptedVC = await encryptJson( - encryptionKey, - JSON.stringify(vc), - ); - // Save the VC to disk - await this.setItem(updatedVcKey, encryptedVC, encryptionKey); - }), - ); - // 2. Update myVCsKey - const dataFromMyVCKey = dataFromDB[MY_VCS_STORE_KEY]; - const encryptedMyVCKeyFromMMKV = await MMKV.getItem(MY_VCS_STORE_KEY); - let newDataForMyVCKey: VCMetadata[] = []; - if (encryptedMyVCKeyFromMMKV != null) { - const myVCKeyFromMMKV = await decryptJson( - encryptionKey, - encryptedMyVCKeyFromMMKV, - ); - newDataForMyVCKey = [ - ...JSON.parse(myVCKeyFromMMKV), - ...dataFromMyVCKey, - ]; - } else { - newDataForMyVCKey = dataFromMyVCKey; - } - const encryptedDataForMyVCKey = await encryptJson( - encryptionKey, - JSON.stringify(newDataForMyVCKey), - ); - await this.setItem( - MY_VCS_STORE_KEY, - encryptedDataForMyVCKey, - encryptionKey, - ); - await fileStorage.removeItemIfExist(`${DocumentDirectoryPath}/.prev`); - return dataFromDB; + (await FileStorage.exists(`${vcDirectoryPath}`)) && + (await FileStorage.removeItem(`${vcDirectoryPath}`)); + const settings = await MMKV.getItem(SETTINGS_STORE_KEY); + const appId = JSON.parse(settings).appId; + __AppId.setValue(appId); + MMKV.clearStore(); + await MMKV.setItem(SETTINGS_STORE_KEY, JSON.stringify({ appId: appId })); } catch (e) { - console.error('error while loading Vcs:', e); - sendErrorEvent( - getErrorEventData( - TelemetryConstants.FlowType.dataBackup, - TelemetryConstants.ErrorId.failure, - e.message, - ), - ); + console.error('Error Occurred while Clearing Storage.', e); } - } + }; private static async isVCAlreadyDownloaded( key: string, @@ -488,7 +251,6 @@ class Storage { return await FileStorage.writeFile(path, data); } - // TODO: INJI-612 refactor private static async storeVcHmac( encryptionKey: string, data: string, @@ -498,60 +260,10 @@ class Storage { const encryptedHMACofVC = await encryptJson(encryptionKey, HMACofVC); await MMKV.setItem(key, encryptedHMACofVC); } - - static removeItem = async (key: string) => { - if (VCMetadata.isVCKey(key)) { - const path = getFilePath(key); - const isFileExists = await FileStorage.exists(path); - if (isFileExists) { - return await FileStorage.removeItem(path); - } else { - console.warn('file not exist`s'); - } - } - MMKV.removeItem(key); - }; - - static clear = async () => { - try { - (await FileStorage.exists(`${vcDirectoryPath}`)) && - (await FileStorage.removeItem(`${vcDirectoryPath}`)); - const settings = await MMKV.getItem(SETTINGS_STORE_KEY); - const appId = JSON.parse(settings).appId; - __AppId.setValue(appId); - MMKV.clearStore(); - await MMKV.setItem(SETTINGS_STORE_KEY, JSON.stringify({appId: appId})); - } catch (e) { - console.error('Error Occurred while Clearing Storage.', e); - } - }; - - static isMinimumLimitReached = async (limitInMB: string) => { - const configurations = await getAllConfigurations(); - if (!configurations[limitInMB]) return false; - - const minimumStorageLimitInBytes = - configurations[limitInMB] * BYTES_IN_MEGABYTE; - - const freeDiskStorageInBytes = - isAndroid() && androidVersion < 29 - ? getFreeDiskStorageOldSync() - : getFreeDiskStorageSync(); - - return freeDiskStorageInBytes <= minimumStorageLimitInBytes; - }; } export default Storage; -function removeWalletBindingDataBeforeBackup(data: string) { - const vcData = JSON.parse(data); - vcData.walletBindingResponse = null; - vcData.publicKey = null; - vcData.privateKey = null; - return vcData; -} - export async function isMinimumLimitForBackupReached() { try { const directorySize = await getDirectorySize(vcDirectoryPath); @@ -573,5 +285,20 @@ export async function isMinimumLimitForBackupRestorationReached() { // APIs: // 1. CloudStorage.stat(file, context) // 2. getUncompressedSize() - return await Storage.isMinimumLimitReached('minStorageRequired'); + return await isMinimumStorageLimitReached('minStorageRequired'); } + +export async function isMinimumStorageLimitReached(limitInMB: string) { + const configurations = await getAllConfigurations(); + if (!configurations[limitInMB]) return false; + + const minimumStorageLimitInBytes = + configurations[limitInMB] * BYTES_IN_MEGABYTE; + + const freeDiskStorageInBytes = + isAndroid() && androidVersion < 29 + ? getFreeDiskStorageOldSync() + : getFreeDiskStorageSync(); + + return freeDiskStorageInBytes <= minimumStorageLimitInBytes; +}; diff --git a/shared/vcjs/verifyCredential.ts b/shared/vcjs/verifyCredential.ts index dc958c8bd4..db7937651d 100644 --- a/shared/vcjs/verifyCredential.ts +++ b/shared/vcjs/verifyCredential.ts @@ -32,82 +32,15 @@ const vcVerifier = NativeModules.VCVerifierModule; export async function verifyCredential( verifiableCredential: Credential, - credentialFormat: String, + credentialFormat: string ): Promise { try { - //ToDo - Have to remove else part once Vc Verifier Library is built for Swift if (isAndroid()) { - let vcVerifierResult = await vcVerifier.verifyCredentials( - typeof verifiableCredential === 'string' - ? verifiableCredential - : JSON.stringify(verifiableCredential), - credentialFormat, - ); - return handleVcVerifierResponse(vcVerifierResult, verifiableCredential); - } else { - //ToDo - Have to remove the condition once Vc Verifier Library is built for Swift to validate mso_mdoc - if (credentialFormat == VCFormat.mso_mdoc) { - return { - isVerified: true, - verificationMessage: VerificationErrorMessage.NO_ERROR, - verificationErrorCode: VerificationErrorType.NO_ERROR, - }; - } - let purpose: PublicKeyProofPurpose | AssertionProofPurpose; - const proof = verifiableCredential.proof; - - switch (proof.proofPurpose) { - case ProofPurpose.PublicKey: - purpose = new PublicKeyProofPurpose(); - break; - case ProofPurpose.Assertion: - purpose = new AssertionProofPurpose(); - break; - } - - let suite: Ed25519Signature2018 | RsaSignature2018; - const suiteOptions = { - verificationMethod: proof.verificationMethod, - date: proof.created, - }; - switch (proof.type) { - case ProofType.RSA: { - suite = new RsaSignature2018(suiteOptions); - break; - } - case ProofType.ED25519_2018: { - suite = new Ed25519Signature2018(suiteOptions); - break; - } - /* - Since Digital Bazaar library is not able to verify ProofType: "Ed25519Signature2020", - defaulting it to return true until VcVerifier is implemented for iOS. - */ - case ProofType.ED25519_2020: { - return { - isVerified: true, - verificationMessage: VerificationErrorMessage.NO_ERROR, - verificationErrorCode: VerificationErrorType.NO_ERROR, - }; - } - } - - const vcjsOptions = { - purpose, - suite, - credential: verifiableCredential, - documentLoader: jsonld.documentLoaders.xhr(), - }; - - //ToDo - Have to remove once range error is fixed during verification - const result = await vcjs.verifyCredential(vcjsOptions); - return handleResponse(result, verifiableCredential); + return await verifyCredentialForAndroid(verifiableCredential, credentialFormat); } + return await verifyCredentialForIos(verifiableCredential, credentialFormat); } catch (error) { - console.error( - 'Error occurred while verifying the VC using digital bazaar:', - error, - ); + console.error('Error occurred during credential verification:', error); return { isVerified: false, @@ -117,6 +50,73 @@ export async function verifyCredential( } } +async function verifyCredentialForAndroid( + verifiableCredential: Credential, + credentialFormat: string +): Promise { + const credentialString = typeof verifiableCredential === 'string' + ? verifiableCredential + : JSON.stringify(verifiableCredential); + + const vcVerifierResult = await vcVerifier.verifyCredentials(credentialString, credentialFormat); + return handleVcVerifierResponse(vcVerifierResult, verifiableCredential); +} + +async function verifyCredentialForIos( + verifiableCredential: Credential, + credentialFormat: string +): Promise { + if (credentialFormat === VCFormat.mso_mdoc) { + return createSuccessfulVerificationResult(); + } + /* + Since Digital Bazaar library is not able to verify ProofType: "Ed25519Signature2020", + defaulting it to return true until VcVerifier is implemented for iOS. + */ + if (verifiableCredential.proof.type === ProofType.ED25519_2020) { + return createSuccessfulVerificationResult(); + } + + const purpose = getPurposeFromProof(verifiableCredential.proof.proofPurpose); + const suite = selectVerificationSuite(verifiableCredential.proof); + const vcjsOptions = { + purpose, + suite, + credential: verifiableCredential, + documentLoader: jsonld.documentLoaders.xhr(), + }; + + const result = await vcjs.verifyCredential(vcjsOptions); + return handleResponse(result, verifiableCredential); +} + +function getPurposeFromProof(proofPurpose) { + switch (proofPurpose) { + case ProofPurpose.PublicKey: + return new vcjs.PublicKeyProofPurpose(); + case ProofPurpose.Assertion: + return new vcjs.AssertionProofPurpose(); + default: + throw new Error('Unsupported proof purpose'); + } +} + +function selectVerificationSuite(proof: any) { + const suiteOptions = { + verificationMethod: proof.verificationMethod, + date: proof.created, + }; + + switch (proof.type) { + case ProofType.RSA: + return new RsaSignature2018(suiteOptions); + case ProofType.ED25519_2018: + return new Ed25519Signature2018(suiteOptions); + default: + throw new Error('Unsupported proof type'); + } +} + function handleResponse( result: any, verifiableCredential: VerifiableCredential | Credential, @@ -159,8 +159,7 @@ function handleVcVerifierResponse( ): VerificationResult { try { if (!verificationResult.verificationStatus) { - verificationResult.verificationErrorCode = - verificationResult.verificationErrorCode === '' + verificationResult.verificationErrorCode = verificationResult.verificationErrorCode === '' ? VerificationErrorType.GENERIC_TECHNICAL_ERROR : verificationResult.verificationErrorCode; sendVerificationErrorEvent( @@ -187,6 +186,14 @@ function handleVcVerifierResponse( } } +function createSuccessfulVerificationResult(): VerificationResult { + return { + isVerified: true, + verificationMessage: VerificationErrorMessage.NO_ERROR, + verificationErrorCode: VerificationErrorType.NO_ERROR, + }; +} + function sendVerificationErrorEvent( errorMessage: string, verifiableCredential: any,