TLS + OpenSSL + Engine + PKCS#11 + softhsm2 安全通信

TLS + OpenSSL + Engine + PKCS#11 + softhsm2 安全通信引擎库路径只有在 /lib 下才能被 \”LOAD\” 识别到,OpenSSL的ReadMe给的示例在/lib,看源码才

引擎库路径只能通过/lib下的“LOAD”识别。 OpenSSL 自述文件中的示例位于/lib 下。直到看源码才明白为什么不能任意指定路径。

//#define PKCS11_ENGINE_PATH \’/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so\’

#定义PKCS11_ENGINE_PATH \’/lib/pkcs11.so\’

客户

#include stdio.h

#包括stdlib.h

#include 字符串.h

#include errno.h

#include sys/socket.h

#include resolv.h

#include netinet/in.h

#include arpa/inet.h

#include unistd.h

#include openssl/err.h

#include openssl/engine.h

#include openssl/pem.h

#include openssl/ssl.h

#include openssl/x509.h

//#define PKCS11_ENGINE_PATH \’/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so\’

#定义PKCS11_ENGINE_PATH \’/lib/pkcs11.so\’

#define PKCS11_MODULE_PATH \’/usr/lib/softhsm/libsofthsm2.so\’

#define CERT_FILE \’./hsm_pem/client.crt\’

#define CA_CERT_FILE \’./hsm_pem/ca.crt\’

#define TOKEN_LABEL \’mytoken\’

#definePIN \’1234\’

#define KEY_ID \’mytoken\’

#defineMAXBUF 1024

voidInitialize_ssl_library() {

SSL_library_init();

SSL_load_error_strings();

OpenSSL_add_all_algorithms();

}

无效cleanup_ssl_library(){

EVP_cleanup();

ERR_free_strings();

}

引擎*load_pkcs11_engine() {

ENGINE_load_dynamic();

ENGINE *engine=ENGINE_by_id(\’动态\’);

如果(!引擎){

fprintf(stderr, \’加载动态引擎失败\\n\’);

返回NULL。

}

if (!ENGINE_ctrl_cmd_string(engine, \’SO_PATH\’, PKCS11_ENGINE_PATH, 0) ||

!ENGINE_ctrl_cmd_string(引擎, \’ID\’, \’pkcs11\’, 0) ||

!ENGINE_ctrl_cmd_string(引擎, \’LIST_ADD\’, \’1\’, 0) ||

!ENGINE_ctrl_cmd_string(引擎, \’加载\’, NULL, 0)) {

fprintf(stderr, \’PKCS#11 引擎配置和加载失败\\n\’);

ENGINE_free(引擎);

返回NULL。

}

if (!ENGINE_ctrl_cmd_string(engine, \’MODULE_PATH\’, PKCS11_MODULE_PATH, 0)) {

fprintf(stderr, \’无法设置MODULE_PATH\\n\’);

ENGINE_free(引擎);

返回NULL。

}

如果(!ENGINE_init(引擎)){

fprintf(stderr, \’PKCS#11 引擎初始化失败\\n\’);

ENGINE_free(引擎);

返回NULL。

}

if (!ENGINE_ctrl_cmd_string(引擎, \’PIN\’, PIN, 0)) {

fprintf(stderr, \’无法设置PIN\\n\’);

ENGINE_free(引擎);

返回NULL。

}

返回引擎。

}

int main(int argc, char **argv)

{

初始化_ssl_library();

SSL_CTX *ctx=SSL_CTX_new(TLS_client_method());

如果(!ctx){

fprintf(stderr, \’创建SSL_CTX 失败\\n\’);

返回1。

}

//加载CA证书

if (!SSL_CTX_load_verify_locations(ctx, CA_CERT_FILE, NULL)) {

fprintf(stderr, \’无法加载CA 证书\\n\’);

SSL_CTX_free(ctx);

cleanup_ssl_library();

返回1。

}

//加载客户端证书

if (!SSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM)) {

fprintf(stderr, \’无法加载客户端证书\\n\’);

SSL_CTX_free(ctx);

cleanup_ssl_library();

返回1。

}

//加载PKCS#11 引擎

引擎*engine=load_pkcs11_engine();

如果(!引擎){

SSL_CTX_free(ctx);

cleanup_ssl_library();

返回1。

}

字符key_id[256];

snprintf(key_id, sizeof(key_id), \’pkcs11:token=%s;object=%s\’, TOKEN_LABEL, KEY_ID);

EVP_PKEY *pkey=ENGINE_load_private_key(引擎, key_id, NULL, NULL);

如果(!pkey){

fprintf(stderr, \’无法从PKCS#11\\n 加载私钥\’);

ENGINE_free(引擎);

SSL_CTX_free(ctx);

cleanup_ssl_library();

返回1。

}

如果(!SSL_CTX_use_PrivateKey(ctx,pkey)){

fprintf(stderr, \’私钥使用失败\\n\’);

EVP_PKEY_free(pkey);

ENGINE_free(引擎);

SSL_CTX_free(ctx);

cleanup_ssl_library();

返回1。

}

EVP_PKEY_free(pkey);

ENGINE_free(引擎);

//检查私钥与证书是否匹配

如果(!SSL_CTX_check_private_key(ctx)){

fprintf(stderr, \’私钥与证书的公钥不匹配\\n\’);

SSL_CTX_free(ctx);

cleanup_ssl_library();

返回1。

}

/* 创建TCP通信的socket */

int sockfd;

结构体sockaddr_in dest;

if ((sockfd=套接字(AF_INET, SOCK_STREAM, 0)) 0) {

pererror(\’套接字\’);

结束(错误号);

}

printf(\’套接字创建成功!\\n\’);

/* 初始化服务器(对方)地址和端口信息*/

bzero(dest, sizeof(dest));

dest.sin_family=AF_INET;

dest.sin_port=htons(atoi(argv[2]));

if (inet_aton(argv[1], (struct in_addr *) dest.sin_addr.s_addr)==0) {

错误(argv[1]);

结束(错误号);

}

printf(\’地址创建成功!\\n\’);

/* 连接到服务器*/

if (connect(sockfd, (struct sockaddr *) dest, sizeof(dest)) !=0) {

pererror(\’连接\’);

结束(错误号);

}

printf(\’服务器连接成功!\\n\’);

//创建SSL连接

SSL *ssl=SSL_new(ctx);

如果(!ssl){

fprintf(stderr, \’无法创建SSL 对象\\n\’);

SSL_CTX_free(ctx);

cleanup_ssl_library();

返回1。

}

SSL_set_fd(ssl, sockfd);

//与服务器执行SSL/TLS 握手

如果(SSL_connect(ssl)=0){

fprintf(stderr, \’SSL/TLS 握手失败\\n\’);

SSL_free(SSL);

SSL_CTX_free(ctx);

cleanup_ssl_library();

返回1。

}

printf(\’SSL/TLS 握手成功\\n\’);

字符send_buffer[MAXBUF + 1];

字符类型recv_buffer[MAXBUF + 1];

int 长度;

同时(1)

{

//使用SSL_write函数发送数据

printf(\’请输入发送到服务器的内容:\\n\’);

scanf(\’%s\’, send_buffer);

if(!strncmp(send_buffer,\’+++\’,3))break //接收++并退出。

/* 向服务器发送消息*/

len=SSL_write(ssl, send_buffer, strlen(send_buffer));

如果(长度0)

printf(\’发送消息\’%s\’失败!错误代码为%d,错误消息为\’%s\’\\n\’, send_buffer, errno, strerror(errno));

除此之外

printf(\’消息\’%s\’成功发送。总共发送%d个字节!\\n\’,send_buffer, len);

memset(send_buffer,0,sizeof(send_buffer));

/* 使用SSL_read函数接收数据,最多可以接收对方MAXBUF字节的消息*/

len=SSL_read(ssl, recv_buffer, MAXBUF);

如果(长度0)

printf(\’消息成功接收:\’%s\’,总共%d字节数据\\n\’,recv_buffer,len);

除此之外

{

printf(\’接收消息失败!错误代码为%d,错误消息为\’%s\’\\n\’,errno, strerror(errno));

休息;

}

memset(recv_buffer,0,sizeof(recv_buffer));

}

SSL_free(SSL);

SSL_CTX_free(ctx);

cleanup_ssl_library();

返回0。

}

使用参数

./ssl_server 7838 1 ./pem/server.crt ./pem/server.key ./pem/ca.crt

./ssl_client 127.0.0.1 7838

测试结果,服务器

./ssl_server 7838 1 ./pem/server.crt ./pem/server.key ./pem/ca.crt

成功创建套接字!

你一定会成功的!

开始监听并等待客户端连接.

server: 从127.0.0.1、端口37678、套接字6 获得连接

收到客户端X509 证书

客户数字证书信息:

证书: /CN=localhost/C=CN/ST=clientprovince/L=clientcity/O=clientorganization/OU=clientgroup

发布者: /CN=MyCA

客户端证书验证通过!

等待客户端发送消息:

成功收到客户端消息:\’14673218723187234\’,共17字节数据

输入您要发送给客户的内容:

客户

./ssl_client 127.0.0.1 7838

成功创建套接字!

您已成功创建地址!

服务器连接成功!

SSL/TLS 握手成功

请输入您要发送到服务器的内容:

14673218723187234

消息‘14673218723187234’发送成功,共发送17个字节。

成功接收消息:\’fdsdfsgdfsjk\’(共12字节数据)

请输入您要发送到服务器的内容:

服务器参考

基于openssl的https双向身份认证及安全通信实现博客_基于openssl的身份认证-CSDN

以上关于#TLS + OpenSSL + Engine + PKCS#11 + Softhsm2 安全通信的相关内容来自网络,仅供参考。相关信息请参见官方公告。

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92052.html

(0)
CSDN's avatarCSDN
上一篇 2024年6月24日 下午5:50
下一篇 2024年6月24日 下午5:50

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注