diff --git a/.talismanrc b/.talismanrc index 39636287cc..3ead8f72f5 100644 --- a/.talismanrc +++ b/.talismanrc @@ -36,9 +36,9 @@ fileignoreconfig: - filename: shared/telemetry/TelemetryUtils.js checksum: ffe9aac2dcc590b98b0d588885c088eff189504ade653a77f74b67312bfd27ad - filename: shared/fileStorage.ts - checksum: 07cb337dc1d5b0f0eef56270ac4f4f589260ee5e490183c024cf98a2aeafb139 + checksum: f86dc7aa4a69e7109310e7ab5529a8599f38f15eb79f3f4da545aceaaf90d731 - filename: shared/storage.ts - checksum: c8d874aa373bdf526bf59192139822f56915e702ef673bac4e0d7549b0fea3d0 + checksum: c31270346f2ef717a31168a93d0311ce6f925434eb613ec7cf86553222630cdb - filename: screens/Issuers/IssuersScreen.tsx checksum: 9c53e3770dbefe26e0de67ee4b7d5cc9c52d9823cbb136a1a5104dcb0a101071 - filename: ios/Podfile.lock diff --git a/shared/fileStorage.ts b/shared/fileStorage.ts index 426f121977..e2835e80b2 100644 --- a/shared/fileStorage.ts +++ b/shared/fileStorage.ts @@ -56,4 +56,14 @@ export const getFilePath = (key: string) => { return `${vcDirectoryPath}/${key}.txt`; }; +//TODO: added temporarily for INJI-612 +export const getFilePathOfHmac = (key: string) => { + return `${vcDirectoryPath}/${key}.hmac`; +}; + +//TODO: added temporarily for INJI-612 +export const getFilePathOfEncryptedHmac = (key: string) => { + return `${vcDirectoryPath}/${key}.hmace`; +}; + export const vcDirectoryPath = `${DocumentDirectoryPath}/inji/VC`; diff --git a/shared/storage.ts b/shared/storage.ts index bd458f2d61..fae050aefd 100644 --- a/shared/storage.ts +++ b/shared/storage.ts @@ -21,9 +21,19 @@ import { RECEIVED_VCS_STORE_KEY, SETTINGS_STORE_KEY, } from './constants'; -import FileStorage, {getFilePath, vcDirectoryPath} from './fileStorage'; +import FileStorage, { + getFilePath, + getFilePathOfEncryptedHmac, + getFilePathOfHmac, + vcDirectoryPath, +} from './fileStorage'; import {__AppId} from './GlobalVariables'; -import {getErrorEventData, sendErrorEvent} from './telemetry/TelemetryUtils'; +import { + getErrorEventData, + getImpressionEventData, + sendErrorEvent, + sendImpressionEvent, +} from './telemetry/TelemetryUtils'; import {TelemetryConstants} from './telemetry/TelemetryConstants'; export const MMKV = new MMKVLoader().initialize(); @@ -94,15 +104,6 @@ class Storage { ); console.debug('[Inji-406]: VC key: ', key); console.debug('[Inji-406]: is Data null', data === null); - getItem(MY_VCS_STORE_KEY, [], encryptionKey).then(res => { - console.debug('[Inji-406]: vcKeys are ', JSON.stringify(res)); - }); - getItem(RECEIVED_VCS_STORE_KEY, null, encryptionKey).then(res => { - console.debug( - '[Inji-406]: received vcKeys is ', - JSON.stringify(res), - ); - }); } return isCorrupted ? null : data; @@ -155,12 +156,40 @@ class Storage { encryptionKey: string, data: string, ) { - const storedHMACofCurrentVC = await this.readHmacForVC(key, encryptionKey); + // TODO: INJI-612 refactor + const storedHMACofCurrentVC = await this.readHmacForDataCorruptionCheck( + key, + encryptionKey, + ); const HMACofVC = await generateHmac(encryptionKey, data); + const hmacStoredinFile = await this.readHmacForVCFromFile(key); if (HMACofVC !== storedHMACofCurrentVC) { - console.debug( - `[Inji-406]: storedHmacOfCurrentVC: ${storedHMACofCurrentVC}, HMACofVC: ${HMACofVC}`, + if (__DEV__) { + sendImpressionEvent( + getImpressionEventData('VC Corruption Event', 'VC Download', { + key: key, + 'HMAC stored in MMKV': this.hexEncode(storedHMACofCurrentVC!), + 'Length HMAC stored in MMKV': storedHMACofCurrentVC?.length, + 'HMAC of VC': this.hexEncode(HMACofVC), + 'Length of HMAC of VC': HMACofVC.length, + 'HMAC stored in file': this.hexEncode(hmacStoredinFile), + 'File vs mmkv data': + hmacStoredinFile === this.hexEncode(storedHMACofCurrentVC!), + }), + ); + } + console.log( + `VC corruption Details: ${JSON.stringify({ + key: key, + 'HMAC stored in MMKV': this.hexEncode(storedHMACofCurrentVC!), + 'Length HMAC stored in MMKV': storedHMACofCurrentVC?.length, + 'HMAC of VC': this.hexEncode(HMACofVC), + 'Length of HMAC of VC': HMACofVC.length, + 'HMAC stored in file': this.hexEncode(hmacStoredinFile), + 'File vs mmkv data': + hmacStoredinFile === this.hexEncode(storedHMACofCurrentVC!), + })}`, ); } @@ -175,6 +204,57 @@ class Storage { return null; } + //TODO: added temporarily for INJI-612 + private static async readHmacForVCFromFile(key: string) { + const HMACofCurrentVC = await FileStorage.readFile(getFilePathOfHmac(key)); + return HMACofCurrentVC; + } + + private static async readHmacForDataCorruptionCheck( + key: string, + encryptionKey: string, + ) { + const encryptedHMACofCurrentVC = await MMKV.getItem(key); + const encryptedHMACofCurrentVCFromMMKVFile = await FileStorage.readFile( + getFilePathOfEncryptedHmac(key), + ); + + if (encryptedHMACofCurrentVC !== encryptedHMACofCurrentVCFromMMKVFile) { + if (__DEV__) { + sendImpressionEvent( + getImpressionEventData('Encrypted HMac Corruption', 'VC Download', { + key: key, + 'Encrypted HMAC of Current VC from MMKV store': + encryptedHMACofCurrentVC, + 'Encrypted HMAC of Current VC from file': + encryptedHMACofCurrentVCFromMMKVFile, + 'encryptedHMACofCurrentVC vs encryptedHMACofCurrentVCFromMMKVFile': `${ + encryptedHMACofCurrentVCFromMMKVFile === encryptedHMACofCurrentVC + }`, + }), + ); + } + + console.log( + `VC corruption Details: ${{ + key: key, + 'Encrypted HMAC of Current VC from MMKV store': + encryptedHMACofCurrentVC, + 'Encrypted HMAC of Current VC from file': + encryptedHMACofCurrentVCFromMMKVFile, + 'encryptedHMACofCurrentVC vs encryptedHMACofCurrentVCFromMMKVFile': `${ + encryptedHMACofCurrentVCFromMMKVFile === encryptedHMACofCurrentVC + }`, + }}`, + ); + } + + if (encryptedHMACofCurrentVC) { + return decryptJson(encryptionKey, encryptedHMACofCurrentVC); + } + return null; + } + private static async readVCFromFile(key: string) { return await FileStorage.readFile(getFilePath(key)); } @@ -185,14 +265,31 @@ class Storage { return await FileStorage.writeFile(path, data); } + // TODO: INJI-612 refactor + private static hexEncode(inp: string) { + var hex, i; + var result = ''; + for (i = 0; i < inp.length; i++) { + hex = inp.charCodeAt(i).toString(16); + result += ('000' + hex).slice(-4); + } + return result; + } + + // TODO: INJI-612 refactor private static async storeVcHmac( encryptionKey: string, data: string, key: string, ) { const HMACofVC = await generateHmac(encryptionKey, data); - console.log('[Inji-406]: Updating hmac of the vc: ', HMACofVC); const encryptedHMACofVC = await encryptJson(encryptionKey, HMACofVC); + const keyOfEncodedHmacStorage = getFilePathOfHmac(key); + const keyOfEncryptedHmacStorage = getFilePathOfEncryptedHmac(key); + + const encodedHMACofVC = this.hexEncode(HMACofVC); + await FileStorage.writeFile(keyOfEncodedHmacStorage, encodedHMACofVC); + await FileStorage.writeFile(keyOfEncryptedHmacStorage, encryptedHMACofVC); await MMKV.setItem(key, encryptedHMACofVC); }