死磕GMSSL通信-C/C++系列(一)
最近再做国密通信的项目开发,以为国密也就简单的集成一个库就可以完事了,没想到能有这么多坑。遂写下文章,避免重复踩坑。以下国密通信的坑有以下场景
1、使用GMSSL guanzhi/GmSSL进行通信
2、使用加密套件SM2-WITH-SMS4-SM3
使用心得
GmSSL这个库的问题很多,发现许多库和它都不能正常通信,都需要修改代码,不是修改客户端就是修改服务端,而且这个开源项目基本处于不维护的状态,如果准备集成的GM通信的,优先选择铜锁/Tongsuo 这个项目,毕竟背后是商业公司在维护。
1、经过最近几天的测试,发现
window编译
网上有好多编译教程,我这里也不细说了,大概步骤如下
安装Perl软件:从Perl官网(https://www.activestate.com/products/perl/downloads/)下载安装包直接安装就行了。安装完好后命令行执行【perl -v】就可以查看版本信息
以64位为列,打开“ VS2015 x64 本机工具命令提示符”
执行:perl Configure VC-WIN64A no-asm no-shared
- VC-WIN32 表示编译选项生成32位的库
- VC-WIN64A 表示编译选项生成64位的库
- VC-WIN64I 表示编译选项生成IA64的库,使用安腾cpu的需要使用此选项,安腾x64架构是inter自家的,比较少见
- no-asm 表示不使用汇编,如果本地安装了nasm工具,可以不使用此选项
- –prefix=D:xxx\xx 表示输出目录
执行nmake
最后程序根目录生成俩个静态库 libcrypto.lib、libssl.lib
生成证书
这里就不提供证书生成的过程了,网上生成的教程很多,GMSSL需要五个证书
-
CA.cert.pem
-
SE.cert.pem
-
SE.key.pem
-
SS.cert.pem
-
SS.key.pem
[注意]
理论上客户端和服务端的证书应该是俩套,也可以直接客户端和服务器用一样的证书,我这里直接用了一套,大家可以自行测试俩套的
GMSSL双向通信
server端代码
/*
* Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* A minimal program to serve an SSL connection.
* It uses blocking.
* saccept host:port
* host is the interface IP to use. If any interface, use *:port
* The default it *:4433
*
* cc -I../../include saccept.c -L../.. -lssl -lcrypto -ldl
*/
#include <stdio.h>
#include <signal.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#define CA_CERT_FILE "CA.cert.pem"
#define SIGN_CERT_FILE "SS.cert.pem"
#define SIGN_KEY_FILE "SS.key.pem"
#define ENCODE_CERT_FILE "SE.cert.pem"
#define ENCODE_KEY_FILE "SE.key.pem"
static int done = 0;
void interrupt(int sig)
{
done = 1;
}
int main(int argc, char* argv[])
{
char* port = "0.0.0.0:9999";
BIO* in = NULL;
BIO* ssl_bio, * tmp;
SSL_CTX* ctx;
char buf[512];
int ret = 1, i;
ctx = SSL_CTX_new(GMTLS_server_method());
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
#if 1
if (!SSL_CTX_load_verify_locations(ctx, CA_CERT_FILE, NULL))
{
goto err;
}
if (!SSL_CTX_use_certificate_file(ctx, SIGN_CERT_FILE, SSL_FILETYPE_PEM))
goto err;
if (!