Skip to content

Instantly share code, notes, and snippets.

@longbuilder
Last active September 9, 2017 09:03
Show Gist options
  • Select an option

  • Save longbuilder/9457809 to your computer and use it in GitHub Desktop.

Select an option

Save longbuilder/9457809 to your computer and use it in GitHub Desktop.
ssl_demo
一、生成用于签发client和server证书的ca根证书。
mkdir -p ca
#生成CA私钥,1024位RSA私钥,这里简单起见,没有对私钥进行加密。
openssl genrsa -out ca/ca.key 1024
#生成ca的证书请求文件
openssl req -new -out ca/ca.csr -key ca/ca.key
#用CA私钥进行自签名,生成ca的证书文件
openssl x509 -req -in ca/ca.csr -out ca/ca.cert -signkey ca/ca.key -days 365
days参数指定过期时间
二、利用ca签发生成客户端证书。
mkdir -p client
#生成client私钥
openssl genrsa -out client/client.key 1024
#生成client证书请求文件
openssl req -new -out client/client.csr -key client/client.key
#ca签发client证书
openssl x509 -req -in client/client.csr -out client/client.crt -signkey client/client.key \
-CA ca/ca.cert -CAkey ca/ca.key -CAcreateserial -days 365
三、利用ca签发生成服务端证书。
mkdir -p server
#生成server私钥
openssl genrsa -out server/server.key 1024
#生成server证书请求文件
openssl req -new -out server/server.csr -key server/server.key
#利用ca签发server端证书
openssl x509 -req -in server/server.csr -out server/server.crt -signkey server/server.key \
-CA ca/ca.cert -CAkey ca/ca.key -CAcreateserial -days 365
—END—
到目前为止,我们生成了ssl通信所需要的全部证书和私钥,目录结构如下:
./ca
|– ca.key  ca私钥
`– ca.cert  ca自签名证书
./client
|– client.key  client私钥
`– client.cert  client证书
./server
|– server.key  server私钥
`– server.cert  server证书
#include <stdio.h>
#include <errno.h>
#include <unistd.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>
int analyse_ssl_error(const SSL* ssl,int err_code )
{
switch(SSL_get_error(ssl,err_code))
{
case SSL_ERROR_NONE:
printf("No error\n");
break;
case SSL_ERROR_ZERO_RETURN:
printf("SSL_ERROR_ZERO_RETURN\n");
break;
case SSL_ERROR_WANT_READ:
printf("SSL_ERROR_WANT_READ\n");
break;
case SSL_ERROR_WANT_WRITE:
printf("SSL_ERROR_WANT_WRITE\n");
break;
case SSL_ERROR_WANT_CONNECT:
printf("SSL_ERROR_WANT_CONNECT\n");
break;
case SSL_ERROR_WANT_ACCEPT:
printf("SSL_ERROR_WANT_ACCEPT\n");
break;
case SSL_ERROR_WANT_X509_LOOKUP:
printf("SSL_ERROR_WANT_X509_LOOKUP\n");
break;
case SSL_ERROR_SYSCALL:
printf("SSL_ERROR_SYSCALL:%s\n", strerror(errno));
if (errno == EPIPE)
{
return 1;
}
break;
case SSL_ERROR_SSL:
printf("SSL_ERROR_SSL\n");
break;
default:
printf("unkown error\n");
break;
}
return 0;
};
SSL_CTX* init_ssl_ctx(const char *certfile, const char *keyfile, const char *cafile)
{
/* Load encryption & hashing algorithms for the SSL program */
SSL_library_init();
/* Load the error strings for SSL & CRYPTO APIs */
SSL_load_error_strings();
/* Create an SSL_METHOD structure (choose an SSL/TLS protocol version) */
const SSL_METHOD *meth = SSLv23_client_method();
/* Create an SSL_CTX structure */
SSL_CTX *ctx = SSL_CTX_new (meth);
if (NULL == ctx)
{
printf("Could not new SSL_CTX\n");
return NULL;
}
/* Load the CA cert file*/
if (SSL_CTX_load_verify_locations(ctx, cafile, NULL) <= 0)
{
printf("Could not load ca cert file\n");
}
/* Load the client certificate into the SSL_CTX structure */
if (SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM) <= 0)
{
printf("Could not use certificate file\n");
}
/* Load the private-key corresponding to the client certificate */
if (SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM) <= 0)
{
printf("Could not use private key file\n");
}
/* Check if the client certificate and private-key matches */
if (!SSL_CTX_check_private_key(ctx))
{
printf("Private key does not match certfile\n");
}
return ctx;
}
int main ()
{
SSL_CTX *ctx = init_ssl_ctx("./PEMS/client/client.crt",
"./PEMS/client/client.key",
"./PEMS/ca/ca.cert");
if (NULL == ctx)
{
exit(-1);
}
/* Create a socket and connect to server using normal socket calls. */
int sd = socket (AF_INET, SOCK_STREAM, 0);
if (sd < 0)
{
perror("New socket error");
exit(-1);
}
struct sockaddr_in sa;
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 */
int err = connect(sd, (struct sockaddr*) &sa,
sizeof(sa));
if (err < 0)
{
perror("Could not conncet to server");
exit(-1);
}
/* Now we have TCP conncetion. Start SSL negotiation. */
SSL* ssl = SSL_new (ctx);
if (NULL == ssl)
{
printf("Could not create new SSL\n");
exit(-1);
}
SSL_set_fd (ssl, sd);
err = SSL_connect (ssl);
if (err <= 0)
{
analyse_ssl_error(ssl, err);
exit(-1);
}
/* --------------------------------------------------- */
/* DATA EXCHANGE - Send a message and receive a reply. */
err = SSL_write (ssl, "Hello World!", strlen("Hello World!"));
if (err <= 0)
{
analyse_ssl_error(ssl, err);
exit(-1);
}
char buf[1024] = {'\0'};
err = SSL_read (ssl, buf, sizeof(buf) - 1);
if (err <= 0)
{
analyse_ssl_error(ssl, err);
exit(-1);
}
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);
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.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>
int analyse_ssl_error(const SSL* ssl,int err_code )
{
switch(SSL_get_error(ssl,err_code))
{
case SSL_ERROR_NONE:
printf("No error\n");
break;
case SSL_ERROR_ZERO_RETURN:
printf("SSL_ERROR_ZERO_RETURN\n");
break;
case SSL_ERROR_WANT_READ:
printf("SSL_ERROR_WANT_READ\n");
break;
case SSL_ERROR_WANT_WRITE:
printf("SSL_ERROR_WANT_WRITE\n");
break;
case SSL_ERROR_WANT_CONNECT:
printf("SSL_ERROR_WANT_CONNECT\n");
break;
case SSL_ERROR_WANT_ACCEPT:
printf("SSL_ERROR_WANT_ACCEPT\n");
break;
case SSL_ERROR_WANT_X509_LOOKUP:
printf("SSL_ERROR_WANT_X509_LOOKUP\n");
break;
case SSL_ERROR_SYSCALL:
printf("SSL_ERROR_SYSCALL:%s\n", strerror(errno));
if (errno == EPIPE)
{
return 1;
}
break;
case SSL_ERROR_SSL:
printf("SSL_ERROR_SSL\n");
break;
default:
printf("unkown error\n");
break;
}
return 0;
};
SSL_CTX* init_ssl_ctx(const char *certfile, const char *keyfile, const char *cafile)
{
/* Load encryption & hashing algorithms for the SSL program */
SSL_library_init();
/* Load the error strings for SSL & CRYPTO APIs */
SSL_load_error_strings();
/* Create an SSL_METHOD structure (choose an SSL/TLS protocol version) */
const SSL_METHOD *meth = SSLv23_server_method();
/* Create an SSL_CTX structure */
SSL_CTX *ctx = SSL_CTX_new (meth);
if (NULL == ctx)
{
printf("Could not new SSL_CTX\n");
return NULL;
}
/* Load the CA cert file*/
if (SSL_CTX_load_verify_locations(ctx, cafile, NULL) <= 0)
{
printf("Could not load ca cert file\n");
}
/* Load the client certificate into the SSL_CTX structure */
if (SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM) <= 0)
{
printf("Could not use certificate file\n");
}
/* Load the private-key corresponding to the client certificate */
if (SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM) <= 0)
{
printf("Could not use private key file\n");
}
/* Check if the client certificate and private-key matches */
if (!SSL_CTX_check_private_key(ctx))
{
printf("Private key does not match certfile\n");
}
return ctx;
}
int main ()
{
SSL_CTX *ctx = init_ssl_ctx("./PEMS/server/server.crt",
"./PEMS/server/server.key",
"./PEMS/ca/ca.cert");
if (NULL == ctx)
{
exit(-1);
}
/* ----------------------------------------------- */
/* Prepare TCP socket for receiving connections */
int listen_sd = socket (AF_INET, SOCK_STREAM, 0);
if (listen_sd < 0)
{
perror("New listen socket error");
exit(-1);
}
struct sockaddr_in sa_serv;
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 */
int err = bind(listen_sd, (struct sockaddr*) &sa_serv,
sizeof (sa_serv));
if (err < 0)
{
perror("Could not bind address");
exit(-1);
}
/* Receive a TCP connection. */
err = listen (listen_sd, 5);
if (err < 0)
{
perror("Could not listen on port");
exit(-1);
}
struct sockaddr_in sa_cli;
socklen_t client_len = sizeof(sa_cli);
int sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
if (sd < 0)
{
perror("Accept error");
exit(-1);
}
close (listen_sd);
/* ----------------------------------------------- */
/* TCP connection is ready. Do server side SSL. */
SSL* ssl = SSL_new (ctx);
if (NULL == ssl)
{
printf("Could not create new SSL\n");
exit(-1);
}
SSL_set_fd (ssl, sd);
err = SSL_accept (ssl);
if (err <= 0)
{
analyse_ssl_error(ssl, err);
exit(-1);
}
/* DATA EXCHANGE - Receive message and send reply. */
char buf[1024] = {'\0'};
err = SSL_read (ssl, buf, sizeof(buf) - 1);
if (err <= 0)
{
analyse_ssl_error(ssl, err);
exit(-1);
}
buf[err] = '\0';
printf ("Got %d chars:'%s'\n", err, buf);
err = SSL_write (ssl, "I hear you.", strlen("I hear you."));
if (err <= 0)
{
analyse_ssl_error(ssl, err);
exit(-1);
}
/* Clean up. */
close (sd);
SSL_free (ssl);
SSL_CTX_free (ctx);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment