国密起步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

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Redis 基本数据类型和使用详解

《Redis基本数据类型和使用详解》String是Redis最基本的数据类型,一个键对应一个值,它的功能十分强大,可以存储字符串、整数、浮点数等多种数据格式,本文给大家介绍Redis基本数据类型和... 目录一、Redis 入门介绍二、Redis 的五大基本数据类型2.1 String 类型2.2 Hash

Redis中Hash从使用过程到原理说明

《Redis中Hash从使用过程到原理说明》RedisHash结构用于存储字段-值对,适合对象数据,支持HSET、HGET等命令,采用ziplist或hashtable编码,通过渐进式rehash优化... 目录一、开篇:Hash就像超市的货架二、Hash的基本使用1. 常用命令示例2. Java操作示例三

Linux创建服务使用systemctl管理详解

《Linux创建服务使用systemctl管理详解》文章指导在Linux中创建systemd服务,设置文件权限为所有者读写、其他只读,重新加载配置,启动服务并检查状态,确保服务正常运行,关键步骤包括权... 目录创建服务 /usr/lib/systemd/system/设置服务文件权限:所有者读写js,其他