Openssl Server C Demo

Posted 小米渣的逆袭

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Openssl Server C Demo相关的知识,希望对你有一定的参考价值。

证书生成

rootPath=$(cd "$(dirname "$0")"; pwd)
#删除打包数据目录
OUTPUT=$rootPath/build
rm -drf $OUTPUT
mkdir $OUTPUT 

# 生成CA证书
echo "-----------------------------生成CA证书----------------------------------"
name="standard_ca"
openssl genrsa -out $OUTPUT/$name.key 2048  
openssl req -new -key $OUTPUT/$name.key -out $OUTPUT/$name.req -subj /C=CN/ST=JS/L=NJ/O=NJ/CN="127.0.0.1"
openssl x509 -req -days 3650 -in $OUTPUT/$name.req -extfile ./openssl.cnf -extensions v3_ca -signkey $OUTPUT/$name.key -out $OUTPUT/$name.cer
openssl x509 -in $OUTPUT/$name.cer -text -noout  
rm -f $OUTPUT/$name.req

echo "-----------------------------Server签名证书----------------------------------"
# Server签名证书
name="standard_server_sign"
openssl genrsa -out $OUTPUT/$name.key 2048  
openssl req -new -key $OUTPUT/$name.key -out $OUTPUT/$name.req -subj /C=CN/ST=JS/L=NJ/O=NJ/CN="127.0.0.1"
openssl x509 -req -days 3650 -in $OUTPUT/$name.req -extfile ./openssl.cnf -extensions v3_req -CA $OUTPUT/standard_ca.cer -CAkey $OUTPUT/standard_ca.key -set_serial 1000000001 -extfile $rootPath/openssl.cnf -out $OUTPUT/$name.cer  
openssl x509 -in $OUTPUT/$name.cer -text -noout  
rm -f $OUTPUT/$name.req


echo "-----------------------------客户端证书----------------------------------"
# 客户端证书
name="standard_client"
openssl genrsa -out $OUTPUT/$name.key 2048  
openssl req -new -key $OUTPUT/$name.key -out $OUTPUT/$name.req -subj /C=CN/ST=JS/L=NJ/O=NJ/CN="127.0.0.1"
openssl x509 -req -days 3650 -in $OUTPUT/$name.req -extfile ./openssl.cnf -extensions v3_req -CA $OUTPUT/standard_ca.cer -CAkey $OUTPUT/standard_ca.key -set_serial 1000000001 -extfile $rootPath/openssl.cnf -out $OUTPUT/$name.cer  
openssl x509 -in $OUTPUT/$name.cer -text -noout  
rm -f $OUTPUT/$name.req

服务端代码

// HttpSvrDemo.cpp : 定义控制台应用程序的入口点。
//


#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib,"Ws2_32.lib")
#pragma comment(lib,"User32.lib")
#pragma comment(lib,"Advapi32.lib")
#pragma comment(lib,"Gdi32.lib")
#include <openssl\\\\ssl.h>
//#pragma comment(lib,"libeay32.lib")
//#pragma comment(lib,"ssleay32.lib")

#pragma warning(disable: 4996)

#define CERTF   "C:\\\\Users\\\\wjr\\\\Downloads\\\\standard_server_sign.cer"
#define KEYF    "C:\\\\Users\\\\wjr\\\\Downloads\\\\standard_server_sign.key"
#define CA		"C:\\\\Users\\\\wjr\\\\Downloads\\\\standard_ca.cer"



// 这是一个 https 服务端 Demo
int main()
	
	WSADATA wsaData;
	sockaddr_in service =  0 ;
	SOCKET ListenSocket = INVALID_SOCKET;
	SOCKET AcceptSocket = INVALID_SOCKET;

	// 1.初始化 WSA 相关函数
	int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (err != 0)
	
		/* Tell the user that we could not find a usable */
		/* Winsock DLL.                                  */
		printf("WSAStartup failed with error: %d\\n", err);
		return -1;
	

	// 2.初始化静态库 加载错误字符 加载算法库
	SSL_library_init();
	SSL_load_error_strings();
	SSLeay_add_ssl_algorithms();

	// 3.绑定本地端口并监听 ---- 摘自 MSDN
	ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (ListenSocket == INVALID_SOCKET)
	
		wprintf(L"socket function failed with error: %ld\\n", WSAGetLastError());
			
	
	//----------------------
	// The sockaddr_in structure specifies the address family,
	// IP address, and port for the socket that is being bound.
	service.sin_family = AF_INET;
	service.sin_addr.s_addr = inet_addr("127.0.0.1");
	service.sin_port = htons(28801);

	int iResult = bind(ListenSocket, (SOCKADDR*)&service, sizeof(service));
	if (iResult == SOCKET_ERROR)
	
		wprintf(L"bind function failed with error %d\\n", WSAGetLastError());			
	
	if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR)
	
		wprintf(L"listen function failed with error: %d\\n", WSAGetLastError());			
	
	wprintf(L"Listening on socket...\\n");

	// 4.等待建立连接
	while (TRUE)
			
		AcceptSocket = accept(ListenSocket, NULL, NULL);
		if (AcceptSocket == INVALID_SOCKET)
		
			wprintf(L"accept failed with error: %ld\\n", WSAGetLastError());
			closesocket(ListenSocket);
			WSACleanup();
			return -1;
		
		else
		
			wprintf(L"Client connected.\\n");
		

		// 4.1将套接字与证书绑定

		const SSL_METHOD* meth = SSLv23_server_method();
		SSL_CTX* ctx = SSL_CTX_new(meth);

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

		加载CA
		if (SSL_CTX_load_verify_locations(ctx, CA, NULL) <= 0)
		
			wprintf(L"SSL_CTX_use_certificate_file failed.\\n");
			closesocket(AcceptSocket);
			continue;
		

		if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0)
		
			wprintf(L"SSL_CTX_use_certificate_file failed.\\n");
			closesocket(AcceptSocket);
			continue;
		

		if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0)
		
			wprintf(L"SSL_CTX_use_PrivateKey_file failed.\\n");
			closesocket(AcceptSocket);
			continue;
		
		if (SSL_CTX_check_private_key(ctx) <= 0) 
		
			wprintf(L"Private key does not match the certificate public key\\n");
			closesocket(AcceptSocket);
			continue;
		
		SSL* ssl = SSL_new(ctx);
		SSL_set_fd(ssl, AcceptSocket);
		if (SSL_accept(ssl) == -1)
		
			int n = SSL_get_error(ssl, -1);					
			const char* p1 = SSL_state_string_long(ssl);
			printf("错误代码:%s\\r\\n", SSL_state_string_long(ssl));
			closesocket(AcceptSocket);
			continue;
		

		// 4.2从SSL套接字读取数据
		char  buf[4096] =  0 ;
		int sslRead = SSL_read(ssl, buf, 4095);		
		printf("%s\\n", buf);

		// 4.3往SSL套接字写入数据
		char szTemp[400] = "HTTP/1.1 200 OK\\r\\nServer: bfe/1.0.8.14\\r\\nDate: Mon, 29 Feb 2016 06:21:46 GMT\\r\\nContent-Type: text/html\\r\\nContent-Length: 70\\r\\nConnection: keep-alive\\r\\n\\r\\n<html>\\r\\n<head><title>200 Ok</title></head><body> 200 OK </body></html>";
		int nCount = strlen(szTemp);
		int nRet = 0;
		do
		
			nRet += SSL_write(ssl, szTemp, nCount);
			if (nRet >= nCount)
			
				break;
			
		 while (true);		
		closesocket(AcceptSocket);
		AcceptSocket = INVALID_SOCKET;
	
	closesocket(ListenSocket);
	return 0;



 

以上是关于Openssl Server C Demo的主要内容,如果未能解决你的问题,请参考以下文章

Openssl Server C Demo

OpenSSL证书生成参考

OpenSSL证书生成参考

c udp server client demo --待调试

c tcp sockt server client -- demo

java翻译lua+c+openssl签名项目