Page MenuHomePhabricator

D10067.id33940.diff
No OneTemporary

D10067.id33940.diff

diff --git a/lib/types/backup-types.js b/lib/types/backup-types.js
--- a/lib/types/backup-types.js
+++ b/lib/types/backup-types.js
@@ -25,6 +25,6 @@
export type BackupEncrypted = {
+backupID: string,
- +userKeys: Uint8Array,
- +userData: Uint8Array,
+ +userKeys: string,
+ +userData: string,
};
diff --git a/native/backup/api.js b/native/backup/api.js
--- a/native/backup/api.js
+++ b/native/backup/api.js
@@ -8,22 +8,24 @@
import { toBase64URL } from 'lib/utils/base64.js';
import { handleHTTPResponseError } from 'lib/utils/services-utils.js';
-import { getBackupBytesFromBlob } from './conversion-utils.js';
+import { getBackupStringFromBlob } from './conversion-utils.js';
import { commUtilsModule } from '../native-modules.js';
function getBackupFormData(backup: BackupEncrypted): FormData {
const { backupID, userKeys, userData } = backup;
- const userKeysHash = commUtilsModule.sha256(userKeys.buffer);
- const userDataHash = commUtilsModule.sha256(userData.buffer);
- const userKeysStr = commUtilsModule.base64EncodeBuffer(userKeys.buffer);
- const userDataStr = commUtilsModule.base64EncodeBuffer(userData.buffer);
+ const userKeysHash = commUtilsModule.sha256(
+ commUtilsModule.encodeStringToUTF8ArrayBuffer(userKeys),
+ );
+ const userDataHash = commUtilsModule.sha256(
+ commUtilsModule.encodeStringToUTF8ArrayBuffer(userData),
+ );
const formData = new FormData();
formData.append('backup_id', backupID);
formData.append('user_keys_hash', toBase64URL(userKeysHash));
- formData.append('user_keys', userKeysStr);
+ formData.append('user_keys', backup.userKeys);
formData.append('user_data_hash', toBase64URL(userDataHash));
- formData.append('user_data', userDataStr);
+ formData.append('user_data', backup.userData);
formData.append('attachments', '');
return formData;
}
@@ -71,7 +73,7 @@
async function getUserKeys(
backupID: string,
auth: BackupAuth,
-): Promise<Uint8Array> {
+): Promise<string> {
const authHeader = getBackupAuthorizationHeader(auth);
const getUserKeysEndpoint = backupService.httpEndpoints.GET_USER_KEYS;
@@ -88,13 +90,13 @@
handleHTTPResponseError(getUserKeysResponse);
const blob = await getUserKeysResponse.blob();
- return getBackupBytesFromBlob(blob);
+ return getBackupStringFromBlob(blob);
}
async function getUserData(
backupID: string,
auth: BackupAuth,
-): Promise<Uint8Array> {
+): Promise<string> {
const authHeader = getBackupAuthorizationHeader(auth);
const getUserDataEndpoint = backupService.httpEndpoints.GET_USER_DATA;
@@ -111,7 +113,7 @@
handleHTTPResponseError(getUserDataResponse);
const blob = await getUserDataResponse.blob();
- return getBackupBytesFromBlob(blob);
+ return getBackupStringFromBlob(blob);
}
export { uploadBackup, getBackupID, getUserKeys, getUserData };
diff --git a/native/backup/constants.js b/native/backup/constants.js
--- a/native/backup/constants.js
+++ b/native/backup/constants.js
@@ -1,5 +1,3 @@
// @flow
-export const BACKUP_ID_LENGTH = 32; //256 bits
-
export const BACKUP_HASH_STORAGE_KEY = 'RECENT_USER_DATA_HASH';
diff --git a/native/backup/conversion-utils.js b/native/backup/conversion-utils.js
--- a/native/backup/conversion-utils.js
+++ b/native/backup/conversion-utils.js
@@ -3,11 +3,9 @@
import { commUtilsModule } from '../native-modules.js';
import { arrayBufferFromBlob } from '../utils/blob-utils-module.js';
-function getBackupBytesFromBlob(blob: Blob): Uint8Array {
+function getBackupStringFromBlob(blob: Blob): string {
const buffer = arrayBufferFromBlob(blob);
- const str = commUtilsModule.decodeUTF8ArrayBufferToString(buffer);
- const decodedBuffer = commUtilsModule.base64DecodeBuffer(str);
- return new Uint8Array(decodedBuffer);
+ return commUtilsModule.decodeUTF8ArrayBufferToString(buffer);
}
function convertObjToBytes<T>(obj: T): Uint8Array {
@@ -21,4 +19,4 @@
return JSON.parse(str);
}
-export { getBackupBytesFromBlob, convertObjToBytes, convertBytesToObj };
+export { getBackupStringFromBlob, convertObjToBytes, convertBytesToObj };
diff --git a/native/backup/encryption.js b/native/backup/encryption.js
deleted file mode 100644
--- a/native/backup/encryption.js
+++ /dev/null
@@ -1,62 +0,0 @@
-// @flow
-
-import { hexToUintArray } from 'lib/media/data-utils.js';
-import type {
- Backup,
- BackupEncrypted,
- UserData,
- UserKeys,
-} from 'lib/types/backup-types.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<Uint8Array> {
- 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<BackupEncrypted> {
- 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 };
-}
-
-async function decryptUserKeys(
- backupID: string,
- userKeysBytes: ArrayBuffer,
-): Promise<UserKeys> {
- const backupKey = await getBackupKey(backupID);
- const decryptedUserKeys = AES.decrypt(
- backupKey,
- new Uint8Array(userKeysBytes),
- );
- return convertBytesToObj<UserKeys>(decryptedUserKeys);
-}
-
-async function decryptUserData(
- backupDataKey: string,
- userDataBytes: ArrayBuffer,
-): Promise<UserData> {
- const decryptedUserData = AES.decrypt(
- hexToUintArray(backupDataKey),
- new Uint8Array(userDataBytes),
- );
- return convertBytesToObj<UserData>(decryptedUserData);
-}
-
-export { getBackupKey, encryptBackup, decryptUserKeys, decryptUserData };
diff --git a/native/backup/use-client-backup.js b/native/backup/use-client-backup.js
--- a/native/backup/use-client-backup.js
+++ b/native/backup/use-client-backup.js
@@ -3,20 +3,17 @@
import _isEqual from 'lodash/fp/isEqual.js';
import * as React from 'react';
-import { uintArrayToHexString } from 'lib/media/data-utils.js';
import { isLoggedIn } from 'lib/selectors/user-selectors.js';
-import type { BackupAuth, UserData, UserKeys } from 'lib/types/backup-types.js';
+import type {
+ BackupAuth,
+ UserData,
+ BackupEncrypted,
+} from 'lib/types/backup-types.js';
import { getBackupID, getUserData, getUserKeys, uploadBackup } from './api.js';
-import { BACKUP_ID_LENGTH } from './constants.js';
-import {
- decryptUserData,
- decryptUserKeys,
- encryptBackup,
-} from './encryption.js';
+import { fetchNativeKeychainCredentials } from '../account/native-credentials.js';
import { commCoreModule } from '../native-modules.js';
import { useSelector } from '../redux/redux-utils.js';
-import { generateKey } from '../utils/aes-crypto-module.js';
import { getContentSigningKey } from '../utils/crypto-utils.js';
// purpose of this result is to improve logging and
@@ -25,7 +22,6 @@
getBackupID?: boolean,
getUserKeys?: boolean,
getUserData?: boolean,
- decryptUserKeys?: boolean,
decryptUserData?: boolean,
userDataIntegrity?: boolean,
error?: Error,
@@ -38,6 +34,14 @@
) => Promise<RestoreBackupResult>,
};
+async function getBackupSecret(): Promise<string> {
+ const nativeCredentials = await fetchNativeKeychainCredentials();
+ if (!nativeCredentials) {
+ throw new Error('Native credentials are missing');
+ }
+ return nativeCredentials.password;
+}
+
function useClientBackup(): ClientBackup {
const accessToken = useSelector(state => state.commServicesAccessToken);
const currentUserID = useSelector(
@@ -52,24 +56,16 @@
}
console.info('Start uploading backup...');
- const backupDataKey = generateKey();
-
- const [ed25519, backupID] = await Promise.all([
- getContentSigningKey(),
- commCoreModule.generateRandomString(BACKUP_ID_LENGTH),
- ]);
+ const backupSecret = await getBackupSecret();
- const userKeys: UserKeys = {
- backupDataKey: uintArrayToHexString(backupDataKey),
- ed25519,
- };
+ const encryptedBackupStr = await commCoreModule.createNewBackup(
+ backupSecret,
+ JSON.stringify(userData),
+ );
- const encryptedBackup = await encryptBackup({
- backupID,
- userKeys,
- userData,
- });
+ const encryptedBackup: BackupEncrypted = JSON.parse(encryptedBackupStr);
+ const ed25519 = await getContentSigningKey();
const backupAuth: BackupAuth = {
userID: currentUserID,
accessToken: accessToken ? accessToken : '',
@@ -92,7 +88,6 @@
getBackupID: undefined,
getUserKeys: undefined,
getUserData: undefined,
- decryptUserKeys: undefined,
decryptUserData: undefined,
userDataIntegrity: undefined,
error: undefined,
@@ -101,7 +96,7 @@
const backupIDPromise: Promise<?string> = (async () => {
try {
// We are using UserID instead of the username.
- // The reason is tha the initial version of the backup service
+ // The reason is that the initial version of the backup service
// cannot get UserID based on username.
const backupID = await getBackupID(currentUserID);
result.getBackupID = true;
@@ -128,7 +123,7 @@
deviceID: ed25519,
};
- const userKeysPromise: Promise<?Uint8Array> = (async () => {
+ const userKeysPromise: Promise<?string> = (async () => {
try {
const userKeysResponse = await getUserKeys(backupID, backupAuth);
result.getUserKeys = true;
@@ -139,7 +134,7 @@
return undefined;
}
})();
- const userDataPromise: Promise<?Uint8Array> = (async () => {
+ const userDataPromise: Promise<?string> = (async () => {
try {
const userDataResponse = await getUserData(backupID, backupAuth);
result.getUserData = true;
@@ -162,33 +157,24 @@
return result;
}
- let userKeys;
- try {
- userKeys = await decryptUserKeys(backupID, userKeysResponse.buffer);
- result.decryptUserKeys = true;
- } catch (e) {
- result.decryptUserKeys = false;
- result.error = e;
- }
-
- if (!userKeys) {
- result.decryptUserKeys = false;
- result.error = new Error('UserKeys is empty');
- return result;
- }
-
if (!userDataResponse) {
result.getUserData = false;
result.error = new Error('UserData response is empty');
return result;
}
- let userData;
+ const backupSecret = await getBackupSecret();
+
+ let userData: UserData;
try {
- userData = await decryptUserData(
- userKeys.backupDataKey,
- userDataResponse.buffer,
+ const restoreResultStr = await commCoreModule.restoreBackup(
+ backupID,
+ backupSecret,
+ userKeysResponse,
+ userDataResponse,
);
+ const { userData: userDataStr } = JSON.parse(restoreResultStr);
+ userData = JSON.parse(userDataStr);
result.decryptUserData = true;
} catch (e) {
result.decryptUserData = false;

File Metadata

Mime Type
text/plain
Expires
Sun, Oct 6, 1:31 AM (22 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2246810
Default Alt Text
D10067.id33940.diff (11 KB)

Event Timeline