diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp index 3a39540e50cab2dde77d8a565e2172cda2fbde98..2270bdcec0269c90ccc3db2f4c005227c2a1b002 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp @@ -57,6 +57,9 @@ namespace { const std::string JSON_EXTRACT_BY_PATH_TEST_CREATED = "SELECT json_extract_by_path('{\"field\":0}', '$.field', 0);"; const std::string DEFAULT_ATTACH_CIPHER = "PRAGMA cipher_default_attach_cipher="; const std::string DEFAULT_ATTACH_KDF_ITER = "PRAGMA cipher_default_attach_kdf_iter=5000"; + const std::string SHA1_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA1"; + const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256"; + const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256"; const std::string EXPORT_BACKUP_SQL = "SELECT export_database('backup');"; const std::string CIPHER_CONFIG_SQL = "PRAGMA codec_cipher="; const std::string KDF_ITER_CONFIG_SQL = "PRAGMA codec_kdf_iter="; @@ -141,7 +144,6 @@ int SQLiteUtils::CreateDataBase(const OpenDbProperties &properties, sqlite3 *&db if (setWal) { sqls.push_back(WAL_MODE_SQL); } - std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri; int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, flag, nullptr); if (errCode != SQLITE_OK) { @@ -150,7 +152,7 @@ int SQLiteUtils::CreateDataBase(const OpenDbProperties &properties, sqlite3 *&db goto END; } - errCode = SetDataBaseProperty(dbTemp, properties, sqls); + errCode = SetDataBaseProperty(dbTemp, properties, setWal, sqls); if (errCode != SQLITE_OK) { LOGE("[SQLite] SetDataBaseProperty failed: %d", errCode); goto END; @@ -432,33 +434,23 @@ int SQLiteUtils::ExecuteRawSQL(sqlite3 *db, const std::string &sql) return SQLiteUtils::MapSQLiteErrno(errCode); } -int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool isMemDb, uint32_t iterTimes) +int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool setWal, uint32_t iterTimes) { if (db == nullptr) { return -E_INVALID_DB; } - // in memory mode no need cipher - if (isMemDb) { - return E_OK; - } - if (passwd.GetSize() != 0) { -#ifndef OMIT_ENCRYPT - int errCode = sqlite3_key(db, static_cast(passwd.GetData()), static_cast(passwd.GetSize())); - if (errCode != SQLITE_OK) { - LOGE("[SQLiteUtils][Setkey] config key failed:(%d)", errCode); - return SQLiteUtils::MapSQLiteErrno(errCode); + int errCode = SetKeyInner(db, type, passwd, iterTimes); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][Setkey] set keyInner failed:%d", errCode); + return errCode; } - - errCode = SQLiteUtils::SetCipherSettings(db, type, iterTimes); + errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL); if (errCode != E_OK) { - LOGE("[SQLiteUtils][Setkey] set cipher settings failed:%d", errCode); + LOGE("[SQLiteUtils][Setkey] set sha algo failed:%d", errCode); return errCode; } -#else - return -E_NOT_SUPPORT; -#endif } // verify key @@ -471,7 +463,10 @@ int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &pass if (errCode == -E_BUSY) { return errCode; } - return -E_INVALID_PASSWD_OR_CORRUPTED_DB; + errCode = UpdateCipherShaAlgo(db, setWal, type, passwd, iterTimes); + if (errCode != E_OK) { + return -E_INVALID_PASSWD_OR_CORRUPTED_DB; + } } return E_OK; } @@ -922,12 +917,14 @@ int SQLiteUtils::GetVersion(const OpenDbProperties &properties, int &version) LOGE("Open database failed: %d, sys:%d", errCode, errno); goto END; } - - errCode = SQLiteUtils::SetKey(dbTemp, properties.cipherType, properties.passwd, properties.isMemDb, - properties.iterTimes); - if (errCode != E_OK) { - LOGE("Set key failed: %d", errCode); - goto END; + // in memory mode no need cipher + if (!properties.isMemDb) { + errCode = SQLiteUtils::SetKey(dbTemp, properties.cipherType, properties.passwd, false, + properties.iterTimes); + if (errCode != E_OK) { + LOGE("Set key failed: %d", errCode); + goto END; + } } errCode = GetVersion(dbTemp, version); @@ -1983,7 +1980,7 @@ int SQLiteUtils::ExplainPlan(sqlite3 *db, const std::string &execSql, bool isQue return errCode; } -int SQLiteUtils::SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, +int SQLiteUtils::SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, bool setWal, const std::vector &sqls) { // Set the default busy handler to retry automatically before returning SQLITE_BUSY. @@ -1991,12 +1988,13 @@ int SQLiteUtils::SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &proper if (errCode != E_OK) { return errCode; } - - errCode = SQLiteUtils::SetKey(db, properties.cipherType, properties.passwd, properties.isMemDb, - properties.iterTimes); - if (errCode != E_OK) { - LOGD("SQLiteUtils::SetKey fail!!![%d]", errCode); - return errCode; + if (!properties.isMemDb) { + errCode = SQLiteUtils::SetKey(db, properties.cipherType, properties.passwd, setWal, + properties.iterTimes); + if (errCode != E_OK) { + LOGD("SQLiteUtils::SetKey fail!!![%d]", errCode); + return errCode; + } } for (const auto &sql : sqls) { @@ -2184,4 +2182,67 @@ void SQLiteUtils::GetSelectCols(sqlite3_stmt *stmt, std::vector &co colNames.emplace_back(name == nullptr ? std::string() : std::string(name)); } } + +int SQLiteUtils::SetKeyInner(sqlite3 *db, CipherType type, const CipherPassword &passwd, uint32_t iterTimes) +{ +#ifndef OMIT_ENCRYPT + int errCode = sqlite3_key(db, static_cast(passwd.GetData()), static_cast(passwd.GetSize())); + if (errCode != SQLITE_OK) { + LOGE("[SQLiteUtils][SetKeyInner] config key failed:(%d)", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); + } + + errCode = SQLiteUtils::SetCipherSettings(db, type, iterTimes); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][SetKeyInner] set cipher settings failed:%d", errCode); + } + return errCode; +#else + return -E_NOT_SUPPORT; +#endif +} + +int SQLiteUtils::UpdateCipherShaAlgo(sqlite3 *db, bool setWal, CipherType type, const CipherPassword &passwd, uint32_t iterTimes) +{ + if (passwd.GetSize() != 0) { + int errCode = SetKeyInner(db, type, passwd, iterTimes); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][UpdateCipherShaAlgo] set keyInner failed:%d", errCode); + return errCode; + } + // set sha1 algo for old version + errCode = SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][UpdateCipherShaAlgo] set sha algo failed:%d", errCode); + return errCode; + } + // try to get user version + errCode = SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][UpdateCipherShaAlgo] verify version failed:%d", errCode); + if (errno == EKEYREVOKED) { + return -E_EKEYREVOKED; + } + if (errCode == -E_BUSY) { + return errCode; + } + return -E_INVALID_PASSWD_OR_CORRUPTED_DB; + } + // try to update sha algo by rekey operation + errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][UpdateCipherShaAlgo] set rekey sha algo failed:%d", errCode); + return errCode; + } + if (setWal) { + errCode = SQLiteUtils::ExecuteRawSQL(db, WAL_MODE_SQL); + if (errCode != E_OK) { + LOGE("[SQLite][UpdateCipherShaAlgo] execute wal sql failed: %d", errCode); + return errCode; + } + } + return Rekey(db, passwd); + } + return -E_INVALID_PASSWD_OR_CORRUPTED_DB; +} } // namespace DistributedDB \ No newline at end of file diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h index f35765b3bc77119bda09406d791a7e2185e111cc..19097e23df2ff79132c524308c9275faff2be08a 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h @@ -101,7 +101,7 @@ public: static int ExecuteRawSQL(sqlite3 *db, const std::string &sql); - static int SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool isMemDb, + static int SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool setWal, uint32_t iterTimes = DBConstant::DEFAULT_ITER_TIMES); static int GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector &value); @@ -200,6 +200,8 @@ public: static void GetSelectCols(sqlite3_stmt *stmt, std::vector &colNames); + static int SetKeyInner(sqlite3 *db, CipherType type, const CipherPassword &passwd, uint32_t iterTimes); + private: static int CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal); @@ -221,7 +223,7 @@ private: static void GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv); - static int SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, + static int SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, bool setWal, const std::vector &sqls); static int RegisterFunction(sqlite3 *db, const std::string &funcName, int nArg, void *uData, TransactFunc &func); @@ -236,6 +238,9 @@ private: static void SqliteLogCallback(void *data, int err, const char *msg); + static int UpdateCipherShaAlgo(sqlite3 *db, bool setWal, CipherType type, const CipherPassword &passwd, + uint32_t iterTimes); + static std::mutex logMutex_; static std::string lastErrorMsg_; }; diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp index 832cc32666fb8c57d3320d685dbc4d07e6615f0a..47c21f6f17ab1f55153d5354cac014cbdc856dca 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp @@ -639,4 +639,49 @@ HWTEST_F(DistributedDBStorageDataOperationTest, CutValueIntoBlock002, TestSize.L CheckSplitData(value2, 0ul, valueDic, savedValue); CheckRecoverData(savedValue, valueDic, value2); EXPECT_EQ(valueDic.size(), 0ul); +} + +/** + * @tc.name: ShaAlgoEncryptTest001 + * @tc.desc: Test sqlite sha algo + * @tc.type: FUNC + * @tc.require: AR000HI2JS + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBStorageDataOperationTest, ShaAlgoEncryptTest001, TestSize.Level1) +{ + sqlite3 *db = nullptr; + CipherPassword passwd; + std::vector passwdVect = {'p', 's', 'd', '1'}; + passwd.SetValue(passwdVect.data(), passwdVect.size()); + const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256"; + const std::string SHA1_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA1"; + const std::string USER_VERSION_SQL = "PRAGMA user_version;"; + const std::string SET_USER_VERSION_SQL = "PRAGMA user_version=100;"; + /** + * @tc.steps: step1. use sha256 to open db + * * @tc.expected: step1. interface return ok + */ + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/ShaAlgoEncryptTest001.db"; + EXPECT_EQ(sqlite3_open_v2(fileUrl.c_str(), &db, flag, nullptr), SQLITE_OK); + EXPECT_EQ(SQLiteUtils::SetKeyInner(db, CipherType::AES_256_GCM, passwd, DBConstant::DEFAULT_ITER_TIMES), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL), E_OK); + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, SET_USER_VERSION_SQL) == E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL), E_OK); + /** + * @tc.steps: step2. close db + * * @tc.expected: step2. interface return ok + */ + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step1. use sha1 to open db + * * @tc.expected: step1. interface return not ok + */ + EXPECT_EQ(sqlite3_open_v2(fileUrl.c_str(), &db, flag, nullptr), SQLITE_OK); + EXPECT_EQ(SQLiteUtils::SetKeyInner(db, CipherType::AES_256_GCM, passwd, DBConstant::DEFAULT_ITER_TIMES), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_SQL), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL), -E_INVALID_PASSWD_OR_CORRUPTED_DB); + sqlite3_close_v2(db); } \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp index d2b6ecea96bc8d0d6e716700ccd55fa742a99033..083d6159c293745ca5af3409dc82107701224132 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp @@ -55,6 +55,8 @@ namespace { const char DEFAULT_CHAR = 'D'; const std::string DEFAULT_TEXT = "This is a text"; const std::vector DEFAULT_BLOB(ONE_HUNDERED, DEFAULT_CHAR); + const std::string SHA1_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA1"; + const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256"; RelationalStoreManager g_mgr(APP_ID, USER_ID); std::string g_testDir; @@ -95,7 +97,7 @@ namespace { ASSERT_TRUE(g_rdbDelegatePtr != nullptr); } - int GetDB(sqlite3 *&db) + int GetDB(sqlite3 *&db, bool isSha256Algo = true) { int flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; const auto &dbPath = g_dbDir; @@ -108,6 +110,11 @@ namespace { "PRAGMA key='" + (g_isAfterRekey ? REKEY_KEY : CORRECT_KEY) + "';" "PRAGMA codec_kdf_iter=" + std::to_string(DEFAULT_ITER) + ";"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + if (isSha256Algo) { + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL), E_OK); + } else { + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_SQL), E_OK); + } #endif EXPECT_EQ(SQLiteUtils::RegisterCalcHash(db), E_OK); EXPECT_EQ(SQLiteUtils::RegisterGetSysTime(db), E_OK); @@ -1932,4 +1939,54 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, OrderbyWriteTimeSync001, TestSiz EXPECT_EQ(g_rdbDelegatePtr->Sync({DEVICE_B}, DistributedDB::SYNC_MODE_PUSH_ONLY, query, nullptr, false), NOT_SUPPORT); } + +/** +* @tc.name: EncryptedAlgoUpgrade001 + * @tc.desc: Test upgrade encrypted db can sync normally + * @tc.type: FUNC + * @tc.require: AR000HI2JS + * @tc.author: zhuwentao +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, EncryptedAlgoUpgrade001, TestSize.Level0) +{ + if (g_rdbDelegatePtr != nullptr) { + LOGD("CloseStore Start"); + ASSERT_EQ(g_mgr.CloseStore(g_rdbDelegatePtr), OK); + g_rdbDelegatePtr = nullptr; + } + EXPECT_EQ(OS::RemoveFile(g_dbDir), E_OK); + /** + * @tc.steps: step1. open old db use sha1 algo and insert some data + * @tc.expected: step1. interface return ok + */ + sqlite3 *db = nullptr; + EXPECT_EQ(GetDB(db, false), SQLITE_OK); + const std::string user_version_sql = "PRAGMA user_version=101;"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, user_version_sql), E_OK); + sqlite3_close(db); + + /** + * @tc.steps: step2. open db by OpenStore + * @tc.expected: step2. interface return ok + */ + OpenStore(); + /** + * @tc.steps: step3. sync with push + * @tc.expected: step3. interface return ok + */ + std::map dataMap; + PrepareEnvironment(dataMap, {g_deviceB}); + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK, {DEVICE_B}); + CheckVirtualData(dataMap); + dataMap.clear(); + + /** + * @tc.steps: step4. sync with pull + * @tc.expected: step4. interface return ok + */ + + Query query = Query::Select(g_tableName); + g_deviceB->GenericVirtualDevice::Sync(DistributedDB::SYNC_MODE_PULL_ONLY, query, true); + CheckVirtualData(dataMap); +} #endif \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp index 21ac5c0a5180095d5346337f5569808589ce112f..cb1b9de8de0dcb9f92ad315f0b5884e0492e3bc3 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp @@ -18,6 +18,7 @@ #include #include "db_constant.h" +#include "db_common.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "kv_store_nb_delegate.h" @@ -40,6 +41,16 @@ namespace { const std::string DEVICE_A = "real_device"; const std::string DEVICE_B = "deviceB"; const std::string DEVICE_C = "deviceC"; + const std::string CREATE_SYNC_TABLE_SQL = + "CREATE TABLE IF NOT EXISTS sync_data(" \ + "key BLOB NOT NULL," \ + "value BLOB," \ + "timestamp INT NOT NULL," \ + "flag INT NOT NULL," \ + "device BLOB," \ + "ori_device BLOB," \ + "hash_key BLOB PRIMARY KEY NOT NULL," \ + "w_timestamp INT);"; KvStoreDelegateManager g_mgr(APP_ID, USER_ID); KvStoreConfig g_config; @@ -53,6 +64,65 @@ namespace { // the type of g_kvDelegateCallback is function auto g_kvDelegateCallback = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, placeholders::_1, placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(g_kvDelegatePtr)); + + void PullSyncTest() + { + DBStatus status = OK; + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + + Key key = {'1'}; + Key key2 = {'2'}; + Value value = {'1'}; + g_deviceB->PutData(key, value, 0, 0); + g_deviceB->PutData(key2, value, 1, 0); + + std::map result; + status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); + ASSERT_TRUE(status == OK); + + ASSERT_TRUE(result.size() == devices.size()); + for (const auto &pair : result) { + LOGD("dev %s, status %d", pair.first.c_str(), pair.second); + EXPECT_TRUE(pair.second == OK); + } + Value value3; + EXPECT_EQ(g_kvDelegatePtr->Get(key, value3), OK); + EXPECT_EQ(value3, value); + EXPECT_EQ(g_kvDelegatePtr->Get(key2, value3), OK); + EXPECT_EQ(value3, value); + } + + void CrudTest() + { + vector entries; + int totalSize = 10; + for (int i = 0; i < totalSize; i++) { + Entry entry; + entry.key.push_back(i); + entry.value.push_back('2'); + entries.push_back(entry); + } + EXPECT_TRUE(g_kvDelegatePtr->PutBatch(entries) == OK); + for (const auto &entry : entries) { + Value resultvalue; + EXPECT_TRUE(g_kvDelegatePtr->Get(entry.key, resultvalue) == OK); + EXPECT_TRUE(resultvalue == entry.value); + } + for (int i = 0; i < totalSize / 2; i++) { + g_kvDelegatePtr->Delete(entries[i].key); + Value resultvalue; + EXPECT_TRUE(g_kvDelegatePtr->Get(entries[i].key, resultvalue) == NOT_FOUND); + } + for (int i = totalSize / 2; i < totalSize; i++) { + Value value = entries[i].value; + value.push_back('x'); + EXPECT_TRUE(g_kvDelegatePtr->Put(entries[i].key, value) == OK); + Value resultvalue; + EXPECT_TRUE(g_kvDelegatePtr->Get(entries[i].key, resultvalue) == OK); + EXPECT_TRUE(resultvalue == value); + } + } } class DistributedDBSingleVerP2PSyncTest : public testing::Test { @@ -2530,3 +2600,77 @@ HWTEST_F(DistributedDBSingleVerP2PSyncTest, OrderbyWriteTimeSync001, TestSize.Le Query query = Query::Select().PrefixKey({'k'}).OrderByWriteTime(true); EXPECT_EQ(g_kvDelegatePtr->Sync(devices, DistributedDB::SYNC_MODE_PUSH_ONLY, nullptr, query, true), NOT_SUPPORT); } + +/** + * @tc.name: EncryptedAlgoUpgrade001 + * @tc.desc: Test upgrade encrypted db can sync normally + * @tc.type: FUNC + * @tc.require: AR000HI2JS + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBSingleVerP2PSyncTest, EncryptedAlgoUpgrade001, TestSize.Level3) +{ + /** + * @tc.steps: step1. clear db + * * @tc.expected: step1. interface return ok + */ + if (g_kvDelegatePtr != nullptr) { + ASSERT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK); + g_kvDelegatePtr = nullptr; + DBStatus status = g_mgr.DeleteKvStore(STORE_ID); + LOGD("delete kv store status %d", status); + ASSERT_TRUE(status == OK); + } + + CipherPassword passwd; + std::vector passwdVect = {'p', 's', 'd', '1'}; + passwd.SetValue(passwdVect.data(), passwdVect.size()); + /** + * @tc.steps: step2. open old db by sql + * * @tc.expected: step2. interface return ok + */ + std::string identifier = DBCommon::GenerateIdentifierId(STORE_ID, APP_ID, USER_ID); + std::string hashDir = DBCommon::TransferHashString(identifier); + std::string hexHashDir = DBCommon::TransferStringToHex(hashDir); + std::string dbPath = g_testDir + "/" + hexHashDir + "/single_ver"; + ASSERT_TRUE(DBCommon::CreateDirectory(g_testDir + "/" + hexHashDir) == OK); + ASSERT_TRUE(DBCommon::CreateDirectory(dbPath) == OK); + std::vector dbDir {DBConstant::MAINDB_DIR, DBConstant::METADB_DIR, DBConstant::CACHEDB_DIR}; + for (const auto &item : dbDir) { + ASSERT_TRUE(DBCommon::CreateDirectory(dbPath + "/" + item) == OK); + } + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + sqlite3 *db; + std::string fileUrl = dbPath + "/" + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + ".db"; + ASSERT_TRUE(sqlite3_open_v2(fileUrl.c_str(), &db, flag, nullptr) == SQLITE_OK); + SQLiteUtils::SetKeyInner(db, CipherType::AES_256_GCM, passwd, DBConstant::DEFAULT_ITER_TIMES); + /** + * @tc.steps: step3. create table and close + * * @tc.expected: step3. interface return ok + */ + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, CREATE_SYNC_TABLE_SQL) == E_OK); + sqlite3_close_v2(db); + db = nullptr; + LOGI("create old db success"); + /** + * @tc.steps: step4. get kvstore + * * @tc.expected: step4. interface return ok + */ + KvStoreNbDelegate::Option option; + option.isEncryptedDb = true; + option.cipher = CipherType::AES_256_GCM; + option.passwd = passwd; + g_mgr.GetKvStore(STORE_ID, option, g_kvDelegateCallback); + ASSERT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvDelegatePtr != nullptr); + /** + * @tc.steps: step5. sync ok + * * @tc.expected: step5. interface return ok + */ + PullSyncTest(); + /** + * @tc.steps: step5. crud ok + * * @tc.expected: step5. interface return ok + */ + CrudTest(); +}