gmssl国密总结

1、gmssl组成

分为加密和通信两部分

2、加密

主要指的是sm2 sm3 sm4加密算法,以及相关的加密组件

3、通信

指的是gmtls

按照一个 GM/T 0024-2014规范实现的,采用双证书,签名证书+加密证书

4、生成证书

可使用地址https://github.com/jntass/TASSL/tree/master/Tassl_demo/mk_tls_cert 下的SM2certgen.sh生成双证书。

注意:生成请求时指定的摘要算法 在用请求生成证书时并不生效,需要重新指定,否则会使用默认的算法rsa-sha256

针对gmssl,签名算法一定要是sm2sign-with-sm3

针对tassl,只要加密用的是sm2即可,sm2sign-with-sm3不是必须

5、兼容性

指的是gmssl对openssl的兼容性

ssl/tls下,仅支持有限的套件:

ECDHE-SM2-WITH-SMS4-SM3

ECDHE-SM2-WITH-SMS4-SHA256

不是完全兼容的

采用老的openssl证书,要指定tls版本为1或1.2才可以,或者直接使用TSLv1_2_method,使用TSL_method不可以,号称的会自己检测版本并没有实现,貌似默认是使用1.1版本

6、双证书

gmssl对双证书和双密钥的设置

直接设置两个sm2证书和密钥就可以,没有新增接口,都是代码里自己适配:

keyusagedigitalSignature 类型的证书是签名证书,否则是加密证书,密钥呢,加密证书存在的时候是加密密钥,否则是签名密钥

这个其实是有漏洞的,必须先设置签名证书。。然后才是加密证书

tassl是有的,增加了一个设置加密密钥的接口SSL_use_enc_PrivateKey,设置证书的接口也是代码里适配的,证书类型需要keyusage(keyAgreementkeyEnciphermentdataEncipherment)

7、版本

以上总结仅针对GmSSL最新版(v2.3.1)和tassl当前最新版(2018-09-17)

8、最新版的openssl已经支持国密算法

仅仅支持国密的算法,通信还未支持

9、编程实现

server.c:

#include <stdio.h>

#include <string.h>

#include <openssl/evp.h>

#include <openssl/x509.h>

#include <openssl/ssl.h>

#include <openssl/pem.h>

#include <openssl/err.h>

#include <sys/socket.h>

#include <unistd.h>

#include <netinet/in.h>

//#define CERTSERVER "/tmp/testopenssl/demoCA/cacert.pem"

//#define KEYSERVER "/tmp/testopenssl/demoCA/private/cakey.pem"

#define CERTSERVER "SS.pem"

#define KEYSERVER "SS.key.pem"

#define SM2_SERVER_ENC_CERT    "SE.pem"

#define SM2_SERVER_ENC_KEY      "SE.key.pem"

#define CHK_ERR(err, s) if((err) == -1) { perror(s); return -1; }else printf("%s  success!\n",s);

#define CHK_RV(rv, s) if((rv) != 1) { printf("%s error\n", s); return -1; }else printf("%s  success!\n",s);

#define CHK_NULL(x, s) if((x) == NULL) { printf("%s error\n", s); return -1; }else printf("%s  success!\n",s);

#define CHK_SSL(err, s) if((err) == -1) { ERR_print_errors_fp(stderr);  return -1;}else printf("%s  success!\n",s);

int main()

{

int rv, err;

SSL_CTX *ctx = NULL;

SSL_METHOD *meth = NULL;

int listen_sd;

int accept_sd;

struct sockaddr_in socketAddrServer;

struct sockaddr_in socketAddrClient;

socklen_t socketAddrClientLen;

SSL *ssl = NULL;

char buf[4096];

rv = SSL_library_init();

CHK_RV(rv, "SSL_library_init");

meth = (SSL_METHOD *)GMTLS_server_method();

ctx = SSL_CTX_new(meth);

CHK_NULL(ctx, "SSL_CTX_new");

rv = SSL_CTX_use_certificate_file(ctx, CERTSERVER, SSL_FILETYPE_PEM);

CHK_RV(rv, "SSL_CTX_use_certicificate_file");

rv = SSL_CTX_use_PrivateKey_file(ctx, KEYSERVER, SSL_FILETYPE_PEM);

CHK_RV(rv, "SSL_CTX_use_PrivateKey_file");

rv = SSL_CTX_check_private_key(ctx);

CHK_RV(rv, "SSL_CTX_check_private_key");

rv = SSL_CTX_use_certificate_file(ctx, SM2_SERVER_ENC_CERT, SSL_FILETYPE_PEM);

CHK_RV(rv, "SSL_CTX_use_certicificate_file2");

rv = SSL_CTX_use_PrivateKey_file(ctx, SM2_SERVER_ENC_KEY, SSL_FILETYPE_PEM);

CHK_RV(rv, "SSL_CTX_use_PrivateKey_file2");

rv = SSL_CTX_check_private_key(ctx);

CHK_RV(rv, "SSL_CTX_check_private_key2");

SSL_CTX_set_security_level(ctx, 0);

listen_sd = socket(AF_INET, SOCK_STREAM, 0);

CHK_ERR(listen_sd, "socket");

memset(&socketAddrServer, 0, sizeof(socketAddrServer));

socketAddrServer.sin_family = AF_INET;

socketAddrServer.sin_port = htons(8443);

socketAddrServer.sin_addr.s_addr = INADDR_ANY;

err = bind(listen_sd, (struct sockaddr *)&socketAddrServer, sizeof(socketAddrServer));

CHK_ERR(err, "bind");

err = listen(listen_sd, 5);

CHK_ERR(err, "listen");

socketAddrClientLen = sizeof(socketAddrClient);

accept_sd = accept(listen_sd, (struct sockaddr *)&socketAddrClient, &socketAddrClientLen);

CHK_ERR(accept_sd, "accept");

close(listen_sd);

printf("Connect from %lx, port %x\n", socketAddrClient.sin_addr.s_addr, socketAddrClient.sin_port);

ssl = SSL_new(ctx);

CHK_NULL(ssl, "SSL_new");

rv = SSL_set_fd(ssl, accept_sd);

CHK_RV(rv, "SSL_set_fd");

rv = SSL_accept(ssl);

CHK_RV(rv, "SSL_accpet");

/* Check for Client authentication error */

if (SSL_get_verify_result(ssl) != X509_V_OK) {

printf("SSL Client Authentication error\n");

SSL_free(ssl);

close(accept_sd);

SSL_CTX_free(ctx);

exit(0);

}

/*Print out connection details*/

printf("SSL connection on socket %x,Version: %s, Cipher: %s\n",

accept_sd,

SSL_get_version(ssl),

SSL_get_cipher(ssl));

rv = SSL_read(ssl, buf, sizeof(buf) - 1);

CHK_SSL(rv, "SSL_read");

buf[rv] = ‘\0‘;

printf("Got %d chars :%s\n", rv, buf);

rv = SSL_write(ssl, "I accept your request", strlen("I accept your request"));

CHK_SSL(rv, "SSL_write");

close(accept_sd);

SSL_free(ssl);

SSL_CTX_free(ctx);

return 0;

}

client.c:

#include <stdio.h>

#include <string.h>

#include <openssl/evp.h>

#include <openssl/x509.h>

#include <openssl/ssl.h>

#include <openssl/pem.h>

#include <openssl/err.h>

#include <sys/socket.h>

#include <unistd.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <iostream>

#define SERVER_IP      "127.0.0.1"

#define SERVER_PORT    8443

int main( int argc, char* argv[] ) {

int ret;

////////////

// 初始化 //

////////////

SSL_CTX* ctx;

SSL_METHOD *meth;

OpenSSL_add_ssl_algorithms();

SSL_load_error_strings();

//meth = (SSL_METHOD *)TLS_client_method();

meth = (SSL_METHOD *)GMTLS_client_method();

ctx = SSL_CTX_new (meth);

if (!ctx) {

ERR_print_errors_fp(stderr);

std::cout<<"SSL_CTX_new error."<<std::endl;

return -1;

}

//SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES256-GCM-SHA384");

//  SSL_CTX_set_max_proto_version(ctx,TLS1_2_VERSION);

//  SSL_CTX_set_min_proto_version(ctx,TLS1_2_VERSION);

///////////////////////

// 建立原始的TCP连接 //

///////////////////////

int client_socket;

struct sockaddr_in addr_server;

client_socket = socket (AF_INET, SOCK_STREAM, 0);

if( client_socket == -1  ) {

std::cout<<"socket error."<<std::endl;

return -1;

}

memset (&addr_server, 0, sizeof(addr_server));

addr_server.sin_family          = AF_INET;

addr_server.sin_addr.s_addr = inet_addr(SERVER_IP);

addr_server.sin_port            = htons (SERVER_PORT);

ret = connect(client_socket, (struct sockaddr*) &addr_server, sizeof(addr_server));

if( ret == -1  ) {

std::cout<<"connect error."<<std::endl;

return -1;

}

/////////////////////////////////////

// TCP连接已经建立,执行Client SSL //

/////////////////////////////////////

SSL*    ssl;

X509*    server_certificate;

char*    str;

ssl = SSL_new (ctx);

if( ssl == NULL ) {

std::cout<<"SSL_new error."<<std::endl;

return -1;

}

SSL_set_fd (ssl, client_socket);

ret = SSL_connect (ssl);

if( ret == -1 ) {

std::cout<<"SSL_connect error."<<std::endl;

ERR_print_errors_fp(stderr);

return -1;

}

ERR_print_errors_fp(stderr);

// 接下来的获取密码和获取服务器端证书的两部是可选的,不会影响数据交换

// 获取cipher

std::cout<<"SSL connection using: "<<SSL_get_cipher(ssl)<<std::endl;

// 获取服务器端的证书

server_certificate = SSL_get_peer_certificate (ssl);

if( server_certificate != NULL ) {

std::cout<<"Server certificate:"<<std::endl;

str = X509_NAME_oneline (X509_get_subject_name (server_certificate),0,0);

if( str == NULL ) {

std::cout<<"X509_NAME_oneline error."<<std::endl;

} else {

std::cout<<"subject: "<<str<<std::endl;

OPENSSL_free (str);

}

str = X509_NAME_oneline (X509_get_issuer_name  (server_certificate),0,0);

if( str == NULL ) {

std::cout<<"X509_NAME_oneline error."<<std::endl;

} else {

std::cout<<"issuer: "<<str<<std::endl;

OPENSSL_free (str);

}

X509_free (server_certificate);

} else {

std::cout<<"Server does not have certificate. we sould Esc!"<<std::endl;

return -1;

}

////////////////

//  数据交换  //

////////////////

char    buf [4096];

ret = SSL_write (ssl, "Hello World!", strlen("Hello World!"));

if( ret == -1 ) {

std::cout<<"SSL_write error."<<std::endl;

return -1;

}

ret = SSL_read (ssl, buf, sizeof(buf) - 1);

if( ret == -1 ) {

std::cout<<"SSL_read error."<<std::endl;

return -1;

}

buf[ret] = ‘\0‘;

std::cout<<buf<<std::endl;

SSL_shutdown(ssl);  /* send SSL/TLS close_notify */

/////////////

// Cleanup //

/////////////

close(client_socket);

SSL_free (ssl);

SSL_CTX_free (ctx);

return 0;

}

作者:高文茂
链接:https://www.jianshu.com/p/0dc9708e34de
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

原文地址:https://www.cnblogs.com/bigben0123/p/12628453.html

时间: 2024-11-05 19:00:20

gmssl国密总结的相关文章

国密算法的ekey的使用--简述

一.龙脉GMTools的使用 1.产品介绍 mToken GM3000 国密身份认证锁是龙脉科技自主研发设计支持国密算法.完全遵照国家密码管理局颁布的<智能IC卡及智能密码钥匙密码应用接口规范>要求设计的USB Key,采用国产高性能智能卡芯片,内置SSF33.SM1.SM2.SM3.SM4等国产算法,支持高速数据国密算法加解密,提供CSP以及PKCS11和国密接口,完全符合国家密码管理局关于"密钥不落地"的技术规范要求,是电子政务.电子军务.CA厂商首选的USB Key产

国密算法的ekey基本使用的说明

概述 本次需要进行的实验研究是国密算法的ekey的使用.对于一个或者多个应用来说,每个应用可以包含一个或多个容器(Container),每个容器中可以存放两对分别用于加密和签名的密钥对,以及两个相应的证书或证书链.每一个容器只能为ECC或RSA一种类型,一个容器中不能混用ECC密钥和RSA密钥.根据个人的理解,ekey的作用就是生成容器,将需要加密的消息或文件利用相应的加密算法加密后,生成证书,将证书导入ekey的容器中.这样以便于在其他终端上用到该文件时,使用ekey,其容器中的对应的证书可以

自己封装的openssl+国密算法的C++接口

Digest #ifndef _DIGESTCALC_H #define _DIGESTCALC_H /********************************** /* 使用示例:(sm3算法) /* DigestCalc hashcl; /* hashcl.Init(DigestCalc::alg_id::sm3); /* hashcl.Update(in,inl); /* vector<unsigned int> out(hashcl.GetHashLength()); /* h

谈谈PBOC3.0中使用的国密SM2算法

转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/39780825 作者:小马 一 知识准备 SM2是国密局推出的一种他们自己说具有自主知识产权的非对称商用password算法.本身是基于ECC椭圆曲线算法的.所以要讲sm2, 先要弄懂ECC. 全然理解ECC算法须要一定的数学功底.由于涉及到射影平面坐标系,齐次方程求解, 曲线的运算规则等概念. 这里不做过多的数学分析(主要是我自己也没有全然整明确). 想要深入了解ECC的我推荐网

PBOC3.0中使用的国密SM2算法详解

转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/39780825 作者:小马 一 知识准备 SM2是国密局推出的一种他们自己说具有自主知识产权的非对称商用密码算法.本身是基于ECC椭圆曲线算法的,所以要讲sm2, 先要弄懂ECC. 完全理解ECC算法需要一定的数学功底,因为涉及到射影平面坐标系,齐次方程求解, 曲线的运算规则等概念.这里不做过多的数学分析(主要是我自己也没有完全整明白).想要深入了解ECC的我推荐网名为ZMWorm

国密算法椭圆曲线参数

#设置默认椭圆曲线参数(P A B N Gx Gy H),将其设置为国密推荐椭圆曲线参数. #通过改写sm2_p, sm2_a, sm2_b, sm2_n, sm2_gx, sm2_gy, sm2_h,可以在自己的脚本里随意设置椭圆曲线参数. # #参数P set sm2_p FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF #参数A set sm2_a FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFF

SM2国密证书合法性验证

通常我们遇到过的X509证书都是基于RSA-SHA1算法的,目前国家在大力推行国密算法,未来银行发行的IC卡也都是基于PBOC3.0支持国密算法的,因此我们来学习一下如何验证SM2国密证书的合法性.至于SM2与SM3的算法实现不在本文讨论范围之内,可以用openssl.BouncyCastle.Crypto.dll等第三方库来实现. SM2国密证书与RSA证书一样,一般内容都是以BASE64格式编码的,以网上下载的一个自签名证书为例: MIIB5jCCAZECAQAwVDELMAkGA1UEBh

国密算法SM2证书制作

国密算法sm2非对称算法椭圆曲线 原文:http://www.jonllen.cn/jonllen/work/162.aspx 前段时间将系统的RSA算法全部升级为SM2国密算法,密码机和UKey硬件设备大都同时支持RSA和SM2算法,只是应用系统的加解密签名验证需要修改,这个更改底层调用的加密动态库来,原来RSA用的对称加密算法DES(AES)和摘要MD5(SHA1)也相应改变,分别对应SM1.SM3算法,SM1算法基于硬件实现,SM2.SM3算法已公开. SM2签名验证算法 SM2签名同样也

java 解析国密SM2算法证书

首先说明用Java自带的解析x509证书类,是不能解析sm2算法的证书,运行会抛出异常. 用开源库bouncycastle可以解析.具体代码 private byte[] getCSPK(byte[] csCert) { InputStream inStream = new ByteArrayInputStream(csCert); ASN1Sequence seq = null; ASN1InputStream aIn; try { aIn = new ASN1InputStream(inSt