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博客
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。