GMSSL-通信

发布于:2024-04-16 ⋅ 阅读:(24) ⋅ 点赞:(0)
死磕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 本机工具命令提示符”

image-20240412170837915

执行:perl Configure VC-WIN64A no-asm no-shared

image-20240412171021233

  • VC-WIN32 表示编译选项生成32位的库
  • VC-WIN64A 表示编译选项生成64位的库
  • VC-WIN64I 表示编译选项生成IA64的库,使用安腾cpu的需要使用此选项,安腾x64架构是inter自家的,比较少见
  • no-asm 表示不使用汇编,如果本地安装了nasm工具,可以不使用此选项
  • –prefix=D:xxx\xx 表示输出目录

执行nmake

image-20240412171044150

最后程序根目录生成俩个静态库 libcrypto.lib、libssl.lib

生成证书

这里就不提供证书生成的过程了,网上生成的教程很多,GMSSL需要五个证书

  1. CA.cert.pem

  2. SE.cert.pem

  3. SE.key.pem

  4. SS.cert.pem

  5. 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 (!