Introduction to openssl in socket programming

Posted by b-ware on Wed, 09 Feb 2022 15:23:38 +0100

1. What is ssl

Secure Sockets Layer

It is a standard that supports secure communication on the Internet, and integrates data encryption technology into the protocol.

Data is encrypted before leaving the computer and is decrypted only after it reaches its intended target.

Certificates and cryptographic algorithms support all this. Use OpenSSL to experience them.

In theory, if encrypted data is intercepted or eavesdropped before reaching the target, those data cannot be cracked.

However, due to the rapid change of computers year by year and the new development of password translation methods, the possibility of cracking the encryption protocol used in SSL is also increasing.

SSL and secure connections can be used for any type of protocol on the Internet, whether HTTP, POP3, or FTP.

SSL can also be used to protect Telnet sessions.  

Although you can protect any connection with SSL, you don't have to use SSL for every type of connection.

If the connection transmits sensitive information, SSL should be used.

2. What is openssl

OpenSSL is more than just SSL. It can realize message digest, file encryption and decryption, digital certificate, digital signature and random number. There is a lot about the OpenSSL library, which is far from an article.

OpenSSL is not only an API, but also a command-line tool.

The command line tool can do the same work as the API, and further, it can test SSL servers and clients.

3. Writing steps of server

4. Client writing steps

5. Related header file

socket related header file

#include <sys/types.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#include <sys/socket.h>

ssl related header file

#include <openssl/ssl.h>

#include <openssl/err.h>

6. Sample program

Server

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
 
#define MAXBUF 1024
 
int main(int argc, char **argv)
{
    int sockfd, new_fd;
    socklen_t len;
    struct sockaddr_in my_addr, their_addr;
    unsigned int myport, lisnum;
    char buf[MAXBUF + 1];
    SSL_CTX *ctx;
 
    if (argv[1])
        myport = atoi(argv[1]);
    else
        myport = 7838;
 
    if (argv[2])
        lisnum = atoi(argv[2]);
    else
        lisnum = 2;
 
    /* SSL Library initialization */
    SSL_library_init();
    /* Load all SSL algorithms */
    OpenSSL_add_all_algorithms();
    /* Load all SSL error messages */
    SSL_load_error_strings();
    /* Generate an SSL in a manner compatible with SSL V2 and V3 standards_ CTX, SSL Content Text */
    ctx = SSL_CTX_new(SSLv23_server_method());
    /* Sslv2 can also be used_ server_ Method() or SSLv3_server_method() stands for V2 or V3 standard separately */
    if (ctx == NULL) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
    /* Load the user's digital certificate, which is used to send to the client. The certificate contains a public key */
    if (SSL_CTX_use_certificate_file(ctx, argv[4], SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
    /* Load user private key */
    if (SSL_CTX_use_PrivateKey_file(ctx, argv[5], SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
    /* Check whether the user's private key is correct */
    if (!SSL_CTX_check_private_key(ctx)) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
 
    /* Turn on a socket to listen */
    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    } else
        printf("socket created/n");
 
    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = PF_INET;
    my_addr.sin_port = htons(myport);
    if (argv[3])
        my_addr.sin_addr.s_addr = inet_addr(argv[3]);
    else
        my_addr.sin_addr.s_addr = INADDR_ANY;
 
    if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))
        == -1) {
        perror("bind");
        exit(1);
    } else
        printf("binded/n");
 
    if (listen(sockfd, lisnum) == -1) {
        perror("listen");
        exit(1);
    } else
        printf("begin listen/n");
 
    while (1) {
        SSL *ssl;
        len = sizeof(struct sockaddr);
        /* Wait for the client to connect */
        if ((new_fd =
             accept(sockfd, (struct sockaddr *) &their_addr,
                    &len)) == -1) {
            perror("accept");
            exit(errno);
        } else
            printf("server: got connection from %s, port %d, socket %d/n",
                   inet_ntoa(their_addr.sin_addr),
                   ntohs(their_addr.sin_port), new_fd);
 
        /* Generate a new SSL based on ctx */
        ssl = SSL_new(ctx);
        /* Add the socket of the connected user to SSL */
        SSL_set_fd(ssl, new_fd);
        /* Establish SSL connection */
        if (SSL_accept(ssl) == -1) {
            perror("accept");
            close(new_fd);
            break;
        }
 
        /* Start processing data transmission and reception on each new connection */
        bzero(buf, MAXBUF + 1);
        strcpy(buf, "server->client");
        /* Send message to client */
        len = SSL_write(ssl, buf, strlen(buf));
 
        if (len <= 0) {
            printf
                ("news'%s'Sending failed! The error code is%d,The error message is'%s'/n",
                 buf, errno, strerror(errno));
            goto finish;
        } else
            printf("news'%s'Successfully sent, total sent%d Bytes!/n",
                   buf, len);
 
        bzero(buf, MAXBUF + 1);
        /* Receive messages from clients */
        len = SSL_read(ssl, buf, MAXBUF);
        if (len > 0)
            printf("Message received successfully:'%s',common%d Bytes of data/n",
                   buf, len);
        else
            printf
                ("Failed to receive message! The error code is%d,The error message is'%s'/n",
                 errno, strerror(errno));
        /* End of processing data transmission and reception on each new connection */
      finish:
        /* Close SSL connection */
        SSL_shutdown(ssl);
        /* Release SSL */
        SSL_free(ssl);
        /* Close socket */
        close(new_fd);
    }
 
    /* Close the listening socket */
    close(sockfd);
    /* Release CTX */
    SSL_CTX_free(ctx);
    return 0;
}

client

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
 
#define MAXBUF 1024
 
void ShowCerts(SSL * ssl)
{
    X509 *cert;
    char *line;
 
    cert = SSL_get_peer_certificate(ssl);
    if (cert != NULL) {
        printf("Digital certificate information:/n");
        line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
        printf("certificate: %s/n", line);
        free(line);
        line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
        printf("Issuer: %s/n", line);
        free(line);
        X509_free(cert);
    } else
        printf("No certificate information!/n");
}
 
int main(int argc, char **argv)
{
    int sockfd, len;
    struct sockaddr_in dest;
    char buffer[MAXBUF + 1];
    SSL_CTX *ctx;
    SSL *ssl;
 
    if (argc != 3) {
        printf
            ("Parameter format error! The correct usage is as follows:/n/t/t%s IP Address port/n/t such as:/t%s 127.0.0.1 80/n This program is used to IP A port of the server with the most addresses receives MAXBUF Byte message",
             argv[0], argv[0]);
        exit(0);
    }
 
    /* SSL For library initialization, see SSL server C code */
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    ctx = SSL_CTX_new(SSLv23_client_method());
    if (ctx == NULL) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
 
    /* Create a socket for tcp communication */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        exit(errno);
    }
    printf("socket created/n");
 
    /* Initialize the address and port information of the server (opposite party) */
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {
        perror(argv[1]);
        exit(errno);
    }
    printf("address created/n");
 
    /* Connect server */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }
    printf("server connected/n");
 
    /* Generate a new SSL based on ctx */
    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, sockfd);
    /* Establish SSL connection */
    if (SSL_connect(ssl) == -1)
        ERR_print_errors_fp(stderr);
    else {
        printf("Connected with %s encryption/n", SSL_get_cipher(ssl));
        ShowCerts(ssl);
    }
 
    /* Receive the message sent by the other party, and receive MAXBUF bytes at most */
    bzero(buffer, MAXBUF + 1);
    /* Receive messages from the server */
    len = SSL_read(ssl, buffer, MAXBUF);
    if (len > 0)
        printf("Message received successfully:'%s',common%d Bytes of data/n",
               buffer, len);
    else {
        printf
            ("Message receiving failed! The error code is%d,The error message is'%s'/n",
             errno, strerror(errno));
        goto finish;
    }
    bzero(buffer, MAXBUF + 1);
    strcpy(buffer, "from client->server");
    /* Send message to server */
    len = SSL_write(ssl, buffer, strlen(buffer));
    if (len < 0)
        printf
            ("news'%s'Sending failed! The error code is%d,The error message is'%s'/n",
             buffer, errno, strerror(errno));
    else
        printf("news'%s'Successfully sent, total sent%d Bytes!/n",
               buffer, len);
 
  finish:
    /* Close connection */
    SSL_shutdown(ssl);
    SSL_free(ssl);
    close(sockfd);
    SSL_CTX_free(ctx);
    return 0;
}

makefile

 

 

EXTRA_CFLAGS+= -Wall -Werror -lssl
all:
        gcc $(EXTRA_CFLAGS) server.c -o server
        gcc $(EXTRA_CFLAGS) client.c -o client
 

7. Generate certificates and keys

openssl genrsa -out privkey.pem 2048

openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095

8. Compile and run

Check whether the openssl development package is installed in the system before compiling. If not, sudo Yum install openssl devel

make

./server 7838 cacert.pem privkey.pem

./client 127.0.0.1 7838