gmssl 国密ssl 源码测试 --非BIO接口
前言
之前的章节中使用gmssl的命令行对ssl gmtls 进行了测试,这里,使用gmssl的源码接口,通过编写测试程序的方式对gmtls进行测试。
注意:
本次使用的是gmssl编译出来的libcrypto.a 和libssl.a 两个静态库。
一 服务端流程
1 ssl初始化
/* SSL 库初始化*/
SSL_library_init();
/* 载入所有SSL 算法*/
OpenSSL_add_all_algorithms();
/* 载入所有SSL 错误消息*/
SSL_load_error_strings();
/* 以SSL V2 和V3 标准兼容方式产生一个SSL_CTX ,即SSL Content Text */
//ctx = SSL_CTX_new(SSLv23_server_method());
ctx = SSL_CTX_new(GMTLS_server_method());
/*
也可以用SSLv2_server_method() 或SSLv3_server_method() 单独表示V2 或V3标准
*/
2 配置验证对方证书,并加载ca证书
//验证对方
SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
//若验证,则放置CA证书
ret = SSL_CTX_load_verify_locations(ctx, "gmcrt/ca.crt", NULL);
printf("ssl load ca ret=%d\n",ret);
3 配置本端双证书和私钥
/* 载入用户的数字证书, 此证书用来发送给客户端。证书里包含有公钥*/
if (SSL_CTX_use_certificate_file(ctx, "gmcrt/1_sign.crt", SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stdout);
exit(1);
}
/* 载入用户私钥*/
if (SSL_CTX_use_PrivateKey_file(ctx, "gmcrt/1_sign.key", SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stdout);
exit(1);
}
/* 载入用户的数字证书, 此证书用来发送给客户端。证书里包含有公钥*/
if (SSL_CTX_use_certificate_file(ctx, "gmcrt/1_enc.crt", SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stdout);
exit(1);
}
/* 载入用户私钥*/
if (SSL_CTX_use_PrivateKey_file(ctx, "gmcrt/1_enc.key", SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stdout);
exit(1);
}
/* 检查用户私钥是否正确*/
if (!SSL_CTX_check_private_key(ctx))
{
ERR_print_errors_fp(stdout);
exit(1);
}
4 开启一个socket
j建立socket,并监听,accept等,和普通socket流程一致
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
else
{
printf("socket created\n");
}
bzero( &my_addr, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(myport);
listen(sockfd, lisnum);
5 建立ssl连接
新建ssl连接,并将socket句柄配置到ssl连接中,之后开始ssl accept,等待客户端连接。
ssl = SSL_new(ctx);
/* 将连接用户的socket 加入到SSL */
SSL_set_fd(ssl, new_fd);
/* 建立SSL 连接*/
// ret=SSL_set_cipher_list(ssl,"ECDHE_SM2_WITH_SMS4_GCM_SM3");
if (SSL_accept(ssl) == -1)
6 从ssl连接中读写数据
len = SSL_write(ssl, buf, strlen(buf));
len = SSL_read(ssl, buf, MAXBUF);
二 客户端流程
1 初始化ssl
/* SSL 库初始化*/
SSL_library_init();
/* 载入所有SSL 算法*/
OpenSSL_add_all_algorithms();
/* 载入所有SSL 错误消息*/
SSL_load_error_strings();
/* 以SSL V2 和V3 标准兼容方式产生一个SSL_CTX ,即SSL Content Text */
//ctx = SSL_CTX_new(SSLv23_client_method());
ctx = SSL_CTX_new(GMTLS_client_method());
2 配置验证服务端证书,并加载ca证书
SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
ret = SSL_CTX_load_verify_locations(ctx, "gmcrt/ca.crt", NULL);
printf("ssl load cerify ca ret=%d\n",ret);
3 加载双证书
/* 载入用户的数字证书, 此证书用来发送给客户端。证书里包含有公钥*/
if (SSL_CTX_use_certificate_file(ctx, "gmcrt/2_sign.crt", SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stdout);
exit(1);
}
/* 载入用户私钥*/
if (SSL_CTX_use_PrivateKey_file(ctx, "gmcrt/2_sign.key", SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stdout);
exit(1);
}
if (SSL_CTX_use_certificate_file(ctx, "gmcrt/2_enc.crt", SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stdout);
exit(1);
}
/* 载入用户私钥*/
if (SSL_CTX_use_PrivateKey_file(ctx, "gmcrt/2_enc.key", SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stdout);
exit(1);
}
/* 检查用户私钥是否正确*/
if (!SSL_CTX_check_private_key(ctx))
{
ERR_print_errors_fp(stdout);
exit(1);
}
4 建立socket,连接到服务端。
这块不写了,和普通socket流程一致。
5 建立ssl连接
新建ssl连接,并将socket句柄配置到ssl连接中,之后开始ssl accept,等待客户端连接。
ssl = SSL_new(ctx);
/* 将新连接的socket 加入到SSL */
SSL_set_fd(ssl, sockfd);
/* 建立SSL 连接*/
if (SSL_connect(ssl) == -1)
{
ERR_print_errors_fp(stderr);
}
6 从ssl连接中读写数据
len = SSL_write(ssl, buf, strlen(buf));
len = SSL_read(ssl, buf, MAXBUF);
三 测试数据和日志
服务端:
ssl set verify ret=0
ssl load ca ret=1
[GMTLS_DEBUG] set sm2 signing certificate
[GMTLS_DEBUG] viqjeee set sm2 signing private key 2
[GMTLS_DEBUG] set sm2 encryption certificate
[GMTLS_DEBUG] viqjeee set sm2 decryption private key 2
socket created
binded
begin listen
server: got connection from 127.0.0.1, port 48783, socket 4
ssl_get_algorithm2=40c04008x
消息'server->client'发送成功,共发送了14 个字节!
接收消息成功:'from client->server',共19 个字节的数据
客户端:
ssl load cerify ca ret=1
[GMTLS_DEBUG] set sm2 signing certificate
[GMTLS_DEBUG] viqjeee set sm2 signing private key 2
[GMTLS_DEBUG] set sm2 encryption certificate
[GMTLS_DEBUG] viqjeee set sm2 decryption private key 2
socket created
address created
server connected
Z=47C0C333B4A586DC828C283395B5512DC4DF0347FB2CD9110A258FAA57E7997B
C=00025C30820258308201FDA003020102020101300A06082A811CCF550183753079310B300906035504061302434E3113301106035504080C0A536F6D652D53746174653110300E06035504070C076265696A696E673121301F060355040A0C18496E7465726E6574205769646769747320507479204C7464310B3009060355040B0C0278643113301106035504030C0A79616F6D696E67797565301E170D3231303130373039333933325A170D3331303130353039333933325A3067310B300906035504061302434E3113301106035504080C0A536F6D652D53746174653121301F060355040A0C18496E7465726E6574205769646769747320507479204C7464310B3009060355040B0C0278643113301106035504030C0A79616F6D696E677975653059301306072A8648CE3D020106082A811CCF5501822D0342000485D806700880BFC9DA1454C7B74F855EF91124B058A4B32F100EF6BC71B0BDD3CCA992DBEF9280BF9F0080AFD0736E1F7EA9ACE1590E83C7F52F75BB7A2BCF17A3818730818430090603551D1304023000300B0603551D0F040403020520302A06096086480186F842010D041D161B476D53534C2047656E657261746564204365727469666963617465301D0603551D0E041604142459546498D9D3E577E24B940B7BD161114F2005301F0603551D2304183016801478E41EBAC5F4575285AB51735D9B5B4BCA9E28E5300A06082A811CCF550183750349003046022100C89AC904C4C88B272B02738505C43E73EAD2DB28B0F2F6C0E947E261C3396451022100EB21178562D6852D42D7F3D2DECC3212ADB45C9F15401E91AC4264217E3D37F9
ssl_get_algorithm2=40bf5008x
Connected with SM2-WITH-SMS4-SM3 encryption
数字证书信息:
证书: /C=CN/ST=Some-State/O=Internet Widgits Pty Ltd/OU=yao/CN=yao
颁发者: /C=CN/ST=Some-State/L=beijing/O=Internet Widgits Pty Ltd/OU=xd/CN=yao
接收消息成功:'server->client',共14 个字节的数据
消息'from client->server'发送成功,共发送了19 个字节!
测试代码
本文源码:
https://download.youkuaiyun.com/download/qq_39952971/16079679
测试步骤:
客户端:
./client 127.0.0.1 18888
服务端:
./server 18888 3 127.0.0.1