TLS + OpenSSL + Engine + PKCS#11 + softhsm2 安全通信
引擎库路径只有在 /lib 下才能被 "LOAD" 识别到,OpenSSL的ReadMe给的示例在/lib,大概是在构建OpenSSL时默认的configure指定了lib路径
(图片来源网络,侵删)
// #define PKCS11_ENGINE_PATH "/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so" #define PKCS11_ENGINE_PATH "/lib/pkcs11.so"
本以为通过配置有效
./Configure --prefix=/usr/local/openssl \
--openssldir=/usr/local/openssl
或者改Makefile有效,但是
old="ENGINESDIR=\$(libdir)\/engines-1.1" new="ENGINESDIR=\/usr\/lib\/engine-1.1" sed -i "s/$old/$new/g" Makefile
构建出来还是
# openssl engine pkcs11 -t 281473798283296:error:25066067:DSO support routines:dlfcn_load:could not load the shared library:crypto/dso/dso_dlfcn.c:118:filename(/home/test0923/Documents/optee_three_part/openssl/out/lib/engines-1.1/pkcs11.so): /home/test0923/Documents/optee_three_part/openssl/out/lib/engines-1.1/pkcs11.so: cannot open shared object file: No such file or directory 281473798283296:error:25070067:DSO support routines:DSO_load:could not load the shared library:crypto/dso/dso_lib.c:162: 281473798283296:error:260B6084:engine routines:dynamic_load:dso not found:crypto/engine/eng_dyn.c:434: 281473798283296:error:2606A074:engine routines:ENGINE_by_id:no such engine:crypto/engine/eng_list.c:421:id=pkcs11
但只找到了export方法
export OPENSSL_ENGINES=/usr/lib/engines-1.1
客户端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// #define PKCS11_ENGINE_PATH "/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so"
#define 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"
#define PIN "1234"
#define KEY_ID "mytoken"
#define MAXBUF 1024
void initialize_ssl_library() {
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
}
void cleanup_ssl_library() {
EVP_cleanup();
ERR_free_strings();
}
ENGINE *load_pkcs11_engine() {
ENGINE_load_dynamic();
ENGINE *engine = ENGINE_by_id("dynamic");
if (!engine) {
fprintf(stderr, "Failed to load dynamic engine\n");
return NULL;
}
if (!ENGINE_ctrl_cmd_string(engine, "SO_PATH", PKCS11_ENGINE_PATH, 0) ||
!ENGINE_ctrl_cmd_string(engine, "ID", "pkcs11", 0) ||
!ENGINE_ctrl_cmd_string(engine, "LIST_ADD", "1", 0) ||
!ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0)) {
fprintf(stderr, "Failed to configure and load PKCS#11 engine\n");
ENGINE_free(engine);
return NULL;
}
if (!ENGINE_ctrl_cmd_string(engine, "MODULE_PATH", PKCS11_MODULE_PATH, 0)) {
fprintf(stderr, "Failed to set MODULE_PATH\n");
ENGINE_free(engine);
return NULL;
}
if (!ENGINE_init(engine)) {
fprintf(stderr, "Failed to initialize PKCS#11 engine\n");
ENGINE_free(engine);
return NULL;
}
if (!ENGINE_ctrl_cmd_string(engine, "PIN", PIN, 0)) {
fprintf(stderr, "Failed to set PIN\n");
ENGINE_free(engine);
return NULL;
}
return engine;
}
int ShowCerts(SSL * ssl)
{
X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl);
// SSL_get_verify_result()是重点,SSL_CTX_set_verify()只是配置启不启用并没有执行认证,调用该函数才会真证进行证书认证
// 如果验证不通过,那么程序抛出异常中止连接
if(SSL_get_verify_result(ssl) == X509_V_OK){
printf("收到server X509证书\n");
}
else{
printf("未收到server X509证书\n");
return 1;
}
if (cert != NULL) {
printf("server数字证书信息:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("证书: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("颁发者: %s\n\n", line);
free(line);
X509_free(cert);
printf("对server证书验证通过!!!\n");
}
else{
printf("无证书信息,对server证书验证失败!!!\n");
return 1;
}
return 0;
}
int main(int argc, char **argv)
{
initialize_ssl_library();
SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
if (!ctx) {
fprintf(stderr, "Failed to create SSL_CTX\n");
return 1;
}
// 双向验证
// SSL_VERIFY_PEER---要求对证书进行认证,没有证书也会放行
// SSL_VERIFY_FAIL_IF_NO_PEER_CERT---要求客户端需要提供证书,但验证发现单独使用没有证书也会放行
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
// Load CA certificate
if (!SSL_CTX_load_verify_locations(ctx, CA_CERT_FILE, NULL)) {
fprintf(stderr, "Failed to load CA certificate\n");
SSL_CTX_free(ctx);
cleanup_ssl_library();
return 1;
}
// Load client certificate
if (!SSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM)) {
fprintf(stderr, "Failed to load client certificate\n");
SSL_CTX_free(ctx);
cleanup_ssl_library();
return 1;
}
// Load PKCS#11 engine
ENGINE *engine = load_pkcs11_engine();
if (!engine) {
SSL_CTX_free(ctx);
cleanup_ssl_library();
return 1;
}
char 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(engine, key_id, NULL, NULL);
if (!pkey) {
fprintf(stderr, "Failed to load private key from PKCS#11\n");
ENGINE_free(engine);
SSL_CTX_free(ctx);
cleanup_ssl_library();
return 1;
}
if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
fprintf(stderr, "Failed to use private key\n");
EVP_PKEY_free(pkey);
ENGINE_free(engine);
SSL_CTX_free(ctx);
cleanup_ssl_library();
return 1;
}
EVP_PKEY_free(pkey);
ENGINE_free(engine);
// Verify that the private key matches the certificate
if (!SSL_CTX_check_private_key(ctx)) {
fprintf(stderr, "Private key does not match the certificate public key\n");
SSL_CTX_free(ctx);
cleanup_ssl_library();
return 1;
}
/* 创建一个 socket 用于 tcp 通信 */
int sockfd;
struct sockaddr_in dest;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 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
socket created success!
binded success!
begin listen,waitting for client connect...
server: got connection from 127.0.0.1, port 35546, socket 6
收到client X509证书
client数字证书信息:
证书: /CN=localhost/C=CN/ST=clientprovince/L=clientcity/O=clientorganization/OU=clientgroup
颁发者: /CN=MyCA
对client证书验证通过!!!
等待客户端发送过来的消息:
接收client消息成功:'saddfsafijd',共11个字节的数据
请输入要发送给客户端的内容:
asfdsa
消息'asfdsa'发送成功,共发送了6个字节!
等待客户端发送过来的消息:
客户端
./ssl_client 127.0.0.1 7838
socket created success!
address created success!
server connected success!
SSL/TLS handshake successful
收到server X509证书
server数字证书信息:
证书: /CN=myserver.com
颁发者: /CN=MyCA
对server证书验证通过!!!
请输入要发送给服务器的内容:
saddfsafijd
消息'saddfsafijd'发送成功,共发送了11个字节!
接收消息成功:'asfdsa',共6个字节的数据
请输入要发送给服务器的内容:
服务端引用
基于openssl实现https双向身份认证及安全通信_基于openssl身份认证-CSDN博客
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!
