1bfc6ded创建于 3月27日历史提交
/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#define LOG_TAG "RdbRekeyTest"
#include <gtest/gtest.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <securec.h>

#include <fstream>
#include <iostream>
#include <string>
#include <thread>

#include "block_data.h"
#include "rdb_test_common.h"
#include "file_ex.h"
#include "logger.h"
#include "rdb_errno.h"
#include "rdb_helper.h"
#include "rdb_open_callback.h"
#include "rdb_security_manager.h"
#include "sqlite_connection.h"
#include "sqlite_utils.h"

using namespace testing::ext;
using namespace OHOS::NativeRdb;
using namespace OHOS::Rdb;
class RdbInterfaceRekeyTest : public testing::Test {
public:
    static void SetUpTestCase();
    static void TearDownTestCase();
    void SetUp() override;
    void TearDown() override;

    static std::string RemoveSuffix(const std::string &name);
    static std::chrono::system_clock::time_point GetKeyFileDate(const std::string &dbName);
    static bool ChangeKeyFileDate(const std::string &dbName, int rep);
    static bool SaveNewKey(const std::string &dbName);
    static RdbStoreConfig GetRdbConfig(const std::string &name);
    static RdbStoreConfig GetRdbNotRekeyConfig(const std::string &name);
    static void InsertData(std::shared_ptr<RdbStore> &store);
    static void CheckQueryData(std::shared_ptr<RdbStore> &store);

    static const std::string encryptedDatabaseName;
    static const std::string encryptedDatabasePath;
    static const std::string encryptedDatabaseKeyDir;
    static const std::string encryptedDatabaseMockName;
    static const std::string encryptedDatabaseMockPath;
    static constexpr int HOURS_EXPIRED = (24 * 365) + 1;
    static constexpr int HOURS_LONG_LONG_AGO = 30 * (24 * 365);
    static constexpr int HOURS_NOT_EXPIRED = (24 * 30);
};

const std::string RdbInterfaceRekeyTest::encryptedDatabaseName = "encrypted.db";
const std::string RdbInterfaceRekeyTest::encryptedDatabasePath = RDB_TEST_PATH + encryptedDatabaseName;
const std::string RdbInterfaceRekeyTest::encryptedDatabaseKeyDir = RDB_TEST_PATH + "key/";
const std::string RdbInterfaceRekeyTest::encryptedDatabaseMockName = "encrypted_mock.db";
const std::string RdbInterfaceRekeyTest::encryptedDatabaseMockPath = RDB_TEST_PATH + encryptedDatabaseMockName;

class RekeyTestOpenCallback : public RdbOpenCallback {
public:
    int OnCreate(RdbStore &store) override;
    int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
    static const std::string createTableTest;
};

std::string const RekeyTestOpenCallback::createTableTest = "CREATE TABLE IF NOT EXISTS test "
                                                           "(id INTEGER PRIMARY KEY "
                                                           "AUTOINCREMENT, "
                                                           "name TEXT NOT NULL, age INTEGER, "
                                                           "salary "
                                                           "REAL, blobType BLOB)";

int RekeyTestOpenCallback::OnCreate(RdbStore &store)
{
    return store.ExecuteSql(createTableTest);
}

int RekeyTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
{
    return E_OK;
}

void RdbInterfaceRekeyTest::SetUpTestCase()
{
}

void RdbInterfaceRekeyTest::TearDownTestCase()
{
}

void RdbInterfaceRekeyTest::SetUp()
{
    RdbHelper::ClearCache();
    RdbHelper::DeleteRdbStore(RdbInterfaceRekeyTest::encryptedDatabasePath);
    RdbStoreConfig config = GetRdbConfig(encryptedDatabasePath);
    RekeyTestOpenCallback helper;
    int errCode;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    EXPECT_NE(store, nullptr);
    InsertData(store);
    store.reset();
    RdbHelper::ClearCache();
}

void RdbInterfaceRekeyTest::TearDown()
{
    RdbHelper::ClearCache();
    RdbHelper::DeleteRdbStore(RdbInterfaceRekeyTest::encryptedDatabasePath);
}

std::string RdbInterfaceRekeyTest::RemoveSuffix(const std::string &name)
{
    std::string suffix(".db");
    auto pos = name.rfind(suffix);
    if (pos == std::string::npos || pos < name.length() - suffix.length()) {
        return name;
    }
    return { name, 0, pos };
}

std::chrono::system_clock::time_point RdbInterfaceRekeyTest::GetKeyFileDate(const std::string &dbName)
{
    std::chrono::system_clock::time_point timePoint;
    std::string name = RemoveSuffix(dbName);
    auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key_v2";
    if (!OHOS::FileExists(keyPath)) {
        return timePoint;
    }
    std::vector<char> content;
    auto loaded = OHOS::LoadBufferFromFile(keyPath, content);
    if (!loaded) {
        return timePoint;
    }
    auto iter = content.begin();
    iter++;
    constexpr uint32_t dateFileLength = sizeof(time_t) / sizeof(uint8_t);
    std::vector<uint8_t> date;
    date.assign(iter, iter + dateFileLength);
    timePoint = std::chrono::system_clock::from_time_t(*reinterpret_cast<time_t *>(const_cast<uint8_t *>(&date[0])));
    return timePoint;
}

bool RdbInterfaceRekeyTest::ChangeKeyFileDate(const std::string &dbName, int rep)
{
    std::string name = RemoveSuffix(dbName);
    auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key_v2";
    if (!OHOS::FileExists(keyPath)) {
        return false;
    }
    std::vector<char> content;
    auto loaded = OHOS::LoadBufferFromFile(keyPath, content);
    if (!loaded) {
        return false;
    }
    auto time =
        std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now() - std::chrono::hours(rep));
    std::vector<char> date(reinterpret_cast<uint8_t *>(&time), reinterpret_cast<uint8_t *>(&time) + sizeof(time));
    std::copy(date.begin(), date.end(), ++content.begin());

    auto saved = OHOS::SaveBufferToFile(keyPath, content);
    return saved;
}

bool RdbInterfaceRekeyTest::SaveNewKey(const string &dbName)
{
    std::string name = RemoveSuffix(dbName);
    auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key_v2";
    auto newKeyPath = RDB_TEST_PATH + "key/" + name + ".pub_key_v2.new";
    if (!OHOS::FileExists(keyPath)) {
        return false;
    }
    std::vector<char> content;
    auto loaded = OHOS::LoadBufferFromFile(keyPath, content);
    if (!loaded) {
        return false;
    }
    OHOS::SaveBufferToFile(newKeyPath, content);
    content[content.size() - 1] = 'E';
    return OHOS::SaveBufferToFile(keyPath, content);
}

RdbStoreConfig RdbInterfaceRekeyTest::GetRdbConfig(const std::string &name)
{
    RdbStoreConfig config(name);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    config.EnableRekey(true);
    return config;
}

RdbStoreConfig RdbInterfaceRekeyTest::GetRdbNotRekeyConfig(const std::string &name)
{
    RdbStoreConfig config(name);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    config.EnableRekey(false);
    return config;
}

void RdbInterfaceRekeyTest::InsertData(std::shared_ptr<RdbStore> &store)
{
    int64_t id;
    ValuesBucket values;
    std::string name = "zhangsan";
    int age = 18;
    double salary = 100.5;
    std::vector<uint8_t> blob{ 1, 2, 3 };
    values.PutString("name", name);
    values.PutInt("age", age);
    values.PutDouble("salary", salary);
    values.PutBlob("blobType", blob);
    int insertRet = store->Insert(id, "test", values);
    EXPECT_EQ(insertRet, E_OK);
}

void RdbInterfaceRekeyTest::CheckQueryData(std::shared_ptr<RdbStore> &store)
{
    std::shared_ptr<ResultSet> resultSet =
        store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector<std::string>{ "zhangsan" });
    EXPECT_NE(resultSet, nullptr);
    int result = resultSet->GoToFirstRow();
    EXPECT_EQ(result, E_OK);
    int columnIndex;
    std::string strVal;
    ColumnType columnType;
    result = resultSet->GetColumnIndex("name", columnIndex);
    EXPECT_EQ(result, E_OK);
    result = resultSet->GetColumnType(columnIndex, columnType);
    EXPECT_EQ(result, E_OK);
    EXPECT_EQ(columnType, ColumnType::TYPE_STRING);
    result = resultSet->GetString(columnIndex, strVal);
    EXPECT_EQ(result, E_OK);
    EXPECT_EQ("zhangsan", strVal);

    result = resultSet->Close();
    EXPECT_EQ(result, E_OK);
}

/**
* @tc.name: Rdb_Rekey_Test_001
* @tc.desc: test automatic rekey when database key is expired (over 365 days)
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_01, TestSize.Level1)
{
    std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2";
    std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2.new";

    bool isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);

    bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, RdbInterfaceRekeyTest::HOURS_EXPIRED);
    ASSERT_TRUE(isFileDateChanged);

    RdbStoreConfig config = GetRdbConfig(RdbInterfaceRekeyTest::encryptedDatabasePath);
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);
    isFileExists = OHOS::FileExists(newKeyPath);
    ASSERT_FALSE(isFileExists);

    CheckQueryData(store);
}

/**
* @tc.name: Rdb_Rekey_Test_002
* @tc.desc: test RdbStore with not outdated password
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_02, TestSize.Level1)
{
    std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2";
    bool isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);

    bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, RdbInterfaceRekeyTest::HOURS_NOT_EXPIRED);
    ASSERT_TRUE(isFileDateChanged);

    auto changedDate = GetKeyFileDate(encryptedDatabaseName);
    ASSERT_TRUE(
        std::chrono::system_clock::now() - changedDate > std::chrono::hours(RdbInterfaceRekeyTest::HOURS_NOT_EXPIRED));

    RdbStoreConfig config = GetRdbConfig(RdbInterfaceRekeyTest::encryptedDatabasePath);
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    CheckQueryData(store);
}

/**
* @tc.name: Rdb_Rekey_Test_004
* @tc.desc: try to open store and modify create date to a future time.
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_04, TestSize.Level1)
{
    std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2";
    std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2.new";

    bool isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);

    bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, -RdbInterfaceRekeyTest::HOURS_EXPIRED);
    ASSERT_TRUE(isFileDateChanged);

    RdbStoreConfig config = GetRdbConfig(RdbInterfaceRekeyTest::encryptedDatabasePath);
    RekeyTestOpenCallback helper;
    int errCode;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);

    isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);
    isFileExists = OHOS::FileExists(newKeyPath);
    ASSERT_FALSE(isFileExists);

    CheckQueryData(store);
}

/**
* @tc.name: Rdb_Rekey_RenameFailed_05
* @tc.desc: test rekey when rename operation fails due to .new key file already existing
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_RenameFailed_05, TestSize.Level1)
{
    std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2";
    std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2.new";

    bool isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);

    bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, RdbInterfaceRekeyTest::HOURS_LONG_LONG_AGO);
    ASSERT_TRUE(isFileDateChanged);

    RdbStoreConfig config = GetRdbConfig(RdbInterfaceRekeyTest::encryptedDatabasePath);
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    for (int i = 0; i < 50; ++i) {
        auto store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
        ASSERT_NE(store, nullptr);
        ASSERT_EQ(errCode, E_OK);
        store = nullptr;
        SaveNewKey(encryptedDatabaseName);
    }

    auto store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    CheckQueryData(store);
}

/**
* @tc.name: Rdb_Delete_Rekey_Test_06
* @tc.desc: test that rekey is skipped when rekey is disabled in config
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_06, TestSize.Level1)
{
    std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2";
    std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2.new";

    bool isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);

    bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, RdbInterfaceRekeyTest::HOURS_EXPIRED);
    ASSERT_TRUE(isFileDateChanged);

    auto changedDate = GetKeyFileDate(encryptedDatabaseName);
    ASSERT_TRUE(
        std::chrono::system_clock::now() - changedDate > std::chrono::hours(RdbInterfaceRekeyTest::HOURS_EXPIRED));

    RdbStoreConfig config = GetRdbNotRekeyConfig(RdbInterfaceRekeyTest::encryptedDatabasePath);
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);
    isFileExists = OHOS::FileExists(newKeyPath);
    ASSERT_FALSE(isFileExists);

    ASSERT_TRUE(
        std::chrono::system_clock::now() - changedDate > std::chrono::hours(RdbInterfaceRekeyTest::HOURS_EXPIRED));
    CheckQueryData(store);
}

/**
* @tc.name: Rdb_Delete_Rekey_Test_07
* @tc.desc: test deleting the key file of the encrypted database
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_07, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetAllowRebuild(true);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2";
    bool isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);
    struct stat fileStat;
    ino_t inodeNumber1 = -1;
    if (stat(keyPath.c_str(), &fileStat) == 0) {
        inodeNumber1 = fileStat.st_ino;
    }
    store = nullptr;

    {
        std::ofstream fsDb(encryptedDatabasePath, std::ios_base::binary | std::ios_base::out);
        fsDb.seekp(64);
        fsDb.write("hello", 5);
        fsDb.close();
    }

    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);
    ino_t inodeNumber2 = -1;
    if (stat(keyPath.c_str(), &fileStat) == 0) {
        inodeNumber2 = fileStat.st_ino;
    }

    ASSERT_NE(inodeNumber1, inodeNumber2);
}

/**
* @tc.name: Rdb_Delete_Rekey_Test_08
* @tc.desc: test key file is NOT regenerated when database is corrupted and AllowRebuild is false
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_08, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetAllowRebuild(false);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2";
    bool isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);
    struct stat fileStat;
    ino_t inodeNumber1 = -1;
    if (stat(keyPath.c_str(), &fileStat) == 0) {
        inodeNumber1 = fileStat.st_ino;
    }
    store = nullptr;

    {
        std::ofstream fsDb(encryptedDatabasePath, std::ios_base::binary | std::ios_base::out);
        fsDb.seekp(64);
        fsDb.write("hello", 5);
        fsDb.close();
    }

    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);
    ino_t inodeNumber2 = -1;
    if (stat(keyPath.c_str(), &fileStat) == 0) {
        inodeNumber2 = fileStat.st_ino;
    }

    ASSERT_EQ(inodeNumber1, inodeNumber2);
}

/**
* @tc.name: Rdb_Delete_Rekey_Test_009
* @tc.desc: test Rekey with invalid CryptoParam parameters returns E_INVALID_ARGS_NEW
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_009, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetAllowRebuild(false);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
 
    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam cryptoParam1;
    cryptoParam1.iterNum = -1;
    errCode = store->Rekey(cryptoParam1);
    ASSERT_EQ(errCode, E_INVALID_ARGS_NEW);

    RdbStoreConfig::CryptoParam cryptoParam2;
    cryptoParam2.encryptAlgo = -1;
    errCode = store->Rekey(cryptoParam2);
    ASSERT_EQ(errCode, E_INVALID_ARGS_NEW);

    RdbStoreConfig::CryptoParam cryptoParam3;
    cryptoParam3.hmacAlgo = -1;
    errCode = store->Rekey(cryptoParam3);
    ASSERT_EQ(errCode, E_INVALID_ARGS_NEW);

    RdbStoreConfig::CryptoParam cryptoParam4;
    cryptoParam4.kdfAlgo = -1;
    errCode = store->Rekey(cryptoParam4);
    ASSERT_EQ(errCode, E_INVALID_ARGS_NEW);

    RdbStoreConfig::CryptoParam cryptoParam5;
    cryptoParam5.cryptoPageSize = -1;
    errCode = store->Rekey(cryptoParam5);
    ASSERT_EQ(errCode, E_INVALID_ARGS_NEW);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);
}
 
/**
* @tc.name: Rdb_Delete_Rekey_Test_010
* @tc.desc: test Rekey on non-encrypted database returns E_NOT_SUPPORT
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_010, TestSize.Level1)
{
    const std::string encryptedDatabaseName1 = "encrypted1.db";
    const std::string encryptedDatabasePath1 = RDB_TEST_PATH + encryptedDatabaseName1;
    RdbStoreConfig config(encryptedDatabasePath1);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan1"));
    values.PutInt("age", 50);
    values.PutDouble("salary", 263);
    values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3, 4, 5});
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam cryptoParam;
    auto isEncrypt = config.IsEncrypt();
    ASSERT_EQ(isEncrypt, false);
    errCode = store->Rekey(cryptoParam);
    ASSERT_EQ(errCode, E_NOT_SUPPORT);

    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    errCode = store->Rekey(cryptoParam);
    ASSERT_EQ(errCode, E_NOT_SUPPORT);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi1"));
    values.PutInt("age", 191);
    values.PutDouble("salary", 2001.5);
    values.PutBlob("blobType", std::vector<uint8_t>{ 4, 5, 6, 7 });
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);

    ret = RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}
 
/**
* @tc.name: Rdb_Delete_Rekey_Test_011
* @tc.desc: test Rekey with modified CryptoParam parameters returns E_NOT_SUPPORT for default encrypted database
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_011, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetBundleName("com.example.test_rekey");
    config.SetEncryptStatus(true);
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("1zhangsan"));
    values.PutInt("age", 118);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam cryptoParam1;
    cryptoParam1.iterNum = 500;
    errCode = store->Rekey(cryptoParam1);
    ASSERT_EQ(errCode, E_NOT_SUPPORT);

    RdbStoreConfig::CryptoParam cryptoParam2;
    cryptoParam2.encryptAlgo = EncryptAlgo::AES_256_CBC;
    errCode = store->Rekey(cryptoParam2);
    ASSERT_EQ(errCode, E_NOT_SUPPORT);

    RdbStoreConfig::CryptoParam cryptoParam3;
    cryptoParam3.hmacAlgo = HmacAlgo::SHA512;
    errCode = store->Rekey(cryptoParam3);
    ASSERT_EQ(errCode, E_NOT_SUPPORT);

    RdbStoreConfig::CryptoParam cryptoParam4;
    cryptoParam4.kdfAlgo = KdfAlgo::KDF_SHA512;
    errCode = store->Rekey(cryptoParam4);
    ASSERT_EQ(errCode, E_NOT_SUPPORT);

    RdbStoreConfig::CryptoParam cryptoParam5;
    cryptoParam5.cryptoPageSize = 2048;
    errCode = store->Rekey(cryptoParam5);
    ASSERT_EQ(errCode, E_NOT_SUPPORT);

    ret = RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}
 
/**
* @tc.name: Rdb_Delete_Rekey_Test_012
* @tc.desc: test Rekey successfully changes custom encryption key and data remains accessible
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_012, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    config.SetCryptoParam(cryptoParam);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);
 
    RdbStoreConfig::CryptoParam newCryptoParam;
    newCryptoParam.encryptKey_ = std::vector<uint8_t>{ 6, 2, 3, 4, 5, 1 };
    errCode = store->Rekey(newCryptoParam);
    ASSERT_EQ(errCode, E_OK);
 
    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    store = nullptr;
    config.SetCryptoParam(newCryptoParam);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);

    RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}
 
 
/**
* @tc.name: Rdb_Delete_Rekey_Test_013
* @tc.desc: test Rekey from default encrypted to custom encrypted returns E_NOT_SUPPORT
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_013, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    int changedRows;
    values.Clear();
    values.PutInt("age", 30);
    ret = store->Update(changedRows, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, changedRows);

    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    errCode = store->Rekey(cryptoParam);
    ASSERT_EQ(errCode, E_NOT_SUPPORT);
 
    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    values.Clear();
    values.PutInt("age", 60);
    ret = store->Update(changedRows, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, changedRows);
 
    ret = RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}
 
/**
* @tc.name: Rdb_Delete_Rekey_Test_014
* @tc.desc: test Rekey from default encrypted to default encrypted with rekey operation
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_014, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam cryptoParam;
    errCode = store->Rekey(cryptoParam);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    int changedRows = 0;
    AbsRdbPredicates predicates("test1");
    predicates.EqualTo("id", 1);
    ret = store->Delete(changedRows, predicates);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(changedRows, 1);

    store = nullptr;
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 1);
}
 
 
/**
* @tc.name: Rdb_Delete_Rekey_Test_015
* @tc.desc: test Rekey from custom encrypted to default encrypted returns E_NOT_SUPPORT
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_015, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    config.SetCryptoParam(cryptoParam);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    RdbHelper::DeleteRdbStore(config);
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");
    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);

    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam newCryptoParam;
    errCode = store->Rekey(newCryptoParam);
    ASSERT_EQ(errCode, E_NOT_SUPPORT);
 
    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    store = nullptr;
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);

    RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}
 
/**
* @tc.name: Rdb_Delete_Rekey_Test_016
* @tc.desc: test Rekey during EXCLUSIVE transaction returns E_DATABASE_BUSY
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_016, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetAllowRebuild(false);
    config.SetEncryptStatus(true);
    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    config.SetCryptoParam(cryptoParam);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    RdbHelper::DeleteRdbStore(config);
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)");

    auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
    ASSERT_EQ(ret, E_OK);
    ASSERT_NE(transaction, nullptr);

    auto result = transaction->Insert("test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
    ASSERT_EQ(result.first, E_OK);
    ASSERT_EQ(1, result.second);

    std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2";
    bool isFileExists = OHOS::FileExists(keyPath);
    ASSERT_FALSE(isFileExists);

    RdbStoreConfig::CryptoParam newCryptoParam;
    newCryptoParam.encryptKey_ = std::vector<uint8_t>{ 6, 5, 4, 3, 2, 1 };
    errCode = store->Rekey(newCryptoParam);
    ASSERT_EQ(errCode, E_DATABASE_BUSY);

    result = transaction->Insert("test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[1]));
    ASSERT_EQ(result.first, E_OK);
    ASSERT_EQ(2, result.second);

    auto resultSet = transaction->QueryByStep("SELECT * FROM test");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);

    ret = transaction->Commit();
    ASSERT_EQ(ret, E_OK);

    resultSet = store->QueryByStep("SELECT * FROM test");
    ASSERT_NE(resultSet, nullptr);
    resultSet->GetRowCount(rowCount);
    EXPECT_EQ(rowCount, 2);

    RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}
 
/**
* @tc.name: Rdb_Delete_Rekey_Test_017
* @tc.desc: test Rekey during DEFERRED transaction returns E_DATABASE_BUSY
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_017, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetAllowRebuild(false);
    config.SetEncryptStatus(true);
    RdbStoreConfig::CryptoParam cryptoParam;
    config.SetCryptoParam(cryptoParam);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    RdbHelper::DeleteRdbStore(config);
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
 
    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)");
    
    auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED);
    ASSERT_EQ(ret, E_OK);
    ASSERT_NE(transaction, nullptr);
 
    auto result = transaction->Insert("test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
    ASSERT_EQ(result.first, E_OK);
    ASSERT_EQ(1, result.second);
 
    std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2";
    bool isFileExists = OHOS::FileExists(keyPath);
    ASSERT_TRUE(isFileExists);
 
    RdbStoreConfig::CryptoParam newCryptoParam;
    errCode = store->Rekey(newCryptoParam);
    ASSERT_EQ(errCode, E_DATABASE_BUSY);
 
    result = transaction->Insert("test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[1]));
    ASSERT_EQ(result.first, E_OK);
    ASSERT_EQ(2, result.second);
 
    auto resultSet = transaction->QueryByStep("SELECT * FROM test");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);
 
    ret = transaction->Commit();
    ASSERT_EQ(ret, E_OK);
 
    resultSet = store->QueryByStep("SELECT * FROM test");
    ASSERT_NE(resultSet, nullptr);
    resultSet->GetRowCount(rowCount);
    EXPECT_EQ(rowCount, 2);
 
    RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}

/**
* @tc.name: Rdb_Delete_Rekey_Test_018
* @tc.desc: test Rekey on read-only database returns E_NOT_SUPPORT
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_018, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetEncryptStatus(true);
    config.SetReadOnly(true);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    RdbStoreConfig::CryptoParam cryptoParam1;

    errCode = store->Rekey(cryptoParam1);
    ASSERT_EQ(errCode, E_NOT_SUPPORT);

    int ret = RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}

/**
* @tc.name: Rdb_Delete_Rekey_Test_019
* @tc.desc: test multi-threaded Rekey operations for thread safety
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_019, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    config.SetCryptoParam(cryptoParam);
    config.SetBundleName("com.example.test_rekey");
    config.SetEncryptStatus(true);
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    
    auto blockResult = std::make_shared<OHOS::BlockData<bool>>(3, false);
    std::thread thread([store, blockResult]() {
        RdbStoreConfig::CryptoParam cryptoParam;
        cryptoParam.encryptKey_ = std::vector<uint8_t>{ 6, 2, 3, 4, 5, 1 };
        int ret1 = store->Rekey(cryptoParam);
        LOG_INFO("Rdb_Rekey_019 thread Rekey finish, code:%{public}d", ret1);
        blockResult->SetValue(true);
    });
    thread.detach();
    RdbStoreConfig::CryptoParam cryptoParam2;
    cryptoParam2.encryptKey_ = std::vector<uint8_t>{ 6, 5, 3, 4, 2, 1 };
    int ret2 = store->Rekey(cryptoParam2);
    LOG_INFO("Rdb_Rekey_019 main Rekey finish, code:%{public}d", ret2);
    EXPECT_TRUE(blockResult->GetValue());

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)");
    
    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan1"));
    values.PutInt("age", 50);
    values.PutDouble("salary", 263);
    values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3, 4, 5 });
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    int changedRows;
    values.Clear();
    values.PutInt("age", 30);
    ret = store->Update(changedRows, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, changedRows);

    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 1);
}

/**
* @tc.name: Rdb_Rekey_020
* @tc.desc: test RekeyEx converts non-encrypted database to encrypted database
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_020, TestSize.Level1)
{
    const std::string encryptedDatabaseName1 = "encrypted1.db";
    const std::string encryptedDatabasePath1 = RDB_TEST_PATH + encryptedDatabaseName1;
    RdbStoreConfig config(encryptedDatabasePath1);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan1"));
    values.PutInt("age", 50);
    values.PutDouble("salary", 263);
    values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3, 4, 5 });
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam cryptoParam;
    auto isEncrypt = config.IsEncrypt();
    ASSERT_EQ(isEncrypt, false);
    errCode = store->RekeyEx(cryptoParam);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi1"));
    values.PutInt("age", 191);
    values.PutDouble("salary", 2001.5);
    values.PutBlob("blobType", std::vector<uint8_t>{ 4, 5, 6, 7 });
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    store = nullptr;
    config.SetEncryptStatus(true);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);

    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);

    ret = RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}

/**
* @tc.name: Rdb_Rekey_021
* @tc.desc: test RekeyEx successfully modifies encryption parameters (iterNum, encryptAlgo, etc.)
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_021, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetBundleName("com.example.test_rekey");
    config.SetEncryptStatus(true);
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("1zhangsan"));
    values.PutInt("age", 118);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam cryptoParam1;
    cryptoParam1.iterNum = 500;
    cryptoParam1.encryptAlgo = EncryptAlgo::AES_256_CBC;
    errCode = store->RekeyEx(cryptoParam1);
    ASSERT_EQ(errCode, E_OK);

    RdbStoreConfig::CryptoParam cryptoParam2;
    cryptoParam2.hmacAlgo = HmacAlgo::SHA512;
    cryptoParam2.kdfAlgo = KdfAlgo::KDF_SHA512;
    cryptoParam2.cryptoPageSize = 2048;
    errCode = store->RekeyEx(cryptoParam2);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    store = nullptr;
    config.SetCryptoParam(cryptoParam2);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);
}

/**
* @tc.name: Rdb_Rekey_022
* @tc.desc: test RekeyEx successfully changes custom encryption key to new custom key
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_022, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    config.SetCryptoParam(cryptoParam);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    errCode = RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(errCode, E_OK);
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam newCryptoParam;
    newCryptoParam.encryptKey_ = std::vector<uint8_t>{ 6, 2, 3, 4, 5, 1 };
    errCode = store->RekeyEx(newCryptoParam);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    store = nullptr;
    config.SetCryptoParam(newCryptoParam);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);

    RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}

/**
* @tc.name: Rdb_Rekey_023
* @tc.desc: test RekeyEx converts default encrypted database to custom encrypted database
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_023, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    int changedRows;
    values.Clear();
    values.PutInt("age", 30);
    ret = store->Update(changedRows, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, changedRows);

    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    errCode = store->RekeyEx(cryptoParam);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    store = nullptr;
    config.SetCryptoParam(cryptoParam);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);

    values.Clear();
    values.PutInt("age", 60);
    ret = store->Update(changedRows, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, changedRows);

    ret = RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}

/**
* @tc.name: Rdb_Rekey_024
* @tc.desc: test RekeyEx performs rekey operation on default encrypted database
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_024, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam cryptoParam;
    errCode = store->RekeyEx(cryptoParam);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    int changedRows = 0;
    AbsRdbPredicates predicates("test1");
    predicates.EqualTo("id", 1);
    ret = store->Delete(changedRows, predicates);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(changedRows, 1);

    store = nullptr;
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 1);
}

/**
* @tc.name: Rdb_Rekey_025
* @tc.desc: test RekeyEx converts custom encrypted database to default encrypted database
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_025, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    config.SetCryptoParam(cryptoParam);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    RdbHelper::DeleteRdbStore(config);
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");
    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);

    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam newCryptoParam;
    errCode = store->RekeyEx(newCryptoParam);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    store = nullptr;
    config.SetCryptoParam(newCryptoParam);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);

    RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}

/**
* @tc.name: Rdb_Rekey_026
* @tc.desc: test RekeyEx converts encrypted database to non-encrypted (PLAIN_TEXT) database
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_026, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptAlgo = EncryptAlgo::PLAIN_TEXT;
    errCode = store->RekeyEx(cryptoParam);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    int changedRows = 0;
    AbsRdbPredicates predicates("test1");
    predicates.EqualTo("id", 1);
    ret = store->Delete(changedRows, predicates);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(changedRows, 1);

    store = nullptr;
    config.SetEncryptStatus(false);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 1);
}

/**
* @tc.name: Rdb_Rekey_027
* @tc.desc: test RekeyEx successfully modifies iteration count (iterNum) parameter
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_027, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetBundleName("com.example.test_rekey");
    config.SetEncryptStatus(true);
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("1zhangsan"));
    values.PutInt("age", 118);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam cryptoParam1;
    cryptoParam1.iterNum = 500;
    errCode = store->RekeyEx(cryptoParam1);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    store = nullptr;
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_EQ(store, nullptr);
    config.SetCryptoParam(cryptoParam1);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);

    ret = RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}

/**
* @tc.name: Rdb_Rekey_028
* @tc.desc: test RekeyEx successfully modifies encryption algorithm and iteration count
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_028, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    config.SetCryptoParam(cryptoParam);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;

    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam newCryptoParam;
    newCryptoParam.encryptKey_ = std::vector<uint8_t>{ 6, 2, 3, 4, 5, 1 };
    newCryptoParam.encryptAlgo = EncryptAlgo::AES_256_CBC;
    newCryptoParam.iterNum = 500;
    errCode = store->RekeyEx(newCryptoParam);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    store = nullptr;
    config.SetCryptoParam(newCryptoParam);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);
}

/**
* @tc.name: Rdb_Rekey_029
* @tc.desc: test RekeyEx successfully modifies HMAC algorithm parameter
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_029, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    int changedRows;
    values.Clear();
    values.PutInt("age", 30);
    ret = store->Update(changedRows, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, changedRows);

    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    cryptoParam.hmacAlgo = HmacAlgo::SHA512;
    errCode = store->RekeyEx(cryptoParam);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    store = nullptr;
    config.SetCryptoParam(cryptoParam);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);

    values.Clear();
    values.PutInt("age", 60);
    ret = store->Update(changedRows, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, changedRows);

    ret = RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}

/**
* @tc.name: Rdb_Rekey_030
* @tc.desc: test RekeyEx successfully modifies key derivation function (KDF) algorithm parameter
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_030, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");

    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);
    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.kdfAlgo = KdfAlgo::KDF_SHA512;
    errCode = store->RekeyEx(cryptoParam);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    int changedRows = 0;
    AbsRdbPredicates predicates("test1");
    predicates.EqualTo("id", 1);
    ret = store->Delete(changedRows, predicates);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(changedRows, 1);

    store = nullptr;
    config.SetCryptoParam(cryptoParam);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 1);
}

/**
* @tc.name: Rdb_Rekey_031
* @tc.desc: test RekeyEx successfully modifies crypto page size parameter
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_031, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetEncryptStatus(true);
    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    config.SetCryptoParam(cryptoParam);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    RdbHelper::DeleteRdbStore(config);
    int errCode = E_OK;
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER)");
    int64_t id;
    ValuesBucket values;
    values.PutInt("id", 1);
    values.PutString("name", std::string("zhangsan"));
    values.PutInt("age", 18);

    int ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(1, id);

    RdbStoreConfig::CryptoParam newCryptoParam;
    newCryptoParam.cryptoPageSize = 2048;
    errCode = store->RekeyEx(newCryptoParam);
    ASSERT_EQ(errCode, E_OK);

    values.Clear();
    values.PutInt("id", 2);
    values.PutString("name", std::string("lisi"));
    values.PutInt("age", 19);
    ret = store->Insert(id, "test1", values);
    EXPECT_EQ(ret, E_OK);
    EXPECT_EQ(2, id);

    store = nullptr;
    config.SetCryptoParam(newCryptoParam);
    store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);
    auto resultSet = store->QueryByStep("SELECT * FROM test1");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);

    RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}

/**
* @tc.name: Rdb_Rekey_032
* @tc.desc: test RekeyEx during EXCLUSIVE transaction returns E_SQLITE_BUSY
* @tc.type: FUNC
*/
HWTEST_F(RdbInterfaceRekeyTest, Rdb_Rekey_032, TestSize.Level1)
{
    RdbStoreConfig config(RdbInterfaceRekeyTest::encryptedDatabasePath);
    config.SetSecurityLevel(SecurityLevel::S1);
    config.SetAllowRebuild(false);
    config.SetEncryptStatus(true);
    RdbStoreConfig::CryptoParam cryptoParam;
    cryptoParam.encryptKey_ = std::vector<uint8_t>{ 1, 2, 3, 4, 5, 6 };
    config.SetCryptoParam(cryptoParam);
    config.SetBundleName("com.example.test_rekey");
    RekeyTestOpenCallback helper;
    int errCode = E_OK;
    RdbHelper::DeleteRdbStore(config);
    std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    ASSERT_NE(store, nullptr);
    ASSERT_EQ(errCode, E_OK);

    store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)");

    auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
    ASSERT_EQ(ret, E_OK);
    ASSERT_NE(transaction, nullptr);

    auto result = transaction->Insert("test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
    ASSERT_EQ(result.first, E_OK);
    ASSERT_EQ(1, result.second);

    std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v2";
    bool isFileExists = OHOS::FileExists(keyPath);
    ASSERT_FALSE(isFileExists);

    RdbStoreConfig::CryptoParam newCryptoParam;
    newCryptoParam.encryptKey_ = std::vector<uint8_t>{ 6, 5, 4, 3, 2, 1 };
    errCode = store->RekeyEx(newCryptoParam);
    ASSERT_EQ(errCode, E_SQLITE_BUSY);

    result = transaction->Insert("test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[1]));
    ASSERT_EQ(result.first, E_OK);
    ASSERT_EQ(2, result.second);

    auto resultSet = transaction->QueryByStep("SELECT * FROM test");
    ASSERT_NE(resultSet, nullptr);
    int32_t rowCount{};
    ret = resultSet->GetRowCount(rowCount);
    ASSERT_EQ(ret, E_OK);
    ASSERT_EQ(rowCount, 2);

    ret = transaction->Commit();
    ASSERT_EQ(ret, E_OK);

    resultSet = store->QueryByStep("SELECT * FROM test");
    ASSERT_NE(resultSet, nullptr);
    resultSet->GetRowCount(rowCount);
    EXPECT_EQ(rowCount, 2);

    RdbHelper::DeleteRdbStore(config);
    EXPECT_EQ(ret, E_OK);
}