相关代码:
server端:
-
#include "stdafx.h"
-
#include <winsock2.h>
-
#include <conio.h>
-
#include <stdio.h>
-
#include "openssl/x509.h"
-
#include "openssl/ssl.h"
-
#include "openssl/err.h"
-
-
#define MSGLENGTH 1024
-
#define PORT 8888
-
#define CACERT "./private/ca.crt"
-
#define SVRCERTF "./certs/server.crt"
-
#define SVRKEYF "./private/server.key"
-
-
#pragma comment(lib, "wsock32.lib")
-
#pragma comment(lib, "libeay32.lib")
-
#pragma comment(lib, "ssleay32.lib")
-
-
int _tmain(int argc, _TCHAR* argv[])
-
{
-
WSADATA wsaData;
-
WSAStartup(MAKEWORD(2,2), &wsaData);
-
SOCKET sock;
-
SSL_METHOD *meth;
-
SSL_CTX* ctx;
-
SSL* ssl;
-
//SSL初始化
-
OpenSSL_add_ssl_algorithms();
-
//SSL错误信息初始化
-
SSL_load_error_strings();
-
//创建本次会话所使用的协议
-
meth = (SSL_METHOD *)TLSv1_server_method();
-
//申请SSL会话的环境
-
ctx = SSL_CTX_new(meth);
-
if (NULL == ctx)
-
exit(1);
-
-
//设置会话的握手方式并加载CA证书
-
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
-
if (!SSL_CTX_load_verify_locations(ctx, CACERT, NULL))
-
{
-
printf("%d \n\n下载CA 证书出错!\n", SSL_CTX_load_verify_locations(ctx, CACERT, NULL));
-
exit(-1);
-
}
-
//加载服务器端的证书
-
if (!SSL_CTX_use_certificate_file(ctx, SVRCERTF, SSL_FILETYPE_PEM)) {
-
ERR_print_errors_fp(stderr);
-
exit(1);
-
}
-
//加载服务器端的私钥
-
if (!SSL_CTX_use_PrivateKey_file(ctx, SVRKEYF, SSL_FILETYPE_PEM)) {
-
ERR_print_errors_fp(stderr);
-
exit(1);
-
}
-
//检查服务器端的证书和私钥是否匹配
-
if (!SSL_CTX_check_private_key(ctx)) {
-
printf("\n\n私钥与证书公钥不匹配!\n");
-
exit(1);
-
}
-
-
//加密方式
-
SSL_CTX_set_cipher_list(ctx, "RC4-MD5");
-
//处理握手多次
-
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
-
-
/*以下是正常的TCP socket建立过程.............................. */
-
sock = socket(AF_INET, SOCK_STREAM, 0);
-
if (sock == INVALID_SOCKET) {
-
printf("\n\nSOCKET有问题. \n");
-
return 0;
-
}
-
-
sockaddr_in addr;
-
memset(&addr, '\0', sizeof(addr));
-
addr.sin_family = AF_INET;
-
addr.sin_port = htons(PORT); /*
Server Port number */
-
addr.sin_addr.s_addr = INADDR_ANY;
-
-
//绑定sock
-
int nResult = bind(sock, (sockaddr *)&addr, sizeof(addr));
-
if (nResult == SOCKET_ERROR) {
-
printf("\n\n绑定SOCKET有问题.\n");
-
return 0;
-
}
-
printf("\n**************************************\n");
-
printf("\n服务器启动成功,端口:%d\n\n等待连接.....\n", PORT);
-
-
/*接受TCP链接*/
-
sockaddr_in sa_cli;
-
int err = listen(sock, 5);
-
if (-1 == err)
-
exit(1);
-
int client_len = sizeof(sa_cli);
-
int ss = accept(sock, (struct sockaddr *) &sa_cli, &client_len);
-
if (ss == -1) {
-
exit(1);
-
}
-
closesocket(sock);
-
printf("\n连接端口:%d, port %d\n", sa_cli.sin_addr.s_addr, sa_cli.sin_port);
-
/* TCP 链接已建立.开始SSL 握手过程.......................... */
-
//绑定套接字
-
ssl = SSL_new(ctx);
-
if (NULL == ssl)
-
exit(1);
-
if (!SSL_set_fd(ssl, ss)) {
-
printf("\n连接失败\n");
-
exit(1);
-
}
-
//SSL握手
-
//SSL_accept(ssl);
-
int k = SSL_accept(ssl);
-
if ( k != 1) {
-
printf("%d\n", k);
-
printf("\n连接失败\n");
-
exit(1);
-
}
-
//进行信息验证
-
X509 *client_cert;
-
client_cert = SSL_get_peer_certificate(ssl);
-
-
printf("\n发现客户端尝试连接\n");
-
if (client_cert != NULL) {
-
printf ("\n客服端证书:\n");
-
//读取证书subject名并显示
-
char *str = X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0);
-
if (NULL == str) {
-
printf("\n认证出错!\n");
-
exit(1);
-
}
-
printf("\n主题:%s\n", str);
-
//读取证书的issuer名并显示
-
str = X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0);
-
if (NULL == str) {
-
printf("\n证书名为空\n");
-
exit(1);
-
}
-
printf("\n颁发者:%s\n", str);
-
printf("\n连接成功\n");
-
-
X509_free (client_cert);/*如不再需要,需将证书释放*/
-
OPENSSL_free(str);
-
}
-
else {
-
printf("\n找不到客户端的认证证书\n");
-
exit(1);
-
}
-
-
char buf[MSGLENGTH];
-
SSL_write(ssl, "\n服务器连接成功!\n", strlen("\n服务器连接成功!\n"));
-
printf("\n监听客服端:\n\n");
-
while (1) {
-
err = SSL_read(ssl, buf, sizeof(buf));
-
buf[err] = '\0';
-
if (!strcmp(buf, "退出"))
-
{
-
//关闭套接字
-
SSL_shutdown(ssl);
-
SSL_free(ssl);
-
SSL_CTX_free(ctx);
-
WSACleanup();
-
getchar();
-
break;
-
}
-
else printf(">> %s\n", buf);
-
}
-
-
return 0;
- }
客户端代码:
-
//client
-
#include <winsock2.h>
-
//#include <winsock.h>
-
#include <conio.h>
-
#include <stdio.h>
-
#include "openssl/x509.h"
-
#include "openssl/ssl.h"
-
#include "openssl/err.h"
-
#include "openssl/rand.h"
-
#include <openssl/applink.c>
-
-
#define PORT 8888
-
#define SERVER "127.0.0.1"
-
//#define SERVER "172.31.32.176"
-
#define CACERT "./private/ca.crt"
-
#define MYCERTF "./certs/client.crt"
-
#define MYKEYF "./private/client.key"
-
#define MSGLENGTH 1024
-
-
#pragma comment(lib, "wsock32.lib")
-
#pragma comment(lib, "libeay32.lib")
-
#pragma comment(lib, "ssleay32.lib")
-
-
int _tmain(int argc, _TCHAR* argv[])
-
{
-
WSADATA wsadata;
-
WSAStartup(MAKEWORD(2,2), &wsadata);
-
sockaddr_in sin;
-
int seed_int[100]; /*存放随机序列*/
-
-
SSL *ssl;
-
const SSL_METHOD *meth;
-
SSL_CTX *ctx;
-
-
//SSL初始化
-
OpenSSL_add_ssl_algorithms();
-
//SSL错误信息初始化
-
SSL_load_error_strings();
-
-
//创建本次会话所使用的协议
-
meth = TLSv1_client_method();
-
//申请SSL会话的环境
-
ctx = SSL_CTX_new(meth);
-
if (NULL == ctx)
-
exit(1);
-
-
//设置会话的握手方式并加载CA证书
-
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
-
if (!SSL_CTX_load_verify_locations(ctx, CACERT, NULL))
-
{
-
printf("%d\n 下载CA 证书出错!\n", SSL_CTX_load_verify_locations(ctx, CACERT, NULL));
-
exit(-1);
-
}
-
-
//加载自己的证书
-
if (!SSL_CTX_use_certificate_file(ctx, MYCERTF, SSL_FILETYPE_PEM)) {
-
ERR_print_errors_fp(stdout);
-
printf("\n错误1 %d\n", SSL_CTX_use_certificate_file(ctx, MYCERTF, SSL_FILETYPE_PEM));
-
exit(1);
-
}
-
//加载自己的私钥
-
if (!SSL_CTX_use_PrivateKey_file(ctx, MYKEYF, SSL_FILETYPE_PEM)) {
-
ERR_print_errors_fp(stderr);
-
exit(1);
-
}
-
-
//检查自己的证书和私钥是否匹配
-
if (!SSL_CTX_check_private_key(ctx)) {
-
printf("\n私钥与证书公钥不匹配!\n");
-
exit(1);
-
}
-
-
/*构建随机数生成机制,WIN32平台必需*/
-
srand((unsigned)time(NULL));
-
for (int i = 0; i < 100; i++)
-
seed_int[i] = rand();
-
RAND_seed(seed_int, sizeof(seed_int));
-
-
//加密方式
-
SSL_CTX_set_cipher_list(ctx, "RC4-MD5");
-
//处理握手多次
-
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
-
-
/*以下是正常的TCP socket建立过程.............................. */
-
SOCKET sock;
-
//printf("Begin tcp socket...\n");
-
sock = socket(AF_INET, SOCK_STREAM, 0);
-
if (sock == INVALID_SOCKET) {
-
printf("\nSOCKET有问题. \n");
-
}
-
-
memset(&sin, '\0', sizeof(sin));
-
sin.sin_family = AF_INET;
-
sin.sin_addr.s_addr = inet_addr(SERVER); /*
Server IP */
-
sin.sin_port = htons(PORT); /*
Server Port number */
-
-
int icnn = connect(sock, (sockaddr *)&sin, sizeof(sin));
-
if (icnn == SOCKET_ERROR) {
-
printf("\n连不上服务器\n", GetLastError());
-
exit(1);
-
}
-
-
/* TCP 链接已建立.开始SSL 握手过程.......................... */
-
//绑定套接字
-
ssl = SSL_new(ctx);
-
if (NULL == ssl)
-
exit(1);
-
if (0 >= SSL_set_fd(ssl, sock)) {
-
printf("\n连接失败!\n");
-
exit(1);
-
}
-
//SSL握手
-
//SSL_connect(ssl);
-
printf("\n正在连接服务器......\n");
-
int k = SSL_connect(ssl);
-
if (k != 1) {
-
printf("%d\n", k);
-
printf("\nSSL connect fail!\n");
-
exit(1);
-
}
-
printf("\n连接服务器成功\n");
-
-
char sendmsg[MSGLENGTH] = "\0";
-
char revmsg[MSGLENGTH] = "\0";
-
-
int err = SSL_read(ssl, revmsg, sizeof(revmsg));
-
revmsg[err] = '\0';
-
printf("%s\n", revmsg);
-
-
while (1) {
-
printf("\n请输入所要发送的数据:\n\n>> ");
-
gets(sendmsg);
-
SSL_write(ssl, sendmsg, strlen(sendmsg));
-
printf("\n发送消息 %s 成功!\n", sendmsg);
-
if (!strcmp(sendmsg, "exit"))
-
{
-
//关闭套接字
-
//sleep(1);
-
SSL_shutdown(ssl);
-
SSL_free(ssl);
-
SSL_CTX_free(ctx);
-
closesocket(sock);
-
WSACleanup();
-
getchar();
-
break;
-
}
-
}
-
return 0;
- }
本文介绍了一个基于SSL/TLS协议实现的安全通信案例,详细展示了服务器端与客户端的代码实现,包括证书验证、密钥交换及数据传输等关键步骤。
937

被折叠的 条评论
为什么被折叠?



