Last active
June 25, 2022 03:33
-
-
Save rickyzhang-cn/72437aa4cc0abba02f0b to your computer and use it in GitHub Desktop.
openssl demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* cli.cpp - Minimal ssleay client for Unix | |
30.9.1996, Sampo Kellomaki <[email protected]> */ | |
/* mangled to work with SSLeay-0.9.0b and OpenSSL 0.9.2b | |
Simplified to be even more minimal | |
12/98 - 4/99 Wade Scholine <[email protected]> */ | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <memory.h> | |
#include <errno.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <netdb.h> | |
#include <openssl/crypto.h> | |
#include <openssl/x509.h> | |
#include <openssl/pem.h> | |
#include <openssl/ssl.h> | |
#include <openssl/err.h> | |
#define CERTF "client.crt" | |
#define KEYF "client.key" | |
#define CACERT "ca.crt" | |
#define CHK_NULL(x) if ((x)==NULL) exit (1) | |
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); } | |
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); } | |
int main () | |
{ | |
int err; | |
int sd; | |
struct sockaddr_in sa; | |
SSL_CTX* ctx; | |
SSL* ssl; | |
X509* server_cert; | |
char* str; | |
char buf [4096]; | |
SSL_METHOD *meth; | |
SSLeay_add_ssl_algorithms(); | |
meth = SSLv23_client_method(); | |
SSL_load_error_strings(); | |
ctx = SSL_CTX_new (meth); CHK_NULL(ctx); | |
CHK_SSL(err); | |
SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); | |
SSL_CTX_load_verify_locations(ctx,CACERT,NULL); | |
if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) { | |
ERR_print_errors_fp(stderr); | |
exit(-2); | |
} | |
if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) { | |
ERR_print_errors_fp(stderr); | |
exit(-3); | |
} | |
if (!SSL_CTX_check_private_key(ctx)) { | |
printf("Private key does not match the certificate public keyn"); | |
exit(-4); | |
} | |
/* ----------------------------------------------- */ | |
/* Create a socket and connect to server using normal socket calls. */ | |
sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(sd, "socket"); | |
memset (&sa, '\0', sizeof(sa)); | |
sa.sin_family = AF_INET; | |
sa.sin_addr.s_addr = inet_addr ("127.0.0.1"); /* Server IP */ | |
sa.sin_port = htons (1111); /* Server Port number */ | |
err = connect(sd, (struct sockaddr*) &sa, | |
sizeof(sa)); CHK_ERR(err, "connect"); | |
/* ----------------------------------------------- */ | |
/* Now we have TCP conncetion. Start SSL negotiation. */ | |
ssl = SSL_new (ctx); CHK_NULL(ssl); | |
SSL_set_fd (ssl, sd); | |
err = SSL_connect (ssl); CHK_SSL(err); | |
/* Following two steps are optional and not required for | |
data exchange to be successful. */ | |
/* Get the cipher - opt */ | |
printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); | |
/* Get server's certificate (note: beware of dynamic allocation) - opt */ | |
server_cert = SSL_get_peer_certificate (ssl); CHK_NULL(server_cert); | |
printf ("Server certificate:\n"); | |
str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0); | |
CHK_NULL(str); | |
printf ("\t subject: %s\n", str); | |
OPENSSL_free (str); | |
str = X509_NAME_oneline (X509_get_issuer_name (server_cert),0,0); | |
CHK_NULL(str); | |
printf ("\t issuer: %s\n", str); | |
OPENSSL_free (str); | |
/* We could do all sorts of certificate verification stuff here before | |
deallocating the certificate. */ | |
X509_free (server_cert); | |
/* --------------------------------------------------- */ | |
/* DATA EXCHANGE - Send a message and receive a reply. */ | |
err = SSL_write (ssl, "Hello World!", strlen("Hello World!")); CHK_SSL(err); | |
err = SSL_read (ssl, buf, sizeof(buf) - 1); CHK_SSL(err); | |
buf[err] = '\0'; | |
printf ("Got %d chars:'%s'\n", err, buf); | |
SSL_shutdown (ssl); /* send SSL/TLS close_notify */ | |
/* Clean up. */ | |
close (sd); | |
SSL_free (ssl); | |
SSL_CTX_free (ctx); | |
return 0; | |
} | |
/* EOF - cli.cpp */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
INC=/usr/local/ssl/include/ | |
LIB=/usr/local/ssl/lib/ | |
all: | |
g++ -I$(INC) -L$(LIB) cli.cpp -o cli -lssl -lcrypto -ldl -fpermissive | |
g++ -I$(INC) -L$(LIB) serv.cpp -o serv -lssl -lcrypto -ldl -fpermissive | |
clean: | |
rm -rf *~ cli serv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* serv.cpp - Minimal ssleay server for Unix | |
30.9.1996, Sampo Kellomaki <[email protected]> */ | |
/* mangled to work with SSLeay-0.9.0b and OpenSSL 0.9.2b | |
Simplified to be even more minimal | |
12/98 - 4/99 Wade Scholine <[email protected]> */ | |
#include <stdio.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <memory.h> | |
#include <errno.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <netdb.h> | |
#include <openssl/rsa.h> /* SSLeay stuff */ | |
#include <openssl/crypto.h> | |
#include <openssl/x509.h> | |
#include <openssl/pem.h> | |
#include <openssl/ssl.h> | |
#include <openssl/err.h> | |
/* define HOME to be dir for key and cert files... */ | |
#define HOME "./" | |
/* Make these what you want for cert & key files */ | |
#define CERTF HOME "server.crt" | |
#define KEYF HOME "server.key" | |
#define CACERT HOME "ca.crt" | |
#define CHK_NULL(x) if ((x)==NULL) exit (1) | |
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); } | |
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); } | |
int main () | |
{ | |
int err; | |
int listen_sd; | |
int sd; | |
struct sockaddr_in sa_serv; | |
struct sockaddr_in sa_cli; | |
size_t client_len; | |
SSL_CTX* ctx; | |
SSL* ssl; | |
X509* client_cert; | |
char* str; | |
char buf [4096]; | |
SSL_METHOD *meth; | |
/* SSL preliminaries. We keep the certificate and key with the context. */ | |
SSL_load_error_strings(); | |
SSLeay_add_ssl_algorithms(); | |
meth = SSLv23_server_method(); | |
ctx = SSL_CTX_new (meth); | |
if (!ctx) { | |
ERR_print_errors_fp(stderr); | |
exit(2); | |
} | |
SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); /* whether verify the certificate */ | |
SSL_CTX_load_verify_locations(ctx,CACERT,NULL); | |
if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) { | |
ERR_print_errors_fp(stderr); | |
exit(3); | |
} | |
if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) { | |
ERR_print_errors_fp(stderr); | |
exit(4); | |
} | |
if (!SSL_CTX_check_private_key(ctx)) { | |
fprintf(stderr,"Private key does not match the certificate public key\n"); | |
exit(5); | |
} | |
/* ----------------------------------------------- */ | |
/* Prepare TCP socket for receiving connections */ | |
listen_sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(listen_sd, "socket"); | |
memset (&sa_serv, '\0', sizeof(sa_serv)); | |
sa_serv.sin_family = AF_INET; | |
sa_serv.sin_addr.s_addr = INADDR_ANY; | |
sa_serv.sin_port = htons (1111); /* Server Port number */ | |
err = bind(listen_sd, (struct sockaddr*) &sa_serv, | |
sizeof (sa_serv)); CHK_ERR(err, "bind"); | |
/* Receive a TCP connection. */ | |
err = listen (listen_sd, 5); CHK_ERR(err, "listen"); | |
client_len = sizeof(sa_cli); | |
sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len); | |
CHK_ERR(sd, "accept"); | |
close (listen_sd); | |
printf ("Connection from %lx, port %x\n", | |
sa_cli.sin_addr.s_addr, sa_cli.sin_port); | |
/* ----------------------------------------------- */ | |
/* TCP connection is ready. Do server side SSL. */ | |
ssl = SSL_new (ctx); CHK_NULL(ssl); | |
SSL_set_fd (ssl, sd); | |
err = SSL_accept (ssl); CHK_SSL(err); | |
/* Get the cipher - opt */ | |
printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); | |
/* Get client's certificate (note: beware of dynamic allocation) - opt */ | |
client_cert = SSL_get_peer_certificate (ssl); | |
if (client_cert != NULL) { | |
printf ("Client certificate:\n"); | |
str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); | |
CHK_NULL(str); | |
printf ("\t subject: %s\n", str); | |
OPENSSL_free (str); | |
str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); | |
CHK_NULL(str); | |
printf ("\t issuer: %s\n", str); | |
OPENSSL_free (str); | |
/* We could do all sorts of certificate verification stuff here before | |
deallocating the certificate. */ | |
X509_free (client_cert); | |
} else | |
printf ("Client does not have certificate.\n"); | |
/* DATA EXCHANGE - Receive message and send reply. */ | |
err = SSL_read (ssl, buf, sizeof(buf) - 1); CHK_SSL(err); | |
buf[err] = '\0'; | |
printf ("Got %d chars:'%s'\n", err, buf); | |
err = SSL_write (ssl, "I hear you.", strlen("I hear you.")); CHK_SSL(err); | |
/* Clean up. */ | |
close (sd); | |
SSL_free (ssl); | |
SSL_CTX_free (ctx); | |
return 0; | |
} | |
/* EOF - serv.cpp */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
1.证书的生成
生成server.csr和client.csr
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl genrsa -des3 -out client.key 1024
openssl req -new -key client.key -out client.csr
生成ca.crt
openssl genrsa -des3 -out ca.key 1024
openssl req -new -x509 -key ca.key -out ca.crt
通过ca.crt颁发server.crt和client.crt
openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key
openssl ca -in client.csr -out client.crt -cert ca.crt -keyfile ca.key
注:
这两条执行的时候可能因为没有指定openssl.cnf 会报错
不过没关系,我们用默认的 /etc/pki/tls/openssl.cnf 就可以
不过用默认的时候需要先执行下面两行:
touch /etc/pki/CA/index.txt
echo 00 > /etc/pki/CA/serial
2.证书的作用
证书主要用于在安全通信开始之前的认证
这个程序中client和server均需要通过证书认证彼此,这些过程主要通过OpenSSL库的API完成
client和server如果需要对对方进行认证,需要有ca.crt这个文件,因为client.crt和server.crt都是通过ca.crt签发的,ca.crt用来确认crt文件的合法性
认证完成后,client和server之间会协商一个对阵加密算法,对阵加密相关信息通过非对称加密传输,之后的数据通信是对称加密的,SSL connection using AES256-GCM-SHA384
3.SSL安全通信流程
OpenSSL初始化过程,设置证书文件和私钥文件,设置认证方式,生成SSL上下文ctx
通过Socket API获得用于网络通信的fd,通过ctx生成ssl,绑定ssl与fd
通过SSL_read()和SSL_Write()读写ssl进行安全通信