openssl + engine + pkcs11 双向认证测试

0 环境

openssl 1.1.1b https://www.cnblogs.com/jsjliyang/p/10606908.html

pkcs11-tool (由sudo apt-get install opensc 安装)

libpksc11 https://github.com/OpenSC/libp11

softhsm2 https://github.com/opendnssec/SoftHSMv2

 

1 证书生成

1.1 CA 自签署证书:

// 生成根证书私钥(pem文件)
openssl genrsa -out root.key 2048
// 生成根证书签发申请文件(csr文件)
openssl req -new -key root.key -out root.csr -subj "/CN=localhost/C=CN/ST=rootprovince/L=rootcity/O=rootorganization/OU=rootgroup"
// 自签发根证书(cer文件)
openssl x509 -req -days 365 -extensions v3_ca -signkey root.key -in root.csr -out root.crt

1.2 CA签发Server 证书:

// 生成服务端私钥   
openssl genrsa -out server.key 2048
// 生成证书请求文件 
openssl req -new -key server.key -out server.csr -subj "/CN=localhost/C=CN/ST=serverprovince/L=servercity/O=serverorganization/OU=servergroup"
// 使用根证书签发服务端证书
openssl x509 -req -days 365 -extensions v3_req -CA root.crt -CAkey root.key -CAserial root.srl -CAcreateserial -in server.csr -out server.crt
// 使用CA证书验证服务端证书
openssl verify -CAfile root.crt server.crt

1.3 CA签发Client证书,Client证书保存于pkcs11中:

//须先执行softhsm的步骤
//生成client密钥对 //module 为pkcs11格式的硬件驱动 id、label和pin要记住
pkcs11-tool --module /usr/local/lib/softhsm/libsofthsm2.so -l -k --key-type rsa:2048 --id 4144 --label testn --pin 56789
// 生成请求文件
openssl req -new -days 365  -subj "/CN=localhost/C=CN/ST=clientprovince/L=clientcity/O=clientorganization/OU=clientgroup" -engine pkcs11 -keyform engine -key "pkcs11:token=test;object=testn;type=private;pin-value=56789" -out client.csr
// 使用根证书签发客户端证书
openssl x509 -req -days 365 -extensions v3_req -CA root.crt -CAkey root.key -CAserial root.srl -CAcreateserial -in client.csr -out client.crt
// 使用CA证书验证客户端证书
openssl verify -CAfile root.crt client.crt
//将cert写入softhsm中
pkcs11-tool --module /usr/local/lib/softhsm/libsofthsm2.so -l --id 4144 --label testn -y cert -w client.crt --pin 56789

2 openssl双向认证

//服务器开启认证
openssl s_server -accept 8090 -key server.key -cert server.crt -CAfile root.crt -Verify 1
//客户端开启认证 此处的token为softhsm进行init时输入的label,而object为创建客户端密钥对时的label
openssl s_client -connect localhost:8090 -engine pkcs11 -keyform engine     -key "pkcs11:token=test;object=testn;type=private;pin-value=56789" -cert client.crt -CAfile root.crt
//接下来双方就可以传数据了

3 softhsm2相关

可以通过配置文件配置so加载:(未测试)

openssl_conf = openssl_init //放在conf文件的顶行

/**
*
*
**/

//以下放在底部
[openssl_init]
engines=engine_section

[engine_section]
pkcs11 = pkcs11_section

[pkcs11_section]
engine_id = pkcs11
dynamic_path = /usr/local/lib/engines-1.1/libpkcs11.so
MODULE_PATH = /usr/local/lib/softhsm/libsofthsm2.so
init = 0

或者命令行:

//加载softhsm
OpenSSL> engine -t dynamic -pre SO_PATH:/usr/local/lib/engines-1.1/libpkcs11.so
         -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD 
         -pre MODULE_PATH:/usr/local/lib/softhsm/libsofthsm2.so
//检测是否运行
openssl engine pkcs11 -t
//初始化softhsm
softhsm2-util --init-token --slot 0 --label "test"
//根据提示输入pin和user pin
=== SO PIN (4-255 characters) ===
Please enter SO PIN: ****
Please reenter SO PIN: ****
=== User PIN (4-255 characters) ===
Please enter user PIN: *****
Please reenter user PIN: *****
The token has been initialized and is reassigned to slot 394926501

 

以下是使用 OpenSSLPKCS#11 进行加解密的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/evp.h> #include <openssl/err.h> #include <openssl/pkcs12.h> #include <openssl/engine.h> #include <openssl/pkcs11.h> #define BUFSIZE 1024 int main(int argc, char *argv[]) { int rv, i; char *infile, *outfile, *password; FILE *in, *out; EVP_CIPHER_CTX *ctx = NULL; PKCS12 *p12 = NULL; X509 *cert = NULL; EVP_PKEY *pkey = NULL; PKCS11_CTX *p11ctx = NULL; CK_OBJECT_HANDLE hkey; CK_SESSION_HANDLE hsession; if (argc != 4) { printf("Usage: %s <infile> <outfile> <password>\n", argv[0]); return 1; } infile = argv[1]; outfile = argv[2]; password = argv[3]; /* Initialize OpenSSL and PKCS#11 */ ERR_load_crypto_strings(); ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); rv = PKCS11_CTX_init(&p11ctx, "pkcs11", NULL, NULL, 0); if (rv != CKR_OK) { printf("Error initializing PKCS#11 context\n"); goto cleanup; } /* Load PKCS#12 file */ in = fopen(infile, "rb"); if (in == NULL) { printf("Error opening input file: %s\n", infile); goto cleanup; } p12 = d2i_PKCS12_fp(in, NULL); if (p12 == NULL) { printf("Error reading PKCS#12 file: %s\n", infile); goto cleanup; } fclose(in); /* Extract certificate and private key from PKCS#12 file */ rv = PKCS12_parse(p12, password, &pkey, &cert, NULL); if (rv == 0) { printf("Error parsing PKCS#12 file: %s\n", infile); goto cleanup; } /* Find corresponding private key in PKCS#11 token */ rv = PKCS11_CTX_login(p11ctx, CKU_USER, password); if (rv != CKR_OK) { printf("Error logging in to PKCS#11 token\n"); goto cleanup; } hsession = PKCS11_CTX_get_session(p11ctx); rv = PKCS11_find_key(p11ctx, &hkey, cert, pkey); if (rv != CKR_OK) { printf("Error finding private key in PKCS#11 token\n"); goto cleanup; } /* Initialize context for decryption */ ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) { printf("Error creating cipher context\n"); goto cleanup; } rv = EVP_OpenInit(ctx, EVP_aes_256_cbc(), NULL, 0, NULL, pkey); if (rv != 1) { printf("Error initializing cipher context\n"); goto cleanup; } /* Decrypt input file and write output file */ in = fopen(infile, "rb"); if (in == NULL) { printf("Error opening input file: %s\n", infile); goto cleanup; } out = fopen(outfile, "wb"); if (out == NULL) { printf("Error opening output file: %s\n", outfile); goto cleanup; } while (1) { unsigned char inbuf[BUFSIZE], outbuf[BUFSIZE]; int inlen, outlen; inlen = fread(inbuf, 1, BUFSIZE, in); if (inlen == 0) { break; } rv = EVP_OpenUpdate(ctx, outbuf, &outlen, inbuf, inlen); if (rv != 1) { printf("Error decrypting input file\n"); goto cleanup; } fwrite(outbuf, 1, outlen, out); } rv = EVP_OpenFinal(ctx, NULL, 0); if (rv != 1) { printf("Error finalizing cipher context\n"); goto cleanup; } fclose(in); fclose(out); printf("Decryption successful\n"); cleanup: if (ctx != NULL) { EVP_CIPHER_CTX_free(ctx); } if (p12 != NULL) { PKCS12_free(p12); } if (cert != NULL) { X509_free(cert); } if (pkey != NULL) { EVP_PKEY_free(pkey); } if (p11ctx != NULL) { PKCS11_CTX_logout(p11ctx); PKCS11_CTX_uninit(p11ctx); } ENGINE_cleanup(); ERR_free_strings(); return 0; } ``` 这是一个简单的解密示例,它可以从 PKCS#12 文件中提取证书和私钥,并使用 PKCS#11 模块从智能卡中获取私钥,然后使用 OpenSSL 中的 EVP 函数进行解密操作。你可以根据自己的需求进行修改和扩展。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值