diff --git a/native/backup/conversion-utils.js b/native/backup/conversion-utils.js index df8e33355..fa00dd407 100644 --- a/native/backup/conversion-utils.js +++ b/native/backup/conversion-utils.js @@ -1,19 +1,24 @@ // @flow import { commUtilsModule } from '../native-modules.js'; import { arrayBufferFromBlob } from '../utils/blob-utils-module.js'; function getBackupBytesFromBlob(blob: Blob): Uint8Array { const buffer = arrayBufferFromBlob(blob); const str = commUtilsModule.decodeUTF8ArrayBufferToString(buffer); const decodedBuffer = commUtilsModule.base64DecodeBuffer(str); return new Uint8Array(decodedBuffer); } function convertObjToBytes(obj: T): Uint8Array { const objStr = JSON.stringify(obj); const objBuffer = commUtilsModule.encodeStringToUTF8ArrayBuffer(objStr ?? ''); return new Uint8Array(objBuffer); } -export { getBackupBytesFromBlob, convertObjToBytes }; +function convertBytesToObj(bytes: Uint8Array): T { + const str = commUtilsModule.decodeUTF8ArrayBufferToString(bytes.buffer); + return JSON.parse(str); +} + +export { getBackupBytesFromBlob, convertObjToBytes, convertBytesToObj }; diff --git a/native/backup/encryption.js b/native/backup/encryption.js index 46d3abd6d..f8dcb6313 100644 --- a/native/backup/encryption.js +++ b/native/backup/encryption.js @@ -1,34 +1,62 @@ // @flow import { hexToUintArray } from 'lib/media/data-utils.js'; -import type { Backup, BackupEncrypted } from 'lib/types/backup-types.js'; +import type { + Backup, + BackupEncrypted, + UserData, + UserKeys, +} from 'lib/types/backup-types.js'; -import { convertObjToBytes } from './conversion-utils.js'; +import { convertBytesToObj, convertObjToBytes } from './conversion-utils.js'; import { fetchNativeKeychainCredentials } from '../account/native-credentials.js'; import { commCoreModule } from '../native-modules.js'; import * as AES from '../utils/aes-crypto-module.js'; async function getBackupKey(backupID: string): Promise { const nativeCredentials = await fetchNativeKeychainCredentials(); if (!nativeCredentials) { throw new Error('Native credentials are missing'); } const { password } = nativeCredentials; const backupKey = await commCoreModule.computeBackupKey(password, backupID); return new Uint8Array(backupKey); } async function encryptBackup(backup: Backup): Promise { const { backupID, userKeys, userData } = backup; const userKeysBytes = convertObjToBytes(userKeys); const backupKey = await getBackupKey(backupID); const ct1 = AES.encrypt(backupKey, userKeysBytes); const userDataBytes = convertObjToBytes(userData); const backupDataKey = hexToUintArray(userKeys.backupDataKey); const ct2 = AES.encrypt(backupDataKey, userDataBytes); return { backupID, userKeys: ct1, userData: ct2 }; } -export { getBackupKey, encryptBackup }; +async function decryptUserKeys( + backupID: string, + userKeysBytes: ArrayBuffer, +): Promise { + const backupKey = await getBackupKey(backupID); + const decryptedUserKeys = AES.decrypt( + backupKey, + new Uint8Array(userKeysBytes), + ); + return convertBytesToObj(decryptedUserKeys); +} + +async function decryptUserData( + backupDataKey: string, + userDataBytes: ArrayBuffer, +): Promise { + const decryptedUserData = AES.decrypt( + hexToUintArray(backupDataKey), + new Uint8Array(userDataBytes), + ); + return convertBytesToObj(decryptedUserData); +} + +export { getBackupKey, encryptBackup, decryptUserKeys, decryptUserData };