Last active
September 9, 2017 09:03
-
-
Save longbuilder/9457809 to your computer and use it in GitHub Desktop.
ssl_demo
This file contains hidden or 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
| 一、生成用于签发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证书 |
This file contains hidden or 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
| #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); | |
| } |
This file contains hidden or 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
| #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