openssl 自定义生成证书和私钥并使用

这里以生成客户端证书和密钥文件为例,目的是建立一个加密的安全的tcp连接

1 生成密钥文件

命令:openssl genrsa -des3 -out PK.pem 2048 

会提示输入密钥短语,输入后还会让输入确认

2 生成证书文件

openssl req -new -x509 -key PK.pem -out CA.pem -days 365


验证代码片段:

// logout

#include <WinSock2.h>
#include "openssl/ossl_typ.h"
#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "KKSock.h"

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

class CSSLClient
{
public:
	CSSLClient();

	~CSSLClient();

	bool DoConnect();

	void Reset(); 

	int Hex2Chr(char *DstStr,char *HexStr,int HexLen);

	int Chr2Hex(char c);

	int CreateMessage(char *binaryMessageBuff,char *deviceTokenBinary, char *payloadBuff, size_t payloadLength);

	void InitSSL();

private:
	SSL_CTX         *m_pctx;
	SSL             *m_pssl;
	const SSL_METHOD      *m_pmeth;
	CKKSock         m_tcpSocket;
};


// 代码里的CKKSock为一个封装的select模型的类,也可以使用原生的socket,执行阻塞或非阻塞操作

</pre><pre name="code" class="cpp">#include "SSLClient.h"
#include <Windows.h>
#include <string>
using namespace std;

CSSLClient::CSSLClient()
{
	m_pssl = NULL;
	m_pctx = NULL;
	m_pmeth = NULL;
	m_tcpSocket.InitSock();
}

CSSLClient::~CSSLClient()
{

}

void CSSLClient::Reset() 
{       
	if(m_pssl)     
	{         
		SSL_shutdown(m_pssl);
		SSL_free(m_pssl);
		m_pssl = NULL;     
	}     
	if(m_pctx)     
	{         
		SSL_CTX_free(m_pctx);
		m_pctx = NULL;     
	}    
	m_tcpSocket.Close();
} 

void CSSLClient::InitSSL()
{
	SSL_library_init();
	SSL_load_error_strings();
}

bool CSSLClient::DoConnect()
{
	//Reset();
	int nErr;
	bool bRet = false;
	do 
	{
		m_pmeth = SSLv23_client_method();// create ssl method
		m_pctx = SSL_CTX_new(m_pmeth);
		if (!m_pctx)
			break;

		SSL_CTX_set_options(m_pctx, SSL_OP_ALL);

		char szPath[MAX_PATH + 1] = {0};
		if (GetModuleFileName(NULL, szPath, MAX_PATH) == 0)
		{
			break;
		}
		for (int i = strlen(szPath); i > 0; i--)
		{
			if (szPath[i - 1] == '\\')
			{
				szPath[i - 1] = '\0';
				break;
			}
		}
		char szCAPath[MAX_PATH + 1] = {0};
		char szPKPath[MAX_PATH + 1] = {0};
		strcpy(szCAPath, szPath);
		strcpy(szPKPath, szPath);
		strcat(szCAPath, "\\CA.pem");
		strcat(szPKPath, "\\PK.pem");
		if (!SSL_CTX_use_certificate_file(m_pctx, szCAPath, SSL_FILETYPE_PEM)) 
			break;
		
		// 验证密码文件
		BIO* pKeyBuff = BIO_new_file(szPKPath, "r");
		if(NULL == pKeyBuff)
		{
			break;
		}

		//SSL_CTX_set_default_passwd_cb_userdata
		char szPwd[16] = "111111";
		EVP_PKEY *pkey = PEM_read_bio_PrivateKey(pKeyBuff, NULL, NULL, szPwd);
		if(pkey==NULL)
		{
			break;
		}

		int nRetTmp = SSL_CTX_use_PrivateKey(m_pctx, pkey);
		if (nRetTmp <= 0)
		{
			break;
		}

		bool bConnect = m_tcpSocket.ConnectEx("10.1.8.26", 10156, 3000);
		if (!bConnect)
			break;

		/* An SSL structure is created */
		m_pssl = SSL_new(m_pctx);
		if(!m_pssl)
		{
			break;
		}

		if(SSL_get_verify_result(m_pssl) != X509_V_OK)
		{
			//X509证书无效
			break;
		}

		/* Assign the socket into the SSL structure (SSL and socket without BIO) */
		SSL_set_fd(m_pssl, m_tcpSocket.m_sock);

		SSL_set_mode(m_pssl, SSL_MODE_AUTO_RETRY);

		/* Perform SSL Handshake on the SSL client */
		DWORD dwNow = GetTickCount();
		while ((nRetTmp = SSL_connect(m_pssl)) <= 0)
		{
			int nLastErr = SSL_get_error(m_pssl, nRetTmp);
			if (nLastErr != SSL_ERROR_WANT_READ && nLastErr != SSL_ERROR_WANT_WRITE)
			{
				char szErrMsg[1024] = {0};
				ERR_error_string(ERR_get_error(), szErrMsg);
				printf("err msg: %s\n", szErrMsg);

				printf("lastErr: %d \n", nLastErr);
				break;
			}
			Sleep(10);
		}
		printf("nRetTmp = %d\n", nRetTmp); //if nRetTmp > 0 means connect success
		bRet = true;

		char szReadBuffer[2048] = {0};
		while (true)
		{
			//
			memset(szReadBuffer, 0, sizeof(szReadBuffer));
			nRetTmp = SSL_read(m_pssl, szReadBuffer, 2048);  // read test
			if (nRetTmp <= 0)
			{
				char szErrMsg[1024] = {0};
				ERR_error_string(ERR_get_error(), szErrMsg);
				printf("err msg: %s\n", szErrMsg);

				int nLastErr = SSL_get_error(m_pssl, nRetTmp);
				if (nLastErr != SSL_ERROR_WANT_READ && nLastErr != SSL_ERROR_WANT_WRITE)
				{
					//close connection
					getchar();
					break;
				}
			}
			else
			{

			}
			Sleep(100);
		}

	} while (false);
	
	return bRet;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值