侧边栏壁纸
博主头像
Into The Abyss 博主等级

My Life is a Death Race

  • 累计撰写 34 篇文章
  • 累计创建 7 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

基于GMP大数库的SM2加密解密

Administrator
2024-01-02 / 0 评论 / 0 点赞 / 375 阅读 / 0 字

因为项目需要使用sm2加密算法,在网上找了很久没有找到一个很好的cpp支持项目,结果发现了这个项目,但是我找不到原链接了,所以只能自己发一下记录配置使用的过程。这个项目只支持c语言,cpp可能需要修改其中的加密算法

编译GMP生成静态库

先前往GNU MP的官网下载源码,官网地址为:https://gmplib.org/,下载源码安装包并解压,我使用的版本是gmp-6.1.1

cd gmp-6.1.1
# --prefix=后面的值为你要移植的位置,其他参数的含义见https://gmplib.org/manual/Build-Options
./configure --prefix=../../test/ --disable-shared --enable-fat --enable-cxx --with-pic CXXFLAGS="-g -O2"
# 这个版本的--prefix=好像只能加绝对路径,按照自己的环境来
make -j12
make check
# 若执行完make check没有报错,则
make install
# 如果想要重新配置编译,可以执行make distclean后重新配置编译
# 进入到安装的目录下,我的是test,删掉无用的文件
cd ../../test
rm -rf share

编译opencrypto

找不到这个项目的原始地址,其中其中主要有5个c文件和4个头文件,以及一个makefile,我会上传代码,并附上链接地址。不过这个makefile只能生成动态库,而我需要的是静态库,我将它换成了我自己写的。

# 定义静态库文件名
lib_name = libopc.a

# 源文件列表
sources = opcbn.c opcec.c opcrand.c opcsm2.c opcsm3.c

# 从源文件生成目标文件的规则
objects = $(sources:.c=.o)

# 设置编译器和选项
CC = gcc
CFLAGS = -O2 -fpic -lgmp
CFLAGS += -I../../test/include/ -I.

LDFLAGS = -L../../test/lib/

# 默认规则:将所有的源文件编译成目标文件
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

# 生成静态库的规则
$(lib_name): $(objects)
    ar rcs $@ $(objects)

# 清理规则
clean:
    rm -f $(lib_name) $(objects)

使用前记得将CFLAGS和LDFLAGS的值换为你自己的环境,就是上一步GMP的安装路径

编辑号makefile后,进行编译,生成静态库

make
# 将生成的静态库libopc.a,移动到gmp的安装目录下的lib文件夹下,记得修改移动目录
mv libopc.a ../../test/lib
# 将所有头文件移动到gmp的安装目录下的include文件夹下,记得修改移动目录
mv *.h ../../test/include

编写test.c测试sm2加密解密

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include "opc.h"
#include "opcsm2.h"


int main(int argc, char *argv[])
{
    char cipherbuffer[512] = {0};
    unsigned char plain[512];
    char decrypt[256] = {0};
    int decryptlen;
    unsigned int plainlen = 32;
    unsigned int tmplen;
    int ret = 0;

    opcec_t pubk;
    opcbn_t prik;
    opcbn_t rand;
    opcec_group_t sm2group;
    opcsm2_cipher *cipher = (opcsm2_cipher *)cipherbuffer;
    opcsm2_signature sign;


    /* you must be call this function first, init random state */
    opcrand_init();

    opcsm2_create_group(sm2group, OPC_SM2_256_NID);
    opcec_init(pubk);
    opcbn_init(prik);
    opcbn_init(rand);

    opcsm2_generate_key(sm2group, pubk, prik);

    opcrand_generate_b(rand, plainlen);
    opcbn_get_bin(plain, &tmplen, rand, 32);

    opc_printf("---------------opc simple test--------------------\n", rand);
    opc_printf("public key:X= %Zx, Y=%Zx\n", pubk->x, pubk->y);
    opc_printf("private key = %Zx\n", prik);
    opc_printf("plain       = %Zx\n", rand);
    opc_printf("               encrypt test\n", rand);

    if ((ret = opcsm2_encrypt(sm2group, pubk, plain, plainlen, cipher)) != 0)
    {
        opc_printf("sm2 encrypt error ! ret = %d\n", ret);
        return ret;
    }
    printf("cipher->XCoordinate = %s\n", cipher->XCoordinate);
    printf("cipher->YCoordinate = %s\n", cipher->YCoordinate);
    printf("cipher->HASH        = %s\n", cipher->HASH);
    printf("cipher->CipherLen   = %d\n", cipher->CipherLen);
    printf("cipher->Cipher      = %s\n", cipher->Cipher);
    opcbn_set_bin(rand, cipher->XCoordinate, 32);
    opc_printf("cipher c1.x = %Zx\n", rand);
    opcbn_set_bin(rand, cipher->YCoordinate, 32);
    opc_printf("cipher c1.y = %Zx\n", rand);
    opcbn_set_bin(rand, cipher->HASH, 32);
    opc_printf("cipher c3   = %Zx\n", rand);
    opcbn_set_bin(rand, cipher->Cipher, cipher->CipherLen);
    opc_printf("cipher c2   = %Zx\n", rand);


    if ((ret = opcsm2_decrypt(sm2group, cipher, prik, decrypt, &decryptlen)) < 0)
    {
        opc_printf("sm2 decrypt error ! ret = %d\n", ret);
        return ret;
    }
    opcbn_set_bin(rand, decrypt, decryptlen);
    opc_printf("decrypt     = %Zx\n", rand);


    if (decryptlen != plainlen || memcmp(decrypt, plain, plainlen))
    {
        opc_printf("sm2 decrypt data not equal!\n");
        return ret;
    }


    opc_printf("               sign test\n", rand);
    if ((ret = opcsm2_sign(sm2group, prik, plain, plainlen, &sign)) != 0)
    {
        opc_printf("sm2 sign error ! ret = %d!\n", ret);
        return ret;
    }
    opcbn_set_bin(rand, sign.r, 32);
    opc_printf("sign.r      = %Zx\n", rand);
    opcbn_set_bin(rand, sign.s, 32);
    opc_printf("sign.s      = %Zx\n", rand);

    if ((ret = opcsm2_verify(sm2group, pubk, &sign, plain, plainlen)) != 0)
    {
        opc_printf("sm2 verify error ! ret = %d!\n", ret);
        return ret;
    }
    opc_printf("verify success\n");

    opc_printf("--------------------------------------------------\n", rand);
    opc_printf("sm2 encrypt decrypt sign verify test success!\n");
    opcec_clear_group(sm2group);
    return 0;
}        /* -------------- end function -------------- */

编写测试的makefile

CC = gcc
CFLAGS = -O2

CFLAGS += -I./include/
LDFLAGS += -L./lib/

all:
    ${CC} test.c -o test $(CFLAGS) $(LDFLAGS) -lopc -lgmp 

clean:
    rm test

完成之后

# 编译
make
# 运行
./test
0
c++

评论区