diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h @@ -52,6 +52,10 @@ jsi::Runtime &rt, std::string backupSecret, std::string backupMessage); + jsi::Value restoreBackupInternal( + jsi::Runtime &rt, + std::string backupSecret, + std::string backupID); virtual jsi::Value getDraft(jsi::Runtime &rt, jsi::String key) override; virtual jsi::Value @@ -184,6 +188,10 @@ jsi::String siweBackupMsg) override; virtual jsi::Value restoreBackup(jsi::Runtime &rt, jsi::String backupSecret) override; + virtual jsi::Value restoreSIWEBackup( + jsi::Runtime &rt, + jsi::String backupSecret, + jsi::String backupID) override; virtual jsi::Value restoreBackupData( jsi::Runtime &rt, jsi::String backupID, diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp @@ -2012,17 +2012,34 @@ return createNewBackupInternal(rt, backupSecretStr, siweBackupMsgStr); } -jsi::Value -CommCoreModule::restoreBackup(jsi::Runtime &rt, jsi::String backupSecret) { - std::string backupSecretStr = backupSecret.utf8(rt); +jsi::Value CommCoreModule::restoreBackupInternal( + jsi::Runtime &rt, + std::string backupSecret, + std::string backupID) { return createPromiseAsJSIValue( rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { auto currentID = RustPromiseManager::instance.addPromise( {promise, this->jsInvoker_, innerRt}); - ::restoreBackup(rust::string(backupSecretStr), currentID); + ::restoreBackup( + rust::string(backupSecret), rust::string(backupID), currentID); }); } +jsi::Value +CommCoreModule::restoreBackup(jsi::Runtime &rt, jsi::String backupSecret) { + std::string backupSecretStr = backupSecret.utf8(rt); + return restoreBackupInternal(rt, backupSecretStr, ""); +} + +jsi::Value CommCoreModule::restoreSIWEBackup( + jsi::Runtime &rt, + jsi::String backupSecret, + jsi::String backupID) { + std::string backupSecretStr = backupSecret.utf8(rt); + std::string backupIDStr = backupID.utf8(rt); + return restoreBackupInternal(rt, backupSecretStr, backupIDStr); +} + jsi::Value CommCoreModule::restoreBackupData( jsi::Runtime &rt, jsi::String backupID, diff --git a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp --- a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp +++ b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp @@ -166,6 +166,9 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreBackup(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->restoreBackup(rt, args[0].asString(rt)); } +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreSIWEBackup(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->restoreSIWEBackup(rt, args[0].asString(rt), args[1].asString(rt)); +} static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreBackupData(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->restoreBackupData(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt)); } @@ -248,6 +251,7 @@ methodMap_["createNewBackup"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createNewBackup}; methodMap_["createNewSIWEBackup"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createNewSIWEBackup}; methodMap_["restoreBackup"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreBackup}; + methodMap_["restoreSIWEBackup"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreSIWEBackup}; methodMap_["restoreBackupData"] = MethodMetadata {3, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreBackupData}; methodMap_["retrieveBackupKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_retrieveBackupKeys}; methodMap_["retrieveLatestSIWEBackupData"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_retrieveLatestSIWEBackupData}; diff --git a/native/cpp/CommonCpp/_generated/commJSI.h b/native/cpp/CommonCpp/_generated/commJSI.h --- a/native/cpp/CommonCpp/_generated/commJSI.h +++ b/native/cpp/CommonCpp/_generated/commJSI.h @@ -69,6 +69,7 @@ virtual jsi::Value createNewBackup(jsi::Runtime &rt, jsi::String backupSecret) = 0; virtual jsi::Value createNewSIWEBackup(jsi::Runtime &rt, jsi::String backupSecret, jsi::String siweBackupMsg) = 0; virtual jsi::Value restoreBackup(jsi::Runtime &rt, jsi::String backupSecret) = 0; + virtual jsi::Value restoreSIWEBackup(jsi::Runtime &rt, jsi::String backupSecret, jsi::String backupID) = 0; virtual jsi::Value restoreBackupData(jsi::Runtime &rt, jsi::String backupID, jsi::String backupDataKey, jsi::String backupLogDataKey) = 0; virtual jsi::Value retrieveBackupKeys(jsi::Runtime &rt, jsi::String backupSecret) = 0; virtual jsi::Value retrieveLatestSIWEBackupData(jsi::Runtime &rt) = 0; @@ -492,6 +493,14 @@ return bridging::callFromJs( rt, &T::restoreBackup, jsInvoker_, instance_, std::move(backupSecret)); } + jsi::Value restoreSIWEBackup(jsi::Runtime &rt, jsi::String backupSecret, jsi::String backupID) override { + static_assert( + bridging::getParameterCount(&T::restoreSIWEBackup) == 3, + "Expected restoreSIWEBackup(...) to have 3 parameters"); + + return bridging::callFromJs( + rt, &T::restoreSIWEBackup, jsInvoker_, instance_, std::move(backupSecret), std::move(backupID)); + } jsi::Value restoreBackupData(jsi::Runtime &rt, jsi::String backupID, jsi::String backupDataKey, jsi::String backupLogDataKey) override { static_assert( bridging::getParameterCount(&T::restoreBackupData) == 4, diff --git a/native/native_rust_library/Cargo.lock b/native/native_rust_library/Cargo.lock --- a/native/native_rust_library/Cargo.lock +++ b/native/native_rust_library/Cargo.lock @@ -241,6 +241,16 @@ "digest 0.10.5", ] +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "block-padding", + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.3" @@ -250,6 +260,12 @@ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + [[package]] name = "bumpalo" version = "3.12.0" @@ -383,6 +399,18 @@ "libc", ] +[[package]] +name = "crypto-bigint" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8658c15c5d921ddf980f7fe25b1e82f4b7a4083b2c4985fea4922edb8e43e07d" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-bigint" version = "0.4.9" @@ -405,6 +433,16 @@ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "curve25519-dalek" version = "4.0.0-pre.1" @@ -468,6 +506,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +[[package]] +name = "der" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" + [[package]] name = "der" version = "0.6.1" @@ -516,7 +560,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ - "block-buffer", + "block-buffer 0.10.3", "crypto-common", "subtle", ] @@ -532,12 +576,39 @@ "syn 1.0.99", ] +[[package]] +name = "ecdsa" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372" +dependencies = [ + "der 0.4.5", + "elliptic-curve 0.10.4", + "hmac 0.11.0", + "signature", +] + [[package]] name = "either" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +[[package]] +name = "elliptic-curve" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e5c176479da93a0983f0a6fdc3c1b8e7d5be0d7fe3fe05a99f15b96582b9a8" +dependencies = [ + "crypto-bigint 0.2.5", + "ff 0.10.1", + "generic-array", + "group 0.10.0", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "elliptic-curve" version = "0.12.3" @@ -545,12 +616,12 @@ checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" dependencies = [ "base16ct", - "crypto-bigint", - "der", + "crypto-bigint 0.4.9", + "der 0.6.1", "digest 0.10.5", - "ff", + "ff 0.12.1", "generic-array", - "group", + "group 0.12.1", "rand_core", "sec1", "subtle", @@ -575,6 +646,16 @@ "instant", ] +[[package]] +name = "ff" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "ff" version = "0.12.1" @@ -712,13 +793,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "group" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" +dependencies = [ + "ff 0.10.1", + "rand_core", + "subtle", +] + [[package]] name = "group" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ - "ff", + "ff 0.12.1", "rand_core", "subtle", ] @@ -788,7 +880,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" dependencies = [ - "hmac", + "hmac 0.12.1", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac", + "digest 0.9.0", ] [[package]] @@ -955,6 +1057,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "iri-string" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f0f7638c1e223529f1bfdc48c8b133b9e0b434094d1d28473161ee48b235f78" +dependencies = [ + "nom", +] + [[package]] name = "itertools" version = "0.10.4" @@ -979,6 +1090,27 @@ "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "008b0281ca8032567c9711cd48631781c15228301860a39b32deb28d63125e46" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve 0.10.4", + "sha3", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1046,6 +1178,12 @@ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -1106,11 +1244,22 @@ "regex", "serde", "serde_json", + "siwe", "tokio", "tonic", "tracing", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1155,6 +1304,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "opaque-ke" version = "2.0.0" @@ -1166,10 +1321,10 @@ "derive-where", "digest 0.10.5", "displaydoc", - "elliptic-curve", + "elliptic-curve 0.12.3", "generic-array", "hkdf", - "hmac", + "hmac 0.12.1", "rand", "serde", "subtle", @@ -1644,7 +1799,7 @@ checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" dependencies = [ "base16ct", - "der", + "der 0.6.1", "generic-array", "subtle", "zeroize", @@ -1755,6 +1910,18 @@ "digest 0.10.5", ] +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -1764,6 +1931,32 @@ "lazy_static", ] +[[package]] +name = "signature" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2807892cfa58e081aa1f1111391c7a0649d4fa127a4ffbe34bcbfb35a1171a4" +dependencies = [ + "digest 0.9.0", + "rand_core", +] + +[[package]] +name = "siwe" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f2d8ae2d4ae58df46e173aa496562ea857ac6a4f0d435ed30fcd19da0aaa79" +dependencies = [ + "chrono", + "hex", + "http", + "iri-string", + "k256", + "rand", + "sha3", + "thiserror", +] + [[package]] name = "slab" version = "0.4.7" @@ -2333,7 +2526,7 @@ "derive-where", "digest 0.10.5", "displaydoc", - "elliptic-curve", + "elliptic-curve 0.12.3", "generic-array", "rand_core", "serde", diff --git a/native/native_rust_library/Cargo.toml b/native/native_rust_library/Cargo.toml --- a/native/native_rust_library/Cargo.toml +++ b/native/native_rust_library/Cargo.toml @@ -13,6 +13,7 @@ comm-opaque2 = { path = "../../shared/comm-opaque2" } derive_more = "0.99" serde = { version = "1.0", features = ["derive"] } +siwe = "0.3" serde_json = "1.0" argon2 = { version = "0.5.1", features = ["std"] } grpc_clients = { path = "../../shared/grpc_clients" } diff --git a/native/native_rust_library/src/backup.rs b/native/native_rust_library/src/backup.rs --- a/native/native_rust_library/src/backup.rs +++ b/native/native_rust_library/src/backup.rs @@ -19,6 +19,7 @@ TryStreamExt, UserIdentity, }; use serde::{Deserialize, Serialize}; +use siwe::Message; use std::error::Error; use std::path::PathBuf; @@ -75,9 +76,14 @@ }); } - pub fn restore_backup(backup_secret: String, promise_id: u32) { + pub fn restore_backup( + backup_secret: String, + backup_id: String, + promise_id: u32, + ) { RUNTIME.spawn(async move { - let result = download_backup(backup_secret) + let backup_id = Option::from(backup_id).filter(|it| !it.is_empty()); + let result = download_backup(backup_secret, backup_id) .await .map_err(|err| err.to_string()); @@ -115,7 +121,19 @@ pub fn retrieve_backup_keys(backup_secret: String, promise_id: u32) { RUNTIME.spawn(async move { - let result = download_backup_keys(backup_secret) + let latest_backup_id_response = download_latest_backup_id() + .await + .map_err(|err| err.to_string()); + + let backup_id = match latest_backup_id_response { + Ok(result) => result.backup_id, + Err(error) => { + string_callback(error, promise_id, "".to_string()); + return; + } + }; + + let result = download_backup_keys(backup_id, backup_secret) .await .map_err(|err| err.to_string()); @@ -199,11 +217,8 @@ siwe_backup_msg, } = result; - let siwe_backup_data = match siwe_backup_msg { - Some(siwe_backup_msg_value) => SIWEBackupData { - backup_id, - siwe_backup_msg: siwe_backup_msg_value, - }, + let siwe_backup_msg_string = match siwe_backup_msg { + Some(siwe_backup_msg_value) => siwe_backup_msg_value, None => { string_callback( "Backup message unavailable".to_string(), @@ -214,6 +229,37 @@ } }; + let siwe_backup_msg_obj: Message = match siwe_backup_msg_string.parse() { + Ok(siwe_backup_msg_obj) => siwe_backup_msg_obj, + Err(error) => { + string_callback(error.to_string(), promise_id, "".to_string()); + return; + } + }; + + let siwe_backup_msg_nonce = siwe_backup_msg_obj.nonce; + let siwe_backup_msg_statement = match siwe_backup_msg_obj.statement { + Some(statement) => statement, + None => { + string_callback( + "Backup message invalid: missing statement".to_string(), + promise_id, + "".to_string(), + ); + return; + } + }; + + let siwe_backup_msg_issued_at = siwe_backup_msg_obj.issued_at.to_string(); + + let siwe_backup_data = SIWEBackupData { + backup_id: backup_id, + siwe_backup_msg: siwe_backup_msg_string, + siwe_backup_msg_nonce: siwe_backup_msg_nonce, + siwe_backup_msg_statement: siwe_backup_msg_statement, + siwe_backup_msg_issued_at: siwe_backup_msg_issued_at, + }; + let serialize_result = serde_json::to_string(&siwe_backup_data); handle_string_result_as_callback(serialize_result, promise_id); }); @@ -261,8 +307,17 @@ async fn download_backup( backup_secret: String, + backup_id: Option, ) -> Result> { - let backup_keys = download_backup_keys(backup_secret).await?; + let backup_id = match backup_id { + Some(backup_id) => backup_id, + None => { + let latest_backup_id_response = download_latest_backup_id().await?; + latest_backup_id_response.backup_id + } + }; + + let backup_keys = download_backup_keys(backup_id, backup_secret).await?; download_backup_data(backup_keys).await } @@ -291,6 +346,7 @@ } async fn download_backup_keys( + backup_id: String, backup_secret: String, ) -> Result> { let backup_client = BackupClient::new(BACKUP_SOCKET_ADDR)?; @@ -300,19 +356,10 @@ username: user_identity.user_id.clone(), }; - let backup_id_response = backup_client - .download_backup_data(&latest_backup_descriptor, RequestedData::BackupID) - .await?; - - let LatestBackupIDResponse { backup_id, .. } = - serde_json::from_slice(&backup_id_response)?; - - let mut backup_key = compute_backup_key_str(&backup_secret, &backup_id)?; - let mut encrypted_user_keys = backup_client .download_backup_data(&latest_backup_descriptor, RequestedData::UserKeys) .await?; - + let mut backup_key = compute_backup_key_str(&backup_secret, &backup_id)?; let user_keys = UserKeys::from_encrypted(&mut encrypted_user_keys, &mut backup_key)?; @@ -393,16 +440,23 @@ } #[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] struct BackupKeysResult { + #[serde(rename = "backupID")] backup_id: String, backup_data_key: String, backup_log_data_key: String, } #[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] struct SIWEBackupData { + #[serde(rename = "backupID")] backup_id: String, siwe_backup_msg: String, + siwe_backup_msg_statement: String, + siwe_backup_msg_nonce: String, + siwe_backup_msg_issued_at: String, } struct CompactionDownloadResult { diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs --- a/native/native_rust_library/src/lib.rs +++ b/native/native_rust_library/src/lib.rs @@ -407,7 +407,11 @@ ); #[cxx_name = "restoreBackup"] - fn restore_backup(backup_secret: String, promise_id: u32); + fn restore_backup( + backup_secret: String, + backup_id: String, + promise_id: u32, + ); #[cxx_name = "restoreBackupData"] fn restore_backup_data( diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js --- a/native/schema/CommCoreModuleSchema.js +++ b/native/schema/CommCoreModuleSchema.js @@ -132,6 +132,10 @@ siweBackupMsg: string, ) => Promise; +restoreBackup: (backupSecret: string) => Promise; + +restoreSIWEBackup: ( + backupSecret: string, + backupID: string, + ) => Promise; +restoreBackupData: ( backupID: string, backupDataKey: string,