openssl证书使用说明02

来源:互联网 发布:tp3.2商城项目源码 编辑:程序博客网 时间:2024/06/15 08:30

vc测试代码,2种方式(p12和非p12)

依赖库及头文件(openssl-1.0.2m版本

libeay32.dll,libeay32.lib

ssleay32.dll,  ssleay32.lib


1.Server

#include "stdafx.h"


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>


#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")


#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "openssl/pkcs12.h"


#pragma comment(lib, "openssl/libeay32.lib")
#pragma comment(lib, "openssl/ssleay32.lib")


///////////////////////////////////////////////////////////////////////////////////////////
// 如果使用低版本vs编译的openssl库,则需要如下代码
#pragma comment(lib, "legacy_stdio_definitions.lib ")
#ifdef __cplusplus
extern "C"
#endif
FILE _iob[3] = { __acrt_iob_func(0)[0], __acrt_iob_func(1)[1], __acrt_iob_func(2)[2] };
///////////////////////////////////////////////////////////////////////////////////////////


#define LOAD_CA_CERT_FILE_FAIL -1 //加载CA证书文件失败
#define LOAD_USER_CERT_FILE_FAIL -2 //加载用户证书文件失败
#define PASSWORD_NOT_MATCH_CERT -3 //用户证书密码和证书不匹配
#define ALLOCATE_MEMORY_FAIL -4 //内存分配错误


#define SSL_INTERACT_FAIL -1 //握手中正常SSL交互失败
#define CONNECT_TO_OCSP_SERVER_FAIL -2 //连接OCSP服务器失败
#define LOAD_OCSP_CERT_FAIL -3 //加载ocsp服务器证书失败
#define CHK_OCSP_SIGNATURE_FAIL -4 //ocsp的响应与签名不符
#define PEER_CERT_NOT_EXIST_IN_OCSP -5 //OCSP服务器无对方证书记录
#define PEER_CERT_IS_REVOKED -6 //对方证书已经被撤销
#define PEER_CERT_IS_VALID 1//对方证书有效
#define SSL_HANDSHAKE_SUCCESS 1//对方证书有效,握手成功


#define USER_CERT_NOT_EXIST_IN_OCSP -7 //OCSP服务器查无此证书
#define USER_CERT_IS_REVOKED -8 //证书已经被撤销
#define GET_USER_CERT_STATUS_FAIL -9 //从服务器查询失败


const int NET_PORT = 8812;


void EXIT_IF_TRUE(bool x)
{
if (x) {
exit(2);
}
}


void OM_NetworkInit()
{
// 初始化套结字动态库
WSADATA wsd;
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
{
printf("WSAStartup failed!");
}
}


// 服务端代码
int Test_openssl_server_v2(const char* cacert, const char* sercert, const char* serkey)
{
OM_NetworkInit();


SSL_CTX     *ctx;
SSL         *ssl;


char szBuffer[1024];
int nLen;


struct sockaddr_in addr;
int len;
int nListenFd, nAcceptFd;


// 初始化
SSLeay_add_ssl_algorithms();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ERR_load_BIO_strings();


// 我们使用SSL V3,V2
EXIT_IF_TRUE((ctx = SSL_CTX_new(SSLv23_method())) == NULL);


// 要求校验对方证书
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);


// 加载CA的证书
EXIT_IF_TRUE(!SSL_CTX_load_verify_locations(ctx, cacert, NULL));


// 加载自己的证书
EXIT_IF_TRUE(SSL_CTX_use_certificate_file(ctx, sercert, SSL_FILETYPE_PEM) <= 0);


// 加载自己的私钥  
EXIT_IF_TRUE(SSL_CTX_use_PrivateKey_file(ctx, serkey, SSL_FILETYPE_PEM) <= 0);


// 判定私钥是否正确  
EXIT_IF_TRUE(!SSL_CTX_check_private_key(ctx));


// 创建并等待连接
nListenFd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in my_addr;
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(NET_PORT);
//my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//  INADDR_ANY;
if (bind(nListenFd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
int a = 2;
int b = a;
}


//
listen(nListenFd, 10);


memset(&addr, 0, sizeof(addr));
len = sizeof(addr);
nAcceptFd = accept(nListenFd, (struct sockaddr *)&addr, (int *)&len);
printf("Accept a connect from [%s:%d]\n",inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));


// 将连接付给SSL  
EXIT_IF_TRUE((ssl = SSL_new(ctx)) == NULL);
SSL_set_fd(ssl, nAcceptFd);
int n1 = SSL_accept(ssl);
if (n1 <= 0) {
const char* p1 = SSL_state_string_long(ssl);
printf("握手失败 : %s\n", p1);
}


// 进行操作  
memset(szBuffer, 0, sizeof(szBuffer));
nLen = SSL_read(ssl, szBuffer, sizeof(szBuffer));


if (nLen > 0)
{
printf("Recevie client msg : %s\n", szBuffer);


memset(szBuffer, 0, sizeof(szBuffer));
strcat_s(szBuffer, "this is from server");
SSL_write(ssl, szBuffer, strlen(szBuffer));
}
else
{
printf("Recevie client msg error\n");
}


// 释放资源  
SSL_free(ssl);
SSL_CTX_free(ctx);
closesocket(nAcceptFd);


// 释放套接字资源
WSACleanup();


return 0;
}


int Test_openssl_server_v1(const char* cacert, const char* sercert, const char* password)
{
OM_NetworkInit();


BIO* bio;
PKCS12* pkcs12User;//用户PKCS12证书结构
EVP_PKEY* pkey;//用户私钥
X509* cert; //用户证书
int nErr = 0;
SSL_CTX *sslContext = NULL;


OpenSSL_add_ssl_algorithms();


//创建SSL_CTX
const SSL_METHOD *meth;
//meth = TLSv1_2_server_method();//***采用TLS1.2协议
meth = SSLv23_method();
sslContext = SSL_CTX_new(meth);
if (NULL == sslContext) {
nErr = ALLOCATE_MEMORY_FAIL;
return NULL;
}


//加载用户证书
bio = BIO_new_file(sercert, "r");//打开p12文件
if (NULL == bio) {
nErr = LOAD_USER_CERT_FILE_FAIL;
SSL_CTX_free(sslContext);
return NULL;
}
pkcs12User = d2i_PKCS12_bio(bio, NULL);//得到p12结构
BIO_free(bio);
if (NULL == pkcs12User) {
nErr = LOAD_USER_CERT_FILE_FAIL;
SSL_CTX_free(sslContext);
return NULL;
}
if (!PKCS12_parse(pkcs12User, password, &pkey, &cert, NULL)) {//解析p12结构
nErr = PASSWORD_NOT_MATCH_CERT;
PKCS12_free(pkcs12User);
SSL_CTX_free(sslContext);
return NULL;
}
PKCS12_free(pkcs12User);
SSL_CTX_use_certificate(sslContext, cert);
SSL_CTX_use_PrivateKey(sslContext, pkey);
X509_free(cert);
EVP_PKEY_free(pkey);


//加载CA证书
if(strlen(cacert) > 0)
{
if (!SSL_CTX_load_verify_locations(sslContext, cacert, NULL)) {
nErr = LOAD_CA_CERT_FILE_FAIL;
SSL_CTX_free(sslContext);
return NULL;
}
}


//设定写模式
SSL_CTX_set_mode(sslContext, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_AUTO_RETRY);


SSL_CTX_set_options(sslContext, SSL_OP_ALL);


//设定认证模式
SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);


char szBuffer[1024];
int nLen;


struct sockaddr_in addr;
int len;
int nListenFd, nAcceptFd;


// 创建并等待连接
nListenFd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in my_addr;
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(NET_PORT);
//my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//  INADDR_ANY;
if (bind(nListenFd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
int a = 2;
int b = a;
}


//
listen(nListenFd, 10);


memset(&addr, 0, sizeof(addr));
len = sizeof(addr);
nAcceptFd = accept(nListenFd, (struct sockaddr *)&addr, (int *)&len);
printf("Accept a connect from [%s:%d]\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));


SSL         *ssl;
// 将连接付给SSL  
EXIT_IF_TRUE((ssl = SSL_new(sslContext)) == NULL);
SSL_set_fd(ssl, nAcceptFd);
int n1 = SSL_accept(ssl);
if (n1 <= 0) {
const char* p1 = SSL_state_string_long(ssl);
printf("握手失败 : %s\n", p1);
}


// 进行操作  
memset(szBuffer, 0, sizeof(szBuffer));
nLen = SSL_read(ssl, szBuffer, sizeof(szBuffer));


if (nLen > 0)
{
printf("Recevie client msg : %s\n", szBuffer);


memset(szBuffer, 0, sizeof(szBuffer));
strcat_s(szBuffer, "this is from server");
SSL_write(ssl, szBuffer, strlen(szBuffer));
}
else
{
printf("Recevie client msg error\n");
}


// 释放资源  
SSL_free(ssl);
SSL_CTX_free(sslContext);
closesocket(nAcceptFd);
closesocket(nListenFd);


// 释放套接字资源
WSACleanup();


return 0;
}


int main()
{
//Test_openssl_server_v1("cacert.crt", "user.pfx", "");// 无密码
//Test_openssl_server_v1("ca.crt", "server.pfx", "123456");// 有密码


//Test_openssl_server_v2("ca.crt", "server.crt", "server.key");// 非p12


Test_openssl_server_v1("ca.crt", "server.pfx", "123456");// 有密码


system("pause");


    return 0;
}


2.Client

#include "stdafx.h"


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>


#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")


#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "openssl/pkcs12.h"


#pragma comment(lib, "openssl/libeay32.lib")
#pragma comment(lib, "openssl/ssleay32.lib")


///////////////////////////////////////////////////////////////////////////////////////////
// 如果使用低版本vs编译的openssl库,则需要如下代码
#pragma comment(lib, "legacy_stdio_definitions.lib ")
#ifdef __cplusplus
extern "C"
#endif
FILE _iob[3] = { __acrt_iob_func(0)[0], __acrt_iob_func(1)[1], __acrt_iob_func(2)[2] };
///////////////////////////////////////////////////////////////////////////////////////////


#define LOAD_CA_CERT_FILE_FAIL -1 //加载CA证书文件失败
#define LOAD_USER_CERT_FILE_FAIL -2 //加载用户证书文件失败
#define PASSWORD_NOT_MATCH_CERT -3 //用户证书密码和证书不匹配
#define ALLOCATE_MEMORY_FAIL -4 //内存分配错误


#define SSL_INTERACT_FAIL -1 //握手中正常SSL交互失败
#define CONNECT_TO_OCSP_SERVER_FAIL -2 //连接OCSP服务器失败
#define LOAD_OCSP_CERT_FAIL -3 //加载ocsp服务器证书失败
#define CHK_OCSP_SIGNATURE_FAIL -4 //ocsp的响应与签名不符
#define PEER_CERT_NOT_EXIST_IN_OCSP -5 //OCSP服务器无对方证书记录
#define PEER_CERT_IS_REVOKED -6 //对方证书已经被撤销
#define PEER_CERT_IS_VALID 1//对方证书有效
#define SSL_HANDSHAKE_SUCCESS 1//对方证书有效,握手成功


#define USER_CERT_NOT_EXIST_IN_OCSP -7 //OCSP服务器查无此证书
#define USER_CERT_IS_REVOKED -8 //证书已经被撤销
#define GET_USER_CERT_STATUS_FAIL -9 //从服务器查询失败


const int NET_PORT = 8812;


int getpid()
{
return 111;
}


void EXIT_IF_TRUE(bool x)
{
if (x) {
exit(2);
}
}


void OM_NetworkInit()
{
// 初始化套结字动态库
WSADATA wsd;
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
{
printf("WSAStartup failed!");
}
}


int Test_openssl_client_v2(const char* cacert, const char* cltcert, const char* cltkey)
{
OM_NetworkInit();


SSL_CTX     *ctx;
SSL         *ssl;


int nFd;
int nLen;
char szBuffer[1024];


// 初始化
SSLeay_add_ssl_algorithms();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ERR_load_BIO_strings();


// 我们使用SSL V3,V2
EXIT_IF_TRUE((ctx = SSL_CTX_new(SSLv23_method())) == NULL);


// 要求校验对方证书
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);


// 加载CA的证书
EXIT_IF_TRUE(!SSL_CTX_load_verify_locations(ctx, cacert, NULL));


// 加载自己的证书
EXIT_IF_TRUE(SSL_CTX_use_certificate_file(ctx, cltcert, SSL_FILETYPE_PEM) <= 0);


// 加载自己的私钥
EXIT_IF_TRUE(SSL_CTX_use_PrivateKey_file(ctx, cltkey, SSL_FILETYPE_PEM) <= 0);


// 判定私钥是否正确
EXIT_IF_TRUE(!SSL_CTX_check_private_key(ctx));


// new
// 创建连接
nFd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in dest;
memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(NET_PORT);
dest.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(nFd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
perror("Connect ");
exit(errno);
}


// 将连接付给SSL
EXIT_IF_TRUE((ssl = SSL_new(ctx)) == NULL);
SSL_set_fd(ssl, nFd);


int n1 = SSL_connect(ssl);
if (n1 <= 0) {
int n2 = SSL_get_error(ssl, n1);


const char* p1 = SSL_state_string(ssl);


printf("握手失败 : %s\n", p1);
}


// 进行操作
sprintf(szBuffer, "this is from client %d", getpid());
int nWriten = SSL_write(ssl, szBuffer, strlen(szBuffer));


// 释放资源
memset(szBuffer, 0, sizeof(szBuffer));
nLen = SSL_read(ssl, szBuffer, sizeof(szBuffer));
if (nLen > 0)
{
printf("Recevie server msg : %s\n", szBuffer);
}
else
{
printf("Recevie server msg error\n");
}


SSL_free(ssl);
SSL_CTX_free(ctx);
closesocket(nFd);


// 释放套接字资源
WSACleanup();


return 0;
}


int Test_openssl_client_v1(const char* cacert, const char* cltcert, const char* password)
{
OM_NetworkInit();


BIO* bio;
PKCS12* pkcs12User;//用户PKCS12证书结构
EVP_PKEY* pkey;//用户私钥
X509* cert; //用户证书
int nErr = 0;
SSL_CTX *sslContext = NULL;
OpenSSL_add_ssl_algorithms();


const SSL_METHOD *meth;
meth = SSLv23_method();
sslContext = SSL_CTX_new(meth);


if (NULL == sslContext) {
nErr = ALLOCATE_MEMORY_FAIL;
return NULL;
}


//加载用户证书
bio = BIO_new_file(cltcert, "r");//打开p12文件
if (NULL == bio) {
nErr = LOAD_USER_CERT_FILE_FAIL;
SSL_CTX_free(sslContext);
return NULL;
}
pkcs12User = d2i_PKCS12_bio(bio, NULL);//得到p12结构
BIO_free(bio);
if (NULL == pkcs12User) {
nErr = LOAD_USER_CERT_FILE_FAIL;
SSL_CTX_free(sslContext);
return NULL;
}
if (!PKCS12_parse(pkcs12User, password, &pkey, &cert, NULL)) {//解析p12结构
nErr = PASSWORD_NOT_MATCH_CERT;
PKCS12_free(pkcs12User);
SSL_CTX_free(sslContext);
return NULL;
}
PKCS12_free(pkcs12User);
SSL_CTX_use_certificate(sslContext, cert);
SSL_CTX_use_PrivateKey(sslContext, pkey);
X509_free(cert);
EVP_PKEY_free(pkey);


//加载CA证书
if (strlen(cacert) > 0)
{
if (!SSL_CTX_load_verify_locations(sslContext, cacert, NULL)) {
nErr = LOAD_CA_CERT_FILE_FAIL;
SSL_CTX_free(sslContext);
return NULL;
}
}


//设定写模式
SSL_CTX_set_mode(sslContext, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_AUTO_RETRY);


SSL_CTX_set_options(sslContext, SSL_OP_ALL);


//设定认证模式
SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);


// new
// 创建连接
int nFd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in dest;
memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(NET_PORT);
dest.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(nFd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
perror("Connect ");
exit(errno);
}


SSL         *ssl;
// 将连接付给SSL
EXIT_IF_TRUE((ssl = SSL_new(sslContext)) == NULL);
SSL_set_fd(ssl, nFd);


int n1 = SSL_connect(ssl);
if (n1 <= 0) {
int n2 = SSL_get_error(ssl, n1);


const char* p1 = SSL_state_string(ssl);


printf("握手失败 : %s\n", p1);
}


char szBuffer[1024];
int nLen;


// 进行操作
sprintf(szBuffer, "this is from client %d", getpid());
int nWriten = SSL_write(ssl, szBuffer, strlen(szBuffer));


// 释放资源
memset(szBuffer, 0, sizeof(szBuffer));
nLen = SSL_read(ssl, szBuffer, sizeof(szBuffer));

if (nLen > 0)
{
printf("Recevie server msg : %s\n", szBuffer);
}
else
{
printf("Recevie server msg error\n");
}


SSL_free(ssl);
SSL_CTX_free(sslContext);
closesocket(nFd);


// 释放套接字资源
WSACleanup();


return 0;
}


int main()
{
//Test_openssl_client_v1("cacert.crt", "public.pfx", "");// 无密码
//Test_openssl_client_v1("ca.crt", "client.pfx", "123456");// 有密码


//Test_openssl_client_v2("ca.crt", "client.crt", "client.key");// 非p12


Test_openssl_client_v1("ca.crt", "client.pfx", "123456");// 无密码


system("pause");


    return 0;
}