2022_1_28_周汇报
一、进度
(一)通信设计
1.包格式
2.包格式解释
-
uid
通信标识,32位 -
sender sequence
数据包发送序号,32位 -
responder sequence
数据包应答序号,32位 -
stage
步骤标识序号,4位,加密秘钥协商4步、通信、结束2步 -
accept flag
对面发送的包应答是有效的,1位,(累计确认,或者单个确认)
-
retranslate flag
是否重传,1位
-
reset flag
重置标志位,1位,表示有一方掉线或中断,重新开启后发现对方没按流程来时,通知对方清除数据从头开始
-
shared flag
是否分段标识,1位 -
next flag
当前分段是否继续标识,1位 -
空着一位作保留或者后面添加
-
packet count
累计包数,6位,单位为:一个包数据长度,现为1440字节 -
checked num
校验和,16位 -
window size
窗口大小,8位 -
timestamp
时间戳,24位 -
reserved
拓展+保留位,12字节 -
共32字节
3.通信流程
所有部分除第一个包和通信阶段,从第二个包开始,要验证响应信息是否有效,有效设置accept-flag,无效accept-flag设置为0且reset-flag设置为1,重新开始
通信阶段accept-flag恒为1,reset-flag恒为0
1.协商部分
按照协商步骤计算后发送,设置stage为0x1、0x2、0x3、0x4
2.通信部分
所有通信包设置stage为0x5
、
加密通信部分($A$发起通信) |
|||
---|---|---|---|
步骤1 |
$A$将信息用加密秘钥加密 |
||
$A$计算$E_k^{sm3}(message)$,将$E_k^{sm3}(message)$打包 | B接受包 | ||
步骤2 |
$B$解密获取信息 |
||
$A$(无) | $B$解密获取信息 |
3.结束
一方提出结束请求,另一方发送结束请求确认(必须要签名数据,签名包含头部),提出请求方还需要确认签名
设置stage为0x6、0x7、0x8
4.意外处理
- 验证证书失败
中止协议,并发送验证证书失败信息+\(sm3 Hash\),设置stage为0xA,设置reset-flag为1 - 验证签名失败
中止协议,并发送验证签名失败信息+\(sm3 Hash\),设置stage为0xB,设置reset-flag为1 - 超时
重传,stage不变,设置retranslate-flag为1 - 收到重发的包
舍弃 - 加解密失败
发送加解密失败信息+签名,设置stage为0xC,设置reset-flag为1(reset-flag为1,结合stage进行处理) - 机器断电或重启或断网
- 内存占用过多,进程崩溃
- 进程被结束掉
- 建立连接时,服务器应用被阻塞
- 端口不存在或未开放
(二)协议demo进展
1.思路
使用接口先生成SM2公私钥,再生成证书,最后模拟协商4步
2.已解决的问题
-
SM2公私钥生成
参考:
自己签名课程做过的sm2
sm234编译
Compute SM2 signature and verify it by invoking EVP interface in OpenSSL 1.1.1
使用openssl的EVP接口使用sm2算法加解密等操作
openssl 1.1.1b 如何制作SM2公钥(在Ubuntu 19.04下测试通过) -
DER和PEM格式区别与解析,ASN1解析
参考:
iOS X509证书的解析
https://blog.csdn.net/kesay/article/details/46874699
通过OpenSSL解析X509证书基本项
ASN.1简介及OpenSSL中ASN.1接口使用举例
通过OpenSSL解析X509证书基本项
OpenSSL之X509系列之1---引言和X509概述
X.509证书的解析、验证及使用
x.509数字证书编码详解
左边为test1()打印证书,右边为ASN1格式解析,ieout.cer是从IE浏览器导出的证书
- 使用OpenSSL命令行生成证书请求和证书并与自己生成的进行比较
参考:
基于国密算法的小型CA系统设计与实现.pdf
国密SM2的证书制作及验证
左边为test1()打印ca.cer证书(参照:国密SM2的证书制作及验证,使用命令行方式生成的根证书),
右边为使用接口自己生成根证书
- API函数使用参考
openssl官网说明
3.使用OpenSSL接口编程如下函数:
-
X509* ReadDer(char *filePath); /*DER编码的单个文件为*.cer*/ /* 函数功能:读取DER格式的X509证书 */
参考:DER证书读取保存和转换
-
int SavetoDer(X509 *Cert, char *filePath); /* 函数功能:将X509结构体保存为DER格式文件 */
-
int SavetoDer_X509Req(X509_REQ *req, char* filePath); /* 函数功能:将X509_REQ结构体保存为DER格式文件 */
-
int SavetoPem_ECPrikey(EC_KEY *eckey, char* filePath); /* 函数功能:提取EC_KEY结构体中私钥并保存为PEM格式文件 */
-
int SM2_KeyGen(EVP_PKEY **evpkeyout, EC_KEY **eckeyout); /* 函数功能:生成SM2公私钥并保存到EC_KEY和EVP_PKEY结构体中 */
-
int SM2_KeyGen_ex(EVP_PKEY * out); /* 函数描述:SM2_KeyGen()的原始版本,未分割的函数 */
-
void get_rand(); /* 函数功能:测试BN_rand()函数,指定位数随机数 */
-
int Cert_Request_Gen(EVP_PKEY * evpPkey); /* 函数描述:Cert_Request_Gen_ex()的原始版本 */
-
X509_REQ* Cert_Request_Gen_ex(EVP_PKEY * evpPkey); /* 函数功能:根据绑定EC_KEY的EVP_PKEY生成X509请求 */
-
int Cert_Gen(X509_REQ *req, X509* ca, X509** cert, char* ca_prikey_file, long sequence); /* 函数功能:根据X509请求生成X509证书 参数: req: X509请求 ca : 签名的根证书 cert: 生成的X509证书 ca_prikey_file: 根证书私钥的PEM格式文件路径 sequence :设置证书的序列号 返回值: 1, 证书生成成功 0, 证书生成失败 */
-
void print_x509(X509* x); /* 函数功能:打印X509结构体 */
-
void print_pem_key(EC_KEY *ecKey); /* 函数功能:打印PEM格式的EC_KEY */
-
void print_key_hex(EC_KEY *ecKey); /* 函数功能:根据EC_KEY打印公私钥16进制 */
参考:公私钥转换成十六进制形式
-
void test2_d(); /* test*() 说明:加上_d为未完成的函数*/ - void test1(); /* 函数功能:测试ReadDer()和print_x509();输入DER格式文件路径,打印证书 */
-
void test2(); /* 函数功能:测试SM2_KeyGen()、print_pem_key()和print_key_hex() */
-
void test3(); /* 函数功能:测试Cert_Request_Gen() */
-
void test4(); /* 函数功能:测试Cert_Gen()、Cert_Request_Gen_ex()、SavetoPem_ECPrikey()和SavetoDer();生成根证书和一个用户证书 */
(后面找到的,同样是编程实现,做个对照)gmssl编程之签发X509证书
二、遇到的问题及解决
1.指针问题:
- EVP_PKEY绑定EC_KEY后,两者共享内存,释放时只需要释放一个
- 使用i2d_X509(Cert, &pTmp1)时,pTmp1虽然是malloc()申请的内存,但是调用i2d_X509()后,pTmp1指向Cert的部分,就不符合动态分配的指针,后面不需要释放
- 参考
解决 C 语言中的 Free Invalid Pointer 错误
munmap_chunk(): invalid pointer
2.有些OpenSSL结构体的使用
在OpenSSL官网参考文档里,有时候可以直接搜索结构体开头的函数,或者在源码里/.../apps/和/.../crypto/里搜