国密起步1:GmSSL3安装和使用AES

2024-08-28 09:28

本文主要是介绍国密起步1:GmSSL3安装和使用AES,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


        此源码位于othertest目录,需要自行编译。(chomd 755 *.sh;rebuild.sh;run.sh) 

目录

一、介绍

二、国密、普密、商密

三、下载和安装

四、AES测试

4.1 不兼容之处

4.2 测试代码

4.3 运行结果


一、介绍

        国密库GmSSL的官网:关于GmSSL

        官网的简介:

GmSSL是一个开源的密码工具箱,支持SM2/SM3/SM4/SM9/ZUC等国密(国家商用密码)算法、SM2国密数字证书及基于SM2证书的SSL/TLS安全通信协议,支持国密硬件密码设备,提供符合国密规范的编程接口与命令行工具,可以用于构建PKI/CA、安全通信、数据加密等符合国密标准的安全应用。GmSSL项目是OpenSSL项目的分支,并与OpenSSL保持接口兼容。因此GmSSL可以替代应用中的OpenSSL组件,并使应用自动具备基于国密的安全能力。GmSSL项目采用对商业应用友好的类BSD开源许可证,开源且可以用于闭源的商业应用。

GmSSL项目由北京大学关志副研究员的密码学研究组开发维护,项目源码托管于GitHub。自2014年发布以来,GmSSL已经在多个项目和产品中获得部署与应用,并获得2015年度“一铭杯”中国Linux软件大赛二等奖(年度最高奖项)与开源中国密码类推荐项目。GmSSL项目的核心目标是通过开源的密码技术推动国内网络空间安全建设。

        我们不是很关心这些细节,对吧?

二、国密、普密、商密

        “国密”有两个意思:国家级秘密和国家密码局。国家级秘密是涉及到国家安全的秘密,普密是党政机关的不涉及国家安全的机密(跟我们一般想的不一样,我们的秘密够不上级别),商密是非国家党政机关的秘密。国家密码局是制定密码标准的国家机关,我们一般说的国密指的是国家密码局制定的商密标准,所以都是以“SM”命名的。

三、下载和安装

        直接找到下载,在github下载项目,然后按照说明编译安装,cmake的东西比较简单,一趟就过了,测试最后三个用例没通过(用sudo也不行),不管了,一时半会也用不上高级的。

      Start 46: chacha20
46/53 Test #46: chacha20 .........................   Passed    0.00 secStart 47: sm4_cbc_mac
47/53 Test #47: sm4_cbc_mac ......................   Passed    0.00 secStart 48: sm3_commands
48/53 Test #48: sm3_commands .....................   Passed    0.02 secStart 49: sm2_commands
49/53 Test #49: sm2_commands .....................   Passed    0.17 secStart 50: cert_commands
50/53 Test #50: cert_commands ....................   Passed    0.62 secStart 51: tlcp_commands
51/53 Test #51: tlcp_commands ....................***Exception: Child terminated  7.07 secStart 52: tls12_commands
52/53 Test #52: tls12_commands ...................***Exception: Child terminated  7.11 secStart 53: tls13_commands
53/53 Test #53: tls13_commands ...................***Exception: Child terminated  7.10 sec94% tests passed, 3 tests failed out of 53Total Test time (real) =  25.16 secThe following tests FAILED:51 - tlcp_commands (Child terminated)52 - tls12_commands (Child terminated)53 - tls13_commands (Child terminated)
Errors while running CTest
Makefile:82: recipe for target 'test' failed
make: *** [test] Error 8

         install之后得到动态库libgmssl.so和一个目录的头文件(目录名gmssl)。有so和头文件我们就知道该怎么做了。

        我装的是最新版,如何查看版本:

user@vm-ubuntu:~/gmssl$ gmssl version
GmSSL 3.1.2 Dev

四、AES测试

        AES不是SM系列的算法,但是兼容嘛,所以我们先拿这个来验证。

        之前写过OpenSSL的AES测试代码,直接拿过来用,稍微修改一下应该就可以了。

        发现不少不同之处啊。

4.1 不兼容之处

  • 头文件目录不同。
  • 库文件名不同。
  • Aes_encrypt函数名和参数顺序不同,此库为aes_encrypt,且参数key为第一个
  • Aes_decrypt类似
  • Rand_bytes函数名不同,此库为rand_bytes
  • Aes_set_encrypt_key函数名和参数不同,此库为aes_set_encrypt_key,且参数为字节长度而不是位长度(不然会coredump啊)
  • AES_set_decrypt_key类似

4.2 测试代码

//myGmSSL.h 文件编码:UTF-8无签名#pragma once#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <stdlib.h>
#include <gmssl/aes.h>
#include <gmssl/rand.h>
#include <vector>
#include "Buffer.h"
#include "mimetype.h"
using namespace std;namespace ns_my_std
{class CMyGmSSL{private:static unsigned char getVer() { return 1; }static void show_buf(char const* title, unsigned char const* buf, int len){cout << title << " ";for (int i = 0; i < len; ++i){cout << hex << setw(2) << setfill('0') << (unsigned int)buf[i] << " ";}cout << endl;}//需要一个从用户密码生成密钥的函数public:class IV{private:unsigned char iv[AES_BLOCK_SIZE * 5];public:IV(){memset(iv, 0, AES_BLOCK_SIZE * 5);}//执行异或static void XOR(unsigned char const* iv, unsigned char* data){//show_buf("IV  ", iv, AES_BLOCK_SIZE);//show_buf("DATA", data, AES_BLOCK_SIZE);for (int i = 0; i < AES_BLOCK_SIZE; ++i){data[i] ^= iv[i];}//show_buf("DATA", data, AES_BLOCK_SIZE);}int size()const{return AES_BLOCK_SIZE;}//用随机数设置void Create(){time_t t = time(NULL);srand(t);for (int i = 0; i < AES_BLOCK_SIZE; i += sizeof(int)){int a = rand();memcpy(iv + i, &a, sizeof(int));}}void Set(unsigned char const* a){memcpy(iv, a, AES_BLOCK_SIZE);}//注意,会修改内容unsigned char* Get(){//show_buf("", iv, AES_BLOCK_SIZE * 2);return iv;}};//由于网上的例子也一样无法解密,所以自行实现CBCstatic void my_AES_cbc_encrypt(const unsigned char* in, unsigned char* out, size_t length, const AES_KEY* key, unsigned char* ivec, bool isEnc){//AES_cbc_encrypt(in, out, length, key, ivec, enc);for (int i = 0; i < (int)length; i += AES_BLOCK_SIZE){if (isEnc){unsigned char tmpin[AES_BLOCK_SIZE];memcpy(tmpin, in + i, AES_BLOCK_SIZE);IV::XOR(ivec, tmpin); thelog << endi;aes_encrypt(key, tmpin, out + i); thelog << endi;memcpy(ivec, out + i, AES_BLOCK_SIZE);}else{unsigned char tmpiv[AES_BLOCK_SIZE];memcpy(tmpiv, in + i, AES_BLOCK_SIZE);aes_decrypt(key, in + i, out + i);IV::XOR(ivec, out + i);memcpy(ivec, tmpiv, AES_BLOCK_SIZE);}}}static int my_aes_encrypt(unsigned char const* userpasswd, int userpasswd_len, vector<unsigned char> const& in_plain, vector<unsigned char>& out_ciphertext, IV& iv){out_ciphertext.clear();unsigned char userkey[32];//必须是16/24/32memset((void*)userkey, '\0', 32);memcpy(userkey, userpasswd, (userpasswd_len > 32 ? 32 : userpasswd_len));/*设置加密key及密钥长度*/AES_KEY key;if (aes_set_encrypt_key(&key, userkey, 32) < 0){return __LINE__;}int len = 0;/*循环加密,每次只能加密AES_BLOCK_SIZE长度的数据*/out_ciphertext.reserve(in_plain.size() + AES_BLOCK_SIZE);while (len < (int)in_plain.size()){if (0 == len){//第一个块是明文长度out_ciphertext.resize(out_ciphertext.size() + AES_BLOCK_SIZE);unsigned char tmp[AES_BLOCK_SIZE];memset((void*)tmp, '\0', AES_BLOCK_SIZE);uint64_t tmp_len = in_plain.size();memcpy(tmp, &tmp_len, sizeof(uint64_t));//show_buf("明文长度加密前 ", tmp, AES_BLOCK_SIZE);my_AES_cbc_encrypt(tmp, &out_ciphertext[out_ciphertext.size() - AES_BLOCK_SIZE], AES_BLOCK_SIZE, &key, iv.Get(), true);//show_buf("明文长度加密后", &out_ciphertext[out_ciphertext.size() - AES_BLOCK_SIZE], AES_BLOCK_SIZE);}out_ciphertext.resize(out_ciphertext.size() + AES_BLOCK_SIZE);if (in_plain.size() - len < AES_BLOCK_SIZE){unsigned char tmp[AES_BLOCK_SIZE];memset((void*)tmp, '\0', AES_BLOCK_SIZE);memcpy(tmp, &in_plain[len], in_plain.size() - len);my_AES_cbc_encrypt(tmp, &out_ciphertext[out_ciphertext.size() - AES_BLOCK_SIZE], AES_BLOCK_SIZE, &key, iv.Get(), true);}else{my_AES_cbc_encrypt(&in_plain[len], &out_ciphertext[out_ciphertext.size() - AES_BLOCK_SIZE], AES_BLOCK_SIZE, &key, iv.Get(), true);}len += AES_BLOCK_SIZE;}return 0;}static int my_aes_decrypt(unsigned char const* userpasswd, int userpasswd_len, vector<unsigned char> const& in_ciphertext, vector<unsigned char>& out_plain, IV& iv){out_plain.clear();unsigned char userkey[32];//必须是16/24/32memset((void*)userkey, '\0', 32);memcpy(userkey, userpasswd, (userpasswd_len > 32 ? 32 : userpasswd_len));/*设置解密key及密钥长度*/AES_KEY key;if (aes_set_decrypt_key(&key, userkey, 32) < 0){return __LINE__;}int len = 0;/*循环解密*/out_plain.reserve(in_ciphertext.size());uint64_t out_len = 0;//原始长度,放在第一个加密块while (len < (int)in_ciphertext.size()){if (0 == len){//第一个块是明文长度unsigned char tmp[AES_BLOCK_SIZE];//show_buf("明文长度解密前", &in_ciphertext[len], AES_BLOCK_SIZE);my_AES_cbc_encrypt(&in_ciphertext[len], tmp, AES_BLOCK_SIZE, &key, iv.Get(), false);//show_buf("明文长度解密后", tmp, AES_BLOCK_SIZE);memcpy(&out_len, tmp, sizeof(uint64_t));//thelog << "明文长度应该是 " << out_len << endi;len += AES_BLOCK_SIZE;}out_plain.resize(out_plain.size() + AES_BLOCK_SIZE);my_AES_cbc_encrypt(&in_ciphertext[len], &out_plain[out_plain.size() - AES_BLOCK_SIZE], AES_BLOCK_SIZE, &key, iv.Get(), false);len += AES_BLOCK_SIZE;}//恢复原始长度if ((uint64_t)out_plain.size() > out_len)out_plain.resize(out_len);return 0;}//保护数据,用密码加密并做格式转换static bool protect_encode(string const& _passwd, string const& _input, string& _output){CUnsignedBuffer passwd;CUnsignedBuffer input;CUnsignedBuffer output;passwd.SetData(_passwd.c_str(), _passwd.size());input.SetData(_input.c_str(), _input.size());if (protect_encode(passwd, input, output)){_output = (char *)output.data();return true;}return false;}static bool protect_encode(CUnsignedBuffer const& passwd, CUnsignedBuffer const& input, CUnsignedBuffer& output){output.setSize(0);IV iv;iv.Create();CUnsignedBuffer tmp;unsigned char ver = getVer();tmp.AddData(&ver, 1);//第一个字节是版本tmp.AddData(iv.Get(), iv.size());//然后是IV,必须在加密之前保存,加密之后会改变//加密vector<unsigned char> in_plain;in_plain.resize(input.size());memcpy(&in_plain[0], input.data(), input.size());vector<unsigned char> out_ciphertext;my_aes_encrypt(passwd.data(), passwd.size(), in_plain, out_ciphertext, iv);//thelog << out_ciphertext.size() << endi;//添加加密后数据tmp.AddData(&out_ciphertext[0], out_ciphertext.size());//thelog << tmp.size() << endi;output.reserve(tmp.size() * 4 / 3 + 4 + 1);//三字节转为4字节,编码函数在最后还会加上一个字符串结束符//thelog << output.capacity() << " " << output.size() << endi;int n = CBase64::Base64Enc(output.lockBuffer(), tmp.data(), tmp.size());output.releaseBuffer();if (n > (int)output.capacity())thelog << "长度不足" << ende;output.setSize(n);//thelog << output.size() << " [" << output.data() << "]" << endi;return true;}//保护数据,用密码加密并做格式转换static bool protect_decode(string const& _passwd, string const& _input, string& _output){CUnsignedBuffer passwd;CUnsignedBuffer input;CUnsignedBuffer output;passwd.SetData(_passwd.c_str(), _passwd.size());input.SetData(_input.c_str(), _input.size());if (protect_decode(passwd, input, output)){_output = (char*)output.data();return true;}return false;}static bool protect_decode(CUnsignedBuffer const& passwd, CUnsignedBuffer const& input, CUnsignedBuffer& output){output.setSize(0);CUnsignedBuffer tmp;//这里导致了奇怪的内存错误,实际并不需要这么长tmp.reserve(input.size() + 100);//实际需要的是4转3,解码函数最后会加上一个字符串结束符//thelog << input.size() << " " << tmp.capacity() << " " << tmp.size() << endi;int n = CBase64::Base64Dec((char*)tmp.lockBuffer(), (char*)input.data(), input.size());tmp.releaseBuffer();if (n<0 || n >(int)tmp.capacity())thelog << "长度不足" << ende;tmp.setSize(n);unsigned char ver = getVer();if (tmp.data()[0] != ver){thelog << "加密版本错误" << ende;return false;}else{//thelog << "加密版本 " << (int)tmp.data()[0]<<" " << (int)ver << ende;}IV iv;iv.Set(tmp.data() + 1);vector<unsigned char> in_plain;in_plain.resize(tmp.size() - 1 - iv.size());memcpy(&in_plain[0], tmp.data() + 1 + iv.size(), tmp.size() - 1 - iv.size());//thelog << tmp.size() << " " << in_plain.size() << endi;vector<unsigned char> out_ciphertext;my_aes_decrypt(passwd.data(), passwd.size(), in_plain, out_ciphertext, iv);output.AddData(&out_ciphertext[0], out_ciphertext.size());return true;}// a simple hex-print routine. could be modified to print 16 bytes-per-linestatic void hex_print(const void* pv, size_t len){const unsigned char* p = (const unsigned char*)pv;if (NULL == pv){printf("NULL");}else{size_t i = 0;for (; i < len; ++i){printf("%02X ", *p++);}}printf("\n");}// main entrypointstatic int a(){int const keylength = 128;/* generate a key with a given length */unsigned char aes_key[keylength / 8];memset(aes_key, 0, keylength / 8);if (!rand_bytes(aes_key, keylength / 8)){return __LINE__;}char const* input = "12345678901234567890";size_t const inputslength = 32;/* generate input with a given length */unsigned char aes_input[inputslength];memset(aes_input, 0, inputslength);memcpy(aes_input, input, strlen(input));/* init vector */unsigned char iv_enc[AES_BLOCK_SIZE], iv_dec[AES_BLOCK_SIZE];rand_bytes(iv_enc, AES_BLOCK_SIZE);memcpy(iv_dec, iv_enc, AES_BLOCK_SIZE);// buffers for encryption and decryptionunsigned char enc_out[inputslength];unsigned char dec_out[inputslength];memset(enc_out, 0, sizeof(enc_out));memset(dec_out, 0, sizeof(dec_out));// so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256AES_KEY enc_key, dec_key;aes_set_encrypt_key(&enc_key, aes_key, keylength/8);my_AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv_enc, true);aes_set_decrypt_key(&dec_key, aes_key, keylength/8);//本函数是网上代码,但是在linux下一样失败,在win下则导致异常(解密正确但退出时异常),原因是此段代码错误使用了长度参数//此函数并不处理padding,所以输出长度和输入长度是相同的,只不过加上了cbc操作而已(正如我自己写的那个替代品)//此处原来的输入比需要的长,导致堆栈异常,按理多解密一个无意义的块有什么危害呢?my_AES_cbc_encrypt(enc_out, dec_out, inputslength, &dec_key, iv_dec, false);printf("original(%d):\t", static_cast<int>(sizeof(aes_input)));hex_print(aes_input, sizeof(aes_input));printf("encrypt(%d):\t", static_cast<int>(sizeof(enc_out)));hex_print(enc_out, sizeof(enc_out));printf("decrypt(%d):\t", static_cast<int>(sizeof(dec_out)));hex_print(dec_out, sizeof(dec_out));return 0;}static bool aes_test(){if (true){constexpr int keybits = 128;thelog << "keybits " << keybits <<" bytes "<< keybits / 8 << endi;unsigned char userkey[keybits/8];//必须是16/24/32memset((void*)userkey, '\0', keybits / 8);memcpy(userkey, "12345", 5);AES_KEY key;if (aes_set_encrypt_key(&key, userkey, keybits/8) < 0){return __LINE__;}unsigned char iv[AES_BLOCK_SIZE];unsigned char data[AES_BLOCK_SIZE];memset(data, 1, AES_BLOCK_SIZE);unsigned char data2[AES_BLOCK_SIZE];memset(data2, 0, AES_BLOCK_SIZE);unsigned char data3[AES_BLOCK_SIZE * 3];memset(data3, 0, AES_BLOCK_SIZE * 3);memset(iv, 0, AES_BLOCK_SIZE);show_buf("简单输入 ", data, AES_BLOCK_SIZE);show_buf("iv ", iv, AES_BLOCK_SIZE);my_AES_cbc_encrypt(data, data2, AES_BLOCK_SIZE, &key, iv, true);show_buf("加密后   ", data2, AES_BLOCK_SIZE);show_buf("iv ", iv, AES_BLOCK_SIZE);if (aes_set_decrypt_key(&key,userkey, keybits/8) < 0){return __LINE__;}memset(iv, 0, AES_BLOCK_SIZE);show_buf("解密前   ", data2, AES_BLOCK_SIZE);show_buf("iv ", iv, AES_BLOCK_SIZE);my_AES_cbc_encrypt(data2, data3, AES_BLOCK_SIZE, &key, iv, false);show_buf("简单输出 ", data3, AES_BLOCK_SIZE * 3);show_buf("iv ", iv, AES_BLOCK_SIZE);a(); thelog << "网上代码测试完成" << endi;}if (true){string passwd = "13579";vector<unsigned char> plaintext;for (int i = 0; i < 65; ++i){plaintext.push_back(i);}vector<unsigned char> out;IV iv;iv.Create();IV iv2;iv2.Set(iv.Get());//show_buf("初始IV", iv.Get(), iv.size());my_aes_encrypt((unsigned char*)passwd.c_str(), passwd.size(), plaintext, out, iv);vector<unsigned char> plaintext2;//show_buf("初始IV", iv2.Get(), iv2.size());my_aes_decrypt((unsigned char*)passwd.c_str(), passwd.size(), out, plaintext2, iv2);thelog << plaintext.size() << " " << out.size() << " " << plaintext2.size() << ENDI;printf("plantext2: \n");for (int i = 0; i < (int)plaintext2.size(); i++){printf("%.2x ", plaintext2[i]);if ((i + 1) % 32 == 0){printf("\n");}}printf("\n");}if (true){try{char const* plaintext = "1234567890";CUnsignedBuffer pass;CUnsignedBuffer in;CUnsignedBuffer out;pass.SetData("123");in.SetData(plaintext);thelog << in.data() << endi;protect_encode(pass, in, out);thelog << out.size() << " [" << out.data() << "]" << endi;CUnsignedBuffer out2;if (!protect_decode(pass, out, out2))thelog << "解码失败" << ende;thelog << out2.data() << endi;if (0 == strcmp(plaintext, (char*)out2.data())){thelog << "匹配成功" << endi;}else{thelog << "匹配失败" << ende;}//out2.lockBuffer();//out2.setSize(10240);}catch (...){thelog << "异常发生" << ende;}}return true;}};
}

4.3 运行结果

[08-26 12:31:18][应用][信息][CommandSet.h            : 236(doCommandSet)][  0.00]
命令表
命令 组           名称      命令 说明
---- ------------ --------- ---- --------
a    未命名命令组 TestGmSSL a    国密测试
---- ------------ --------- ---- --------请选择命令:(--group选择命令组 b=break)(q=exit default=a):[08-26 12:31:19][应用][信息] 用户输入的是:a
[08-26 12:31:19][应用][信息][myGmSSL.h               : 373(aes_test)][  0.00]keybits 128 bytes 16
简单输入  01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
iv  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[08-26 12:31:19][应用][信息][myGmSSL.h               :  95(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  96(my_AES_cbc_encrypt)][  0.00]
加密后    ee a2 aa 8d 92 fd 10 be 22 03 fe 08 52 6a 57 d1
iv  ee a2 aa 8d 92 fd 10 be 22 03 fe 08 52 6a 57 d1
解密前    ee a2 aa 8d 92 fd 10 be 22 03 fe 08 52 6a 57 d1
iv  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
简单输出  01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
iv  ee a2 aa 8d 92 fd 10 be 22 03 fe 08 52 6a 57 d1
[08-26 12:31:19][应用][信息][myGmSSL.h               :  95(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  96(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  95(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  96(my_AES_cbc_encrypt)][  0.00]
original(32):   31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 00 00 00 00 00 00 00 00 00 00 00 00
encrypt(32):    7D 36 62 28 9A C8 3B 22 1B CC B8 B7 79 13 CA C4 C9 26 43 A6 D3 23 17 02 7A 93 30 A3 34 63 1A 84
decrypt(32):    31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 00 00 00 00 00 00 00 00 00 00 00 00
[08-26 12:31:19][应用][信息][myGmSSL.h               : 408(aes_test)][  0.00]网上代码测试完成
[08-26 12:31:19][应用][信息][myGmSSL.h               :  95(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  96(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  95(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  96(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  95(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  96(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  95(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  96(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  95(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  96(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  95(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  96(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               : 429(aes_test)][  0.00]65 96 65
plantext2:
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
40
[08-26 12:31:19][应用][信息][myGmSSL.h               : 452(aes_test)][  0.00]1234567890
[08-26 12:31:19][应用][信息][myGmSSL.h               :  95(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  96(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  95(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               :  96(my_AES_cbc_encrypt)][  0.00]
[08-26 12:31:19][应用][信息][myGmSSL.h               : 454(aes_test)][  0.00]68 [AVPRQGy8Aj5Dlmc7LhtTAgNr4B6769ZxXBhK9K09zWkvHawenVr5/pDgHINXiD8lHA==]
[08-26 12:31:19][应用][信息][myGmSSL.h               : 457(aes_test)][  0.00]1234567890
[08-26 12:31:19][应用][信息][myGmSSL.h               : 460(aes_test)][  0.00]匹配成功
[08-26 12:31:19][应用][信息][CommandSet.h            : 129(doCommand)][  0.00]
命令 TestGmSSL 执行完毕 返回码 0

这篇关于国密起步1:GmSSL3安装和使用AES的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1114376

相关文章

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

MyBatis ParameterHandler的具体使用

《MyBatisParameterHandler的具体使用》本文主要介绍了MyBatisParameterHandler的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、概述二、源码1 关键属性2.setParameters3.TypeHandler1.TypeHa

Spring 中的切面与事务结合使用完整示例

《Spring中的切面与事务结合使用完整示例》本文给大家介绍Spring中的切面与事务结合使用完整示例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录 一、前置知识:Spring AOP 与 事务的关系 事务本质上就是一个“切面”二、核心组件三、完