鸿蒙Des 加密解密 C++版本

鸿蒙Des 加密解密 C++版本

参考文件

写文档的时候,现在的 API 主流版本可能还是 API15 及以上,des 加密算法是在 API20 的时候才加入的。但是 API20 预计升级也是在 2025.10 月以后了。当前用到了 DES 加密解密,因此还是需要想办法实现一下的。

而且当前需要的是一个把 so 库的版本,需要把 Des 加密算法使用 c++实现,并且打包到 so 库中。

本文主要介绍一下,如何实现 Des 加密解密的 c++ 版本。

cryptopp 库

当然肯定不是自己实现一套加解密算法,现在是用的 cryptoPP 库,cryptoPP 库是一个开源的加解密库,支持多种加解密算法,包括 DES、AES、RSA 等。

cryptopp 项目地址:https://gitcode.com/openharmony-sig/tpc_c_cplusplus/tree/master/thirdparty/cryptopp

下载项目代码

base 复制代码
git clone https://gitcode.com/openharmony-sig/tpc_c_cplusplus.git

配置编译环境

下载 command line tools

https://developer.huawei.com/consumer/cn/download/

导出 OHOS_SDK 环境变量
base 复制代码
export OHOS_SDK=~/command-line-tools/sdk/default/openharmony
拷贝必要鸿蒙平台的 cmake

这个地方可能要根据自己的本地的 cmake 地址来修改路径

base 复制代码
cp command-line-tools/sdk/default/openharmony/native/build-tools/cmake/share/cmake-3.28/Modules/Platform/OHOS.cmake /opt/homebrew/Cellar/cmake/4.0.2/share/cmake/Modules/Platform/
进入到相应的编译工具文件夹
base 复制代码
cd tpc_c_cplusplus/lycium/Buildtools
解压工具链
base 复制代码
tar -zxvf toolchain.tar.gz
拷贝必要的编译工具
base 复制代码
cp toolchain/\* command-line-tools/sdk/default/openharmony/native/llvm/bin/
进入到

tpc_c_cplusplus/lycium

开始编译

./build cryptopp

之后产物就在 lycium/usr 目录下

cd tpc_c_cplusplus/lycium/usr

在之后就可以根据文档来引入相关的库来编译 cryptopp

接入到项目中

如果是新项目,可以选择模版的时候创建 c++模版,这次主要说一下如何在已有项目中接入 c++库;

创建相应的目录

在 src/main 的目录下创建 cpp 文件夹。

cpp 文件夹下包含以下文件/文件夹:

bash 复制代码
├── CMakeLists.txt // c++ cmake 编译文件
├── include // 头文件目录
├── napi_init.cpp // 同arkts交互的接口文件,一般逻辑都在这个地方
├── thirdparty // 第三方目录文件,刚才编译完的crypto的文件直接拷贝到这个地方
    ├── cryptopp
        ├── arm64-v8a
        ├── armeabi-v7a
├── types
    ├── libentry
        ├── Index.d.ts // 导出的so接口
        ├── oh-package.json5 // so的配置文件

CMakeLists.txt

bash 复制代码
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.5.0)
project(Encrypt) // 可以改一个名字,不过影响不大

set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

if(DEFINED PACKAGE_FIND_FILE)
    include(${PACKAGE_FIND_FILE})
endif()

include_directories(${NATIVERENDER_ROOT_PATH}
                    ${NATIVERENDER_ROOT_PATH}/include)

add_library(entry SHARED napi_init.cpp)
target_link_libraries(entry PUBLIC libace_napi.z.so)
target_link_libraries(entry PUBLIC libohcrypto.so)
target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so)

# 这个地方是 cryptopp 库的引入文件方式
#将三方库加入工程中
target_link_libraries(entry PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/cryptopp/${OHOS_ARCH}/lib/libcryptopp.a)
#将三方库的头文件加入工程中
target_include_directories(entry PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/cryptopp/${OHOS_ARCH}/include)

napi_init.cpp

实现了一个解密算法,加密算法稍微改改参数就可以了。

c 复制代码
#include "napi/native_api.h"
#include <iostream>
#include <random>
#include <ctime>
#include <string.h>
#include <cstring>
#include "hilog/log.h"
#include "cryptopp/des.h"
#include "cryptopp/rsa.h"
#include "cryptopp/cryptlib.h"
#include "cryptopp/base64.h"
#include "cryptopp/filters.h"
#include "cryptopp/modes.h"
#include "cryptopp/hex.h"
#include "cryptopp/osrng.h"
#include "cryptopp/config_int.h"

std::string hexDecode(const std::string& hexStr) {
    std::string decoded;
    CryptoPP::StringSource ss(
        hexStr, true,
        new CryptoPP::HexDecoder(new CryptoPP::StringSink(decoded))
    );
    return decoded;
}

std::string generate_random_alphanumeric_string() {
    const std::string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    const int length = 8; // 固定生成8位字符串
    std::string result;

    // 使用随机设备作为种子(更安全)[2,5](@ref)
    std::random_device rd;
    std::mt19937 generator(rd());
    std::uniform_int_distribution<size_t> distribution(0, charset.size() - 1);

    // 预分配空间以提高性能[5](@ref)
    result.reserve(length);
    for (int i = 0; i < length; ++i) {
        result += charset[distribution(generator)];
    }
    return result;
}

static napi_value doDesDecrypt(napi_env env, napi_callback_info info)
{
    size_t argc = 2;
    napi_value args[2] = {nullptr};

    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);

    // 获取加密字符串
    size_t encrypted_length = 0;
    napi_status status = napi_get_value_string_utf8(env, args[0], nullptr, 0, &encrypted_length);
    if (status != napi_ok) {
        return nullptr;
    }
    char* encryptedStr = new char[encrypted_length + 1];
    std::memset(encryptedStr, 0, encrypted_length + 1);
    status = napi_get_value_string_utf8(env, args[0], encryptedStr, encrypted_length + 1, &encrypted_length);
    if (status != napi_ok) {
        if (encryptedStr) {
            delete[] encryptedStr;
        }
        return nullptr;
    }

    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);

    size_t key_length = 0;
    napi_status status = napi_get_value_string_utf8(env, args[1], nullptr, 0, &key_length);
    if (status != napi_ok) {
        OH_LOG_ERROR(LOG_APP, "xxx get key failed");
        return nullptr;
    }

    char* keyStr = new char[key_length + 1];
    std::memset(keyStr, 0, key_length + 1);
    status = napi_get_value_string_utf8(env, args[1], keyStr, key_length + 1, &key_length);
    if (status != napi_ok) {
        if (keyStr) {
            delete[] keyStr;
        }
        OH_LOG_ERROR(LOG_APP, "xxx copy key failed");
        return nullptr;
    }

    CryptoPP::ECB_Mode<CryptoPP::DES>::Decryption decryptor;
    decryptor.SetKey(reinterpret_cast<const CryptoPP::byte*>(keyStr), key_length);

    std::string decrypted;
    CryptoPP::StringSource ss(
        hexDecode(encryptedStr), true,
        new CryptoPP::StreamTransformationFilter(
            decryptor,
            new CryptoPP::StringSink(decrypted)
        )
    );

    napi_value result = nullptr;
    status = napi_create_string_utf8(env, decrypted.data(), decrypted.size(), &result);
    if (status != napi_ok) {
        napi_throw_error(env, nullptr, "Failed to create UTF-8 string");
        return nullptr;
    }
    return result;
}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
    napi_property_descriptor desc[] = {
        { "decrypt", nullptr, doDesDecrypt, nullptr, nullptr, nullptr, napi_default, nullptr},
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void*)0),
    .reserved = { 0 },
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{
    napi_module_register(&demoModule);
}

Index.d.ts

导出相应的函数,如果在 napi_init.cpp 中保存一个全局变量,那么在导出的函数中也能够使用。

javacript 复制代码
export const decrypt: (encrypted: string, key: string) => string;

oh-package.json5

json 复制代码
{
  "name": "libentry.so",
  "types": "./Index.d.ts",
  "version": "1.0.0",
  "description": "Please describe the basic information."
}

build-profile.json

然后需要在模块的编译配置中增加如下配置:

json 复制代码
  "buildOption": {
    "externalNativeOptions": {
      "path": "./src/main/cpp/CMakeLists.txt",
      "arguments": "",
      "cppFlags": "",
    }
  },

模块 package 依赖中增加 c++模块依赖

json 复制代码
  "dependencies": {
    "libentry.so": "file:./src/main/cpp/types/libentry"
  }

结束

这样基本上就完成了 c++模块的加密解密功能的实现,在 ts 中调用也比较方便。

javascript 复制代码
import libEntry from 'libentry.so' // libEntry 是随便起了个名字
let res = libEntry.decrypt('des加密串', 'des密钥')
相关推荐
程序猿编码25 分钟前
基于LLVM的memcpy静态分析工具:设计思路与原理解析(C/C++代码实现)
c语言·c++·静态分析·llvm·llvm ir
猪蹄手29 分钟前
C/C++基础详解(三)
开发语言·jvm·c++
再睡一夏就好36 分钟前
【排序算法】④堆排序
c语言·数据结构·c++·笔记·算法·排序算法
程序员莫小特41 分钟前
老题新解|求一元二次方程
数据结构·c++·算法·青少年编程·c·信息学奥赛一本通
森林古猿11 小时前
论区间dp:常用模型(附极角排序教程)
c++·学习·算法·排序算法·动态规划·几何学
阿巴~阿巴~1 小时前
string 类元素访问方法
开发语言·c++
li理2 小时前
鸿蒙应用本地数据库导出与查看指南
harmonyos
li理2 小时前
HarmonyOS 鸿蒙 本地数据库开发实战指南:从原理到封装
harmonyos
watson_pillow2 小时前
mfc按钮点击事件没有触发,且程序卡死
c++·mfc
404未精通的狗3 小时前
(C++)继承全解析及运用
开发语言·c++