前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ArkUI实战开发-引入三方库

ArkUI实战开发-引入三方库

原创
作者头像
小帅聊鸿蒙
发布2024-10-10 21:39:53
830
发布2024-10-10 21:39:53
举报
文章被收录于专栏:鸿蒙开发笔记

笔者在第 4 小节里基于前 3 小结的知识点简单扩展了一个 md5() 方法并成功在 JS 代码里调起了 C++ 代码,本节笔者简单介绍一下引入三方库编译的知识点。

引入MD5源码

上一小节的 md5() 方法实现只是简单模拟,并没有真正实现 MD5 的计算,因此笔者从网上找了一个 MD5 计算的源码并引入工程,工程目录如下所示:

其中 md5.h 源码如下所示:

代码语言:cpp
复制
//
// Created on 2023/2/28.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef oh_0400_napi_md5_H
#define oh_0400_napi_md5_H

/* Parameters of MD5\. */
#define s11 7
#define s12 12
#define s13 17
#define s14 22

#define s21 5
#define s22 9
#define s23 14
#define s24 20

#define s31 4
#define s32 11
#define s33 16
#define s34 23

#define s41 6
#define s42 10
#define s43 15
#define s44 21

#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))

#define ROTATELEFT(num, n) (((num) << (n)) | ((num) >> (32-(n))))

#define FF(a, b, c, d, x, s, ac) { \
  (a) += F ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
  (a) += G ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
  (a) += H ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
  (a) += I ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}

#include <string>
#include <cstring>

using std::string;

/* Define of btye.*/
typedef unsigned char byte;
/* Define of byte. */
typedef unsigned int bit32;

class MD5 {
public:
    /* Construct a MD5 object with a string. */
    MD5(const string& message);

    /* Generate md5 digest. */
    const byte* getDigest();

    /* Convert digest to string value */
    string toStr();

private:
    /* Initialization the md5 object, processing another message block,
     * and updating the context.*/
    void init(const byte* input, size_t len);

    /* MD5 basic transformation. Transforms state based on block. */
    void transform(const byte block[64]);

    /* Encodes input (usigned long) into output (byte). */
    void encode(const bit32* input, byte* output, size_t length);

    /* Decodes input (byte) into output (usigned long). */
    void decode(const byte* input, bit32* output, size_t length);

private:
    /* Flag for mark whether calculate finished. */
    bool finished;

    /* state (ABCD). */
    bit32 state[4];

    /* number of bits, low-order word first. */
    bit32 count[2];

    /* input buffer. */
    byte buffer[64];

    /* message digest. */
    byte digest[16];

    /* padding for calculate. */
    static const byte PADDING[64];

    /* Hex numbers. */
    static const char HEX_NUMBERS[16];
};

#endif //oh_0400_napi_md5_H

md5.cpp 源码如下所示:

代码语言:cpp
复制
//
// Created on 2023/2/28.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#include "md5.h"
#include <string>

/* Define the static member of MD5\. */
const byte MD5::PADDING[64] = { 0x80 };
const char MD5::HEX_NUMBERS[16] = {
        '0', '1', '2', '3',
        '4', '5', '6', '7',
        '8', '9', 'a', 'b',
        'c', 'd', 'e', 'f'
};

MD5::MD5(const string& message) {
    finished = false;
    /* Reset number of bits. */
    count[0] = count[1] = 0;

    /* Initialization constants. */
    state[0] = 0x67452301;
    state[1] = 0xefcdab89;
    state[2] = 0x98badcfe;
    state[3] = 0x10325476;

    /* Initialization the object according to message. */
    init((const byte*)message.c_str(), message.length());
}

/**
 * @Generate md5 digest.
 *
 * @return the message-digest.
 *
 */
const byte* MD5::getDigest() {
    if (!finished) {
        finished = true;

        byte bits[8];
        bit32 oldState[4];
        bit32 oldCount[2];
        bit32 index, padLen;

        /* Save current state and count. */
        memcpy(oldState, state, 16);
        memcpy(oldCount, count, 8);

        /* Save number of bits */
        encode(count, bits, 8);

        /* Pad out to 56 mod 64\. */
        index = (bit32)((count[0] >> 3) & 0x3f);
        padLen = (index < 56) ? (56 - index) : (120 - index);
        init(PADDING, padLen);

        /* Append length (before padding) */
        init(bits, 8);

        /* Store state in digest */
        encode(state, digest, 16);

        /* Restore current state and count. */
        memcpy(state, oldState, 16);
        memcpy(count, oldCount, 8);
    }
    return digest;
}

/**
 * @Initialization the md5 object, processing another message block,
 * and updating the context.
 *
 * @param {input} the input message.
 *
 * @param {len} the number btye of message.
 *
 */
void MD5::init(const byte* input, size_t len) {

    bit32 i, index, partLen;

    finished = false;

    /* Compute number of bytes mod 64 */
    index = (bit32)((count[0] >> 3) & 0x3f);

    /* update number of bits */
    if ((count[0] += ((bit32)len << 3)) < ((bit32)len << 3)) {
        ++count[1];
    }
    count[1] += ((bit32)len >> 29);

    partLen = 64 - index;

    /* transform as many times as possible. */
    if (len >= partLen) {

        memcpy(&buffer[index], input, partLen);
        transform(buffer);

        for (i = partLen; i + 63 < len; i += 64) {
            transform(&input[i]);
        }
        index = 0;

    } else {
        i = 0;
    }

    /* Buffer remaining input */
    memcpy(&buffer[index], &input[i], len - i);
}

void MD5::transform(const byte block[64]) {

    bit32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];

    decode(block, x, 64);

    /* Round 1 */
    FF (a, b, c, d, x[ 0], s11, 0xd76aa478);
    FF (d, a, b, c, x[ 1], s12, 0xe8c7b756);
    FF (c, d, a, b, x[ 2], s13, 0x242070db);
    FF (b, c, d, a, x[ 3], s14, 0xc1bdceee);
    FF (a, b, c, d, x[ 4], s11, 0xf57c0faf);
    FF (d, a, b, c, x[ 5], s12, 0x4787c62a);
    FF (c, d, a, b, x[ 6], s13, 0xa8304613);
    FF (b, c, d, a, x[ 7], s14, 0xfd469501);
    FF (a, b, c, d, x[ 8], s11, 0x698098d8);
    FF (d, a, b, c, x[ 9], s12, 0x8b44f7af);
    FF (c, d, a, b, x[10], s13, 0xffff5bb1);
    FF (b, c, d, a, x[11], s14, 0x895cd7be);
    FF (a, b, c, d, x[12], s11, 0x6b901122);
    FF (d, a, b, c, x[13], s12, 0xfd987193);
    FF (c, d, a, b, x[14], s13, 0xa679438e);
    FF (b, c, d, a, x[15], s14, 0x49b40821);

    /* Round 2 */
    GG (a, b, c, d, x[ 1], s21, 0xf61e2562);
    GG (d, a, b, c, x[ 6], s22, 0xc040b340);
    GG (c, d, a, b, x[11], s23, 0x265e5a51);
    GG (b, c, d, a, x[ 0], s24, 0xe9b6c7aa);
    GG (a, b, c, d, x[ 5], s21, 0xd62f105d);
    GG (d, a, b, c, x[10], s22,  0x2441453);
    GG (c, d, a, b, x[15], s23, 0xd8a1e681);
    GG (b, c, d, a, x[ 4], s24, 0xe7d3fbc8);
    GG (a, b, c, d, x[ 9], s21, 0x21e1cde6);
    GG (d, a, b, c, x[14], s22, 0xc33707d6);
    GG (c, d, a, b, x[ 3], s23, 0xf4d50d87);
    GG (b, c, d, a, x[ 8], s24, 0x455a14ed);
    GG (a, b, c, d, x[13], s21, 0xa9e3e905);
    GG (d, a, b, c, x[ 2], s22, 0xfcefa3f8);
    GG (c, d, a, b, x[ 7], s23, 0x676f02d9);
    GG (b, c, d, a, x[12], s24, 0x8d2a4c8a);

    /* Round 3 */
    HH (a, b, c, d, x[ 5], s31, 0xfffa3942);
    HH (d, a, b, c, x[ 8], s32, 0x8771f681);
    HH (c, d, a, b, x[11], s33, 0x6d9d6122);
    HH (b, c, d, a, x[14], s34, 0xfde5380c);
    HH (a, b, c, d, x[ 1], s31, 0xa4beea44);
    HH (d, a, b, c, x[ 4], s32, 0x4bdecfa9);
    HH (c, d, a, b, x[ 7], s33, 0xf6bb4b60);
    HH (b, c, d, a, x[10], s34, 0xbebfbc70);
    HH (a, b, c, d, x[13], s31, 0x289b7ec6);
    HH (d, a, b, c, x[ 0], s32, 0xeaa127fa);
    HH (c, d, a, b, x[ 3], s33, 0xd4ef3085);
    HH (b, c, d, a, x[ 6], s34,  0x4881d05);
    HH (a, b, c, d, x[ 9], s31, 0xd9d4d039);
    HH (d, a, b, c, x[12], s32, 0xe6db99e5);
    HH (c, d, a, b, x[15], s33, 0x1fa27cf8);
    HH (b, c, d, a, x[ 2], s34, 0xc4ac5665);

    /* Round 4 */
    II (a, b, c, d, x[ 0], s41, 0xf4292244);
    II (d, a, b, c, x[ 7], s42, 0x432aff97);
    II (c, d, a, b, x[14], s43, 0xab9423a7);
    II (b, c, d, a, x[ 5], s44, 0xfc93a039);
    II (a, b, c, d, x[12], s41, 0x655b59c3);
    II (d, a, b, c, x[ 3], s42, 0x8f0ccc92);
    II (c, d, a, b, x[10], s43, 0xffeff47d);
    II (b, c, d, a, x[ 1], s44, 0x85845dd1);
    II (a, b, c, d, x[ 8], s41, 0x6fa87e4f);
    II (d, a, b, c, x[15], s42, 0xfe2ce6e0);
    II (c, d, a, b, x[ 6], s43, 0xa3014314);
    II (b, c, d, a, x[13], s44, 0x4e0811a1);
    II (a, b, c, d, x[ 4], s41, 0xf7537e82);
    II (d, a, b, c, x[11], s42, 0xbd3af235);
    II (c, d, a, b, x[ 2], s43, 0x2ad7d2bb);
    II (b, c, d, a, x[ 9], s44, 0xeb86d391);

    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;
}

/**
* @Encodes input (unsigned long) into output (byte).
*
* @param {input} usigned long.
*
* @param {output} byte.
*
* @param {length} the length of input.
*
*/
void MD5::encode(const bit32* input, byte* output, size_t length) {

    for (size_t i = 0, j = 0; j < length; ++i, j += 4) {
        output[j]= (byte)(input[i] & 0xff);
        output[j + 1] = (byte)((input[i] >> 8) & 0xff);
        output[j + 2] = (byte)((input[i] >> 16) & 0xff);
        output[j + 3] = (byte)((input[i] >> 24) & 0xff);
    }
}

/**
 * @Decodes input (byte) into output (usigned long).
 *
 * @param {input} bytes.
 *
 * @param {output} unsigned long.
 *
 * @param {length} the length of input.
 *
 */
void MD5::decode(const byte* input, bit32* output, size_t length) {
    for (size_t i = 0, j = 0; j < length; ++i, j += 4) {
        output[i] = ((bit32)input[j]) | (((bit32)input[j + 1]) << 8) |
                    (((bit32)input[j + 2]) << 16) | (((bit32)input[j + 3]) << 24);
    }
}

/**
 * @Convert digest to string value.
 *
 * @return the hex string of digest.
 *
 */
string MD5::toStr() {
    const byte* digest_ = getDigest();
    string str;
    str.reserve(16 << 1);
    for (size_t i = 0; i < 16; ++i) {
        int t = digest_[i];
        int a = t / 16;
        int b = t % 16;
        str.append(1, HEX_NUMBERS[a]);
        str.append(1, HEX_NUMBERS[b]);
    }
    return str;
}

使用MD5算法

引入 MD5 算法后,就可以在 hello.cpp 里的 Md5() 方法内实现 MD5 算法了,使用流程如下:

  • 引入头文件

引入头文件的目的是调用其提供的 MD5 计算方法,和 JS 里的 import 功能类似。

代码语言:cpp
复制
    #include "./md5/md5.h"
  • 使用md5算法

修改 hello.cpp 里的 Md5() 方法内容如下所示:

代码语言:cpp
复制
    static napi_value Md5(napi_env env, napi_callback_info info) {
        // 1、从info中取出JS传递过来的参数放入args
        size_t argc = 1;
        napi_value args[1] = { nullptr };
        if (napi_ok != napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)) {
            napi_throw_error(env, "-1000", "napi_get_cb_info error");
            return nullptr;
        }

        // 2、获取参数的类型
        napi_valuetype stringType;
        if (napi_ok != napi_typeof(env, args[0], &stringType)) {
            napi_throw_error(env, "-1001", "napi_typeof error");
            return nullptr;
        }

        // 3、如果参数为null,这抛异常
        if (napi_null == stringType) {
            napi_throw_error(env, "-1002", "the param can't be null");
            return nullptr;
        }

        // 4、获取传递的string长度
        size_t length = 0;
        if (napi_ok != napi_get_value_string_utf8(env, args[0], nullptr, 0, &length)) {
            napi_throw_error(env, "-1003", "napi_get_value_string_utf8 error");
            return nullptr;
        }

        // 5、如果传递的是"",则抛异常
        if (length == 0) {
            napi_throw_error(env, "-1004", "the param length invalid");
            return nullptr;
        }

        // 6、读取传递的string参数放入buffer中
        char* buffer = new char[length + 1];
        if (napi_ok != napi_get_value_string_utf8(env, args[0], buffer, length + 1, &length)) {
            delete[] buffer;
            buffer = nullptr;
            napi_throw_error(env, "-1005", "napi_get_value_string_utf8 error");
            return nullptr;
        }

        // **********************************************************************
        // ********************************MD5加密********************************
        // 7、计算MD5加密操作
        std::string str = buffer;
        // MD5 加密计算
        str = MD5(str).toStr();
        // **********************************************************************
        // ********************************MD5加密********************************

        // 8、把C++数据转成napi_value并返回
        napi_value value = nullptr;
        const char* md5 = str.c_str();
        if (napi_ok != napi_create_string_utf8(env, md5, strlen(md5), &value)) {
            delete[] buffer;
            buffer = nullptr;
            napi_throw_error(env, "-1006", "napi_create_string_utf8 error");
            return nullptr;
        }

        // 9、资源清理
        delete[] buffer;
        buffer = nullptr;

        return value;
    }

主要看第 7 步:直接创建 MD5 后调用其 toStr() 方法即可生成加密后的字符串。

修改CMake文件

增加了 MD5 计算的源码,需要修改 CMakeLists.txt 文件,目的是把计算 MD5 的源文件打包进 so 中,修改后的代码如下所示:

代码语言:cpp
复制
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(oh_0400_napi)

set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

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

# 把 md5.cpp 源文件引入
add_library(entry SHARED hello.cpp ./md5/md5.cpp)

target_link_libraries(entry PUBLIC libace_napi.z.so)

测试MD5算法

根据 Md5() 方法的实现,限制条件是不允许数据 null 和 "",如果输入则抛异常。因此可测试以下三种场景:正常参数,null 参数和 "" 参数,样例代码如下所示:

代码语言:cpp
复制
import testNapi from 'libentry.so'

@Entry @Component struct Index {

  @State message: string = 'Hello,OpenHarmony'

  build() {
    Column({space: 10}) {

      Text(this.message)
        .fontSize(20)

      Button("正常参数")
        .onClick(() => {
          this.message = testNapi.md5("Hello, OpenHarmony")
        })

      Button("null参数")
        .onClick(() => {
          this.message = testNapi.md5(null);
        })

      Button("\"\"参数")
        .onClick(() => {
          this.message = testNapi.md5("");
        })
    }
    .padding(10)
    .width('100%')
    .height("100%")
  }
}

点解 正常参数 按钮,输出结果和在线网站上计算的结果一致,非常棒(#^.^#),样例运行结果如下所示:

小结

本节笔者通过引入三方库的方式实现了 MD5 的计算,当前只是一个简单的计算,如果是一个非常复杂的耗时计算,就会阻塞主线程,因此需要实现异步方法,笔者将要在下节讲解一下异步的实现方式。

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力;
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识;
  • 想要获取更多完整鸿蒙最新学习知识点,可关注B站:码牛课堂鸿蒙开发;

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引入MD5源码
  • 使用MD5算法
  • 修改CMake文件
  • 测试MD5算法
  • 小结
  • 写在最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档