Self signed certificate creation, c code verification

Advance preparation

relevant:
pem, key: private key file, which encrypts and decrypts data
csr: the certificate signing request file, which is submitted to the certification authority (CA, CA) to sign the certificate
crt: a certificate or self signed certificate signed by a certification authority (CA, CA). The certificate contains information such as the certificate holder's information, the holder's public key and the signer's signature
The certificate related format conversion is not introduced in this article

Terminal input command: VIM / usr / local / openssl / SSL / openssl CNF, you can find the default configuration file of openssl according to your specific installation path. Some contents are shown in the following figure:

Screenshot of openssl default configuration

dir: the default ssl working directory. You can modify the default directory. Here is the default directory after installation
certs: store issued certificates
newcerts: store the certificate newly generated by the CA
Private: store the private key
crl: store revoked certificates
index.txt: text database file of the issued certificate
Serial: the serial number stores the file. The serial number is a hexadecimal number, which is stored for the issuance of the certificate bookmark. The serial number is used as a reference
. rand: private random file,
Generate random number command: OpenSSL Rand - out XXX / rand 1024
1024 indicates the length of the random number
To create a default configuration directory file in the temporary directory where the certificate is generated, click Soha:
mkdir -p ./demoCA/certs; mkdir -p ./demoCA/crl; mkdir ./democA/newcerts; mkdir -p ./demoCA/private; touch ./demoCA/index.txt; touch ./demoCA/serial; echo 01 > ./demoCA/serial;

Create a temporary folder for self generated certificates: mkdir ~/Desktop/openssl_ssl
Enter the folder: cd ~/Desktop/openssl_ssl, and then copy the previously mentioned [openssl.cnf] file here to start making certificates for later socket programming

1. Make ca root certificate

1.1 generate ca root certificate private key

openssl genrsa -aes256 -out ca.key 2048

genrsa: use RSA algorithm to generate private key
-aes256: AES algorithm using 256 bit key encrypts the private key
-out: output file path
2048: private key length
After entering the command, you will enter the password of the private key file twice

1.2 generate ca root certificate request file

openssl req -new -key ca.key -out ca.csr

req: execute certificate issuing command
-New: new certificate issuance request
-Key: Specifies the path of the private key file
-out: the output path of the csr file
After entering the command, you will enter the password of the ca root certificate private key and fill in some information, as shown below:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.

Country Name (2 letter code) [AU]:cn [country code can be empty, ca, server and client should be consistent]
State or province name (full name) [some state]: [Province, ca, server and client should be consistent]
Locality Name (eg, city) []: [city]
Organization name (eg, company) [Internet widgets Pty Ltd]: [company name, ca, server and client should be consistent]
Organizational Unit Name (eg, section) []: [organization name]
Common Name (e.g. server FQDN or YOUR name) []: [cannot be empty, fully qualified domain name or name]
Email Address []: [email]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: [enter password]
An optional company name [] [optional company name]

The ca request information entered above shall be consistent with the request certificate signed by the ca certificate in subsequent applications.

1.3 sign and issue root certificate as a ca Organization (self issued certificate)

openssl x509 -req -days 365 -signkey ca.key -in ca.csr -out ca.crt

X509: used to self sign certificates and generate certificates in x509 format
-req: request signature
-days: certificate validity
-signkey: the private key issued by the certificate
-in: certificate request file, valid file path
-out: ca signed certificate output path

2. Make server certificate

Use the ca certificate just now to issue a certificate for the user

2.1 generate server-side private key

openssl genrsa -aes256 -out server.key 2048
Enter the password twice in a row

2.2 generate server certificate request file

openssl req -new -key server.key -out server.csr
Similarly, you will be asked to enter the password of the private key and fill in the same information as the ca root certificate request file. The two should remain the same

2.3 use ca root certificate to issue certificate for server

openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key -config openssl.cnf

-in: enter the certificate signing request file
-out: output path of signed certificate
-cert: ca root certificate
-keyfile: ca root certificate private key file
-config: configuration file

3. Create client certificate

The routine is basically the same as that of the server side. Now you can directly use the command

3.1 generate client private key

openssl genrsa -aes256 -out client.key 2048

3.2 generate client certificate request file

openssl req -new -key client.key-out client.csr

3.3 use ca root certificate to issue certificate for client

openssl ca -in client.csr -out client.crt -cert ca.crt -keyfile ca.key -config openssl.cnf

Document changes: 1 index. Txt local database text file has two more pieces of information, 2 The serial number of the serial number file is incremented by, 3 Newcerts folder has two more certificates, 4 other...

Here we can finish. We have obtained ca.crt and server key,server.crt,client.key,client.crt, we can start programming.
For two-way authentication, ensure that the ca signed by the server and client certificates are the same or the period has not expired, otherwise the authentication will fail
[next: openssl self signed certificate - socket programming application (3)]

4. Export certificate

4.1 export server certificate

When exporting, you will be asked to enter the password of the server-side private key, namely server key The password of PEM. After passing the verification, enter the password exported by the certificate twice
openssl pkcs12 -export -clcerts -name server-p12 -inkey server.key -in server.crt -out server-p12.keystore

4.2 export client certificate

The export is the same as the server operation. Enter client key first Password for PEM. Enter the password for certificate export twice
openssl pkcs12 -export -clcerts -name client-p12 -inkey client.key -in client.crt -out client-p12.keystore

4.3 export trusted certificates

keytool -importcert -trustcacerts -alias localhost -file ca-crt.cer -keystore ca-trust.keystore

Terminal display:

Enter the keystore password:
Enter the new password again:
Owner: EMAILADDRESS = [email address], CN=127.0.0.1, OU = [organization name], O = [company], L = [city], ST = [province], C=cn [country code]
Publisher: EMAILADDRESS = [email address], CN=127.0.0.1, OU = [organization name], O = [company name], L = [city], ST = [province], C=cn [country code]
Serial No.: 4272b0ce733*************316f20cfe5f6a182
Effective: Mon Jan 28 11:12:17 CST 2019, expired: Tue Jan 28 11:12:17 CST 2020
Certificate fingerprint:
SHA1: C1:B6:C6:B3:95:8F:3C:12:B8:C4:AB:5E:8B:0D:03:6B:6D:B2:1E:D3
SHA256: 31:BF:B7:EA:F3:72:E9:28:95:55:41:76:F0:7B:24:19:2B:FF:C7:C4:AA:AE:63:EF:6C:98:69:5A:49:37:56:3F
Signature algorithm name: SHA256withRSA
Principal public key algorithm: 2048 bit RSA key
Version: 1
Do you trust this certificate? [no]: y [terminal input y/n]
The certificate has been added to the keystore

Now you can start socket programming with ca certificate, server certificate and private key, client certificate and private key



Author: Code blending_ Shani
Link: https://www.jianshu.com/p/37ded4da1095
Source: Jianshu
The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Create application project with xcode

1. Confirm the header file search directory

1. Compile and set the directory according to openssl, such as / usr/local/openssl/include
2. I use homebrew to install openssl. The directory is usually / usr/local/opt/openssl/include

2. Project setting header file search

On the left, click Project - > middle target - > Build Settings tab - > header search paths on the right, and double-click to add a path

Header file search settings

3. Static library settings

  1. Copy the compiled [libcrypto.a] [libssl.a] to the project directory and add it
  2. I installed homebrew, copied [libcrypto.a] [libssl.a] to the project directory, and then added it, "what? Where can I find it?!", It is usually in / usr/local/opt/openssl/lib /

4. Upper code

#include <stdio.h>

#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

#include <openssl/ssl.h>
#include <openssl/err.h>

#define SSL_ROOT_DIR            "your path here..."

#define SSL_CA_PATH             SSL_ROOT_DIR "ca.crt"
#define SSL_SERVER_CER_PATH     SSL_ROOT_DIR "server.crt"
#define SSL_SERVER_KEY_PATH     SSL_ROOT_DIR "server.key"

#define SSL_CLIENT_CER_PATH     SSL_ROOT_DIR "client.crt"
#define SSL_CLIENT_KEY_PATH     SSL_ROOT_DIR "client.key"

#ifndef SSL_VERIFY
#define SSL_VERIFY          1
#endif

#if SSL_VERIFY
#define SSL_VERIFY_MODE     SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT
#else
#define SSL_VERIFY_MODE     SSL_VERIFY_NONE
#endif

int g_ssl_connect_flag = 0;
int g_ssl_server_close = 0;
int g_ssl_client_close = 0;

void ssl_show_certs(SSL * ssl, const char *label)
{
    X509 *cert;
    char *line;
    
    cert = SSL_get_peer_certificate(ssl);
    // SSL_get_verify_result(), really verify
    printf(">>> %s\n", label);
    if(SSL_get_verify_result(ssl) == X509_V_OK){
        
        printf("ssl verify ok.\n");
    }
    
    if(NULL != cert) {
        
        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("ca: %s\n", line);
        free(line);
        X509_free(cert);
    } else{
        
        printf("no certificate info.\n");
    }
}

void ssl_socket_server(void){
    
    SSL_CTX *ctx = NULL;
    int sock = 0;
    ctx = SSL_CTX_new(SSLv23_server_method());
    if(NULL == ctx){
        
        fprintf(stderr, "server create ssl context fail.\n");
        ERR_print_errors_fp(stderr);
        return;
    }
    
    do{
        
        SSL_CTX_set_verify(ctx, SSL_VERIFY_MODE, NULL);
        
        if(0 >= SSL_CTX_load_verify_locations(ctx, SSL_CA_PATH, NULL)){
            
            ERR_print_errors_fp(stderr);
            fprintf(stderr, "server load ca file fail.\n");
            ERR_print_errors_fp(stderr);
            break;
        }
        
        if(0 >= SSL_CTX_use_certificate_chain_file(ctx, SSL_SERVER_CER_PATH)){
            
            fprintf(stderr, "server load cer file fail.\n");
            ERR_print_errors_fp(stderr);
            break;
        }
        
        /// set private key password if needed
        SSL_CTX_set_default_passwd_cb_userdata(ctx, "123456");
        
        if(0 >= SSL_CTX_use_PrivateKey_file(ctx, SSL_SERVER_KEY_PATH, SSL_FILETYPE_PEM)){
            
            fprintf(stderr, "server load private key file fail.\n");
            ERR_print_errors_fp(stderr);
            break;
        }
        
        if(0 >= SSL_CTX_check_private_key(ctx)){
            
            fprintf(stderr, "check server private key fail.\n");
            ERR_print_errors_fp(stderr);
            break;
        }
        
        sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        struct sockaddr_in s_addr;
        memset(&s_addr, 0, sizeof(s_addr));
        s_addr.sin_family = AF_INET;
        s_addr.sin_port = htons(10086);
        s_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        
        if(0 != bind(sock, (const struct sockaddr*)&s_addr, sizeof(s_addr))){
            
            fprintf(stderr, "server bind fail.\n");
            break;
        }
        
        if(0 != listen(sock, 1)){
            
            fprintf(stderr, "server lisent fail.\n");
            break;
        }
        
        struct sockaddr_in s_addr_out;
        int s_add_len = 0;
        int new_sock = 0;
        memset(&s_addr_out, 0x00, sizeof(s_addr_out));
        g_ssl_connect_flag = 1;
        SSL *ssl = NULL;
        printf("server waiting...\n");
        char msg[256] = {0};
        while(1){
            
            s_add_len = sizeof(s_addr_out);
            new_sock = accept(sock, (struct sockaddr*)&s_addr_out, (socklen_t*)&s_add_len);
            if(0 >= new_sock){
                
                continue;
            }
            
            ssl = SSL_new(ctx);
            SSL_set_fd(ssl, new_sock);
            if(1 != SSL_accept(ssl)){
                
                fprintf(stderr, "server accept ssl socket fail.\n");
                ERR_print_errors_fp(stderr);
                SSL_free(ssl);
                close(new_sock);
                continue;
            }
            
#if SSL_VERIFY
            ssl_show_certs(ssl, "serever side:");
#endif
            
            memset(msg, 0x00, 256);
            int sl = sprintf(msg, "hello client<%d> from <%s:%d>\n", new_sock, inet_ntoa(s_addr_out.sin_addr), ntohs(s_addr_out.sin_port));
            int wl = SSL_write(ssl, msg, sl);
            printf("server send %d bytes data.\n", wl);
            
            memset(msg, 0x00, 256);
            int rl = SSL_read(ssl, msg, 256);
            printf("server recv %d bytes data:\ncontent: %s\n", rl, msg);
            
            g_ssl_client_close = 1;
            
            while(1 != g_ssl_server_close){
                
                usleep(200000);
            }
            
            SSL_shutdown(ssl);
            SSL_free(ssl);
            close(new_sock);
            
            printf("server close...\n");
            break;
        }
    }while(0);
    
    shutdown(sock, 2);
    close(sock);
    SSL_CTX_free(ctx);
}

void* ssl_client_thread_(void *param){
    
    int sock = 0;
    SSL *ssl = NULL;
    SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
    if(NULL == ctx){
        
        fprintf(stderr, "client create ssl context fail.\n");
        ERR_print_errors_fp(stderr);
        return NULL;
    }
    
    do{
        
        do{
            
            usleep(200000);
        }while(1 != g_ssl_connect_flag);
        
        usleep(1000000);
        
        SSL_CTX_set_verify(ctx, SSL_VERIFY_MODE, NULL);
        
        if(0 >= SSL_CTX_load_verify_locations(ctx, SSL_CA_PATH, NULL)){
            
            fprintf(stderr, "client load ca file fail.\n");
            ERR_print_errors_fp(stderr);
            break;
        }
        
        if(0 >= SSL_CTX_use_certificate_chain_file(ctx, SSL_CLIENT_CER_PATH)){
            
            fprintf(stderr, "client load cer file fail.\n");
            ERR_print_errors_fp(stderr);
            break;
        }
        
        /// set private key password if needed
        SSL_CTX_set_default_passwd_cb_userdata(ctx, "123456");
        
        if(0 >= SSL_CTX_use_PrivateKey_file(ctx, SSL_CLIENT_KEY_PATH, SSL_FILETYPE_PEM)){
            
            fprintf(stderr, "client load private key file fail.\n");
            ERR_print_errors_fp(stderr);
            break;
        }
        
        if(0 >= SSL_CTX_check_private_key(ctx)){
            
            fprintf(stderr, "check client private key fail.\n");
            ERR_print_errors_fp(stderr);
            break;
        }
        
        sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        struct sockaddr_in s_addr;
        memset(&s_addr, 0x00, sizeof(s_addr));
        s_addr.sin_family = AF_INET;
        s_addr.sin_port = htons(10086);
        s_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        if(0 != connect(sock, (const struct sockaddr *)&s_addr, sizeof(s_addr))){
            
            printf("client connect server fail.\n");
            break;
        }
        
        ssl = SSL_new(ctx);
        SSL_set_fd(ssl, sock);
        if(1 != SSL_connect(ssl)){
            
            fprintf(stderr, "client ssl connect fail.\n");
            ERR_print_errors_fp(stderr);
            break;
        }
        
#if SSL_VERIFY
        ssl_show_certs(ssl, "client side:");
#endif
        
        char msg[256] = {0};
        int rl = SSL_read(ssl, msg, 256);
        printf("client recv %d bytes data:\ncontent: %s\n", rl, msg);
        memset(msg, 0x00, 256);
        const char *m = "hello ssl server!!";
        int sl = (int)strlen(m);
        int wl = SSL_write(ssl, m, sl);
        printf("client send %d bytes data.\n", wl);
        
        while(1 != g_ssl_client_close){
            
            usleep(200000);
        }
    }while(0);
    
    if(NULL != ssl){
        
        SSL_shutdown(ssl);
        SSL_free(ssl);
    }
    close(sock);
    SSL_CTX_free(ctx);
    g_ssl_server_close = 1;
    
    printf("client close...\n");
    
    return NULL;
}

void ssl_socket_client(void){
    
    pthread_t pt;
    if(0 > pthread_create(&pt, NULL, ssl_client_thread_, NULL)){
        
        printf("client create socket thread fail.\n");
        return;
    }
}

void ssl_socket_test(void){
    
    printf("ca path: %s\nser-req: %s\nser-key: %s\nclt-req: %s\nclt-key: %s\n", SSL_CA_PATH, SSL_SERVER_CER_PATH, SSL_SERVER_KEY_PATH, SSL_CLIENT_CER_PATH, SSL_CLIENT_KEY_PATH );
    
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    
    ssl_socket_client();
    ssl_socket_server();
}

int main(int argc, const char * argv[]) {
    // insert code here...
    printf("Hello, World!\n");
    
    ssl_socket_test();
    printf("press any key to exit...\n");
    getchar();
    
    return 0;
}

The main information output of the console is as follows:
Hello, World!
...
server waiting...
...
server send 39 bytes data.
...
client recv 39 bytes data:
content: hello client<5> from <127.0.0.1:53269>

client send 18 bytes data.
server recv 18 bytes data:
content: hello ssl server!!
client close...
server close...
press any key to exit...



Author: Code blending_ Shani
Link: https://www.jianshu.com/p/bba9c47a0515
Source: Jianshu
The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Added by shoxlx on Mon, 24 Jan 2022 12:44:58 +0200