Self signed SSL certificate and use of server and client

Posted by Flying Sagittarius on Wed, 19 Jan 2022 09:59:13 +0100

 

Basic generation steps:

  1. Generate CA root certificate
  2. Generate server certificate
  3. Generate client certificate (if two-way authentication is required)

1. Generate root certificate

# Generate root private key
openssl genrsa -out root.key 1024

# To create a root certificate request file based on the private key, you need to enter some meta information of the certificate: mailbox, domain name, etc
openssl req -new -out root.csr -key root.key

# Combine the private key with the request file to create a root certificate with a validity of 10 years
openssl x509 -req -in root.csr -out root.crt -signkey root.key -CAcreateserial -days 3650

2. Generate server certificate

# Create server private key
openssl genrsa -out server.key 1024

# Generate request file based on private key
openssl req -new -out server.csr -key server.key

# The server certificate is created by combining the private key and the request file, which is valid for 10 years
openssl x509 -req -in server.csr -out server.crt -signkey server.key -CA ../root_ca/root.crt -CAkey ../root_ca/root.key -CAcreateserial -days 3650

If you only need to deploy the server certificate side, you can end it. Take it CRT public key and server The key private key is deployed on the server, then the domain name is resolved and the server points to the IP. The certificate is successfully deployed.

3. Generate client certificate

If two-way verification is required, that is, the server needs to verify the client certificate. Then you need to regenerate a client certificate under the same root certificate

# Generate private key
openssl genrsa -out client.key 1024

# Application request document
openssl req -new -out client.csr -key client.key

# Generate certificate
openssl x509 -req -in client.csr -out client.crt -signkey client.key -CA ../root_ca/root.crt -CAkey ../root_ca/root.key -CAcreateserial -days 3650

# Generate a file in pkcs12 format of client integration certificate to facilitate browser or http client access (password: 123456)
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12

Server configuration

1. Service domain name plus certificate

Use Caddy as a server to deploy https services
Caddyfile

{
  admin off # Close operation and maintenance interface
  auto_https off # Auto configure https off
}

https://example.com {
    tls <Certificate file path> <Private key file path>
}

2. Two way certificate authentication is required

{
  admin off # Close operation and maintenance interface
  auto_https off # Auto configure https off
}

https://example.com {
    tls <Certificate file path> <Private key file path> {
        client_auth {
            mode require_and_verify
            trusted_ca_cert_file <Root certificate file path>
        }
    }
}

Client configuration

You need to set the root certificate on the client and trust the root certificate. Because the server certificate is a self signed certificate, a public CA cannot authenticate a self signed certificate. Therefore, the client needs to add and trust its own root certificate before accessing the server through https. If a certificate issued by a public CA is deployed on the server, you do not need to set it because most public CA certificates have been built in the system

Using Postman

Select the root certificate file from settings - > certificates - > CA certificates - > PEM file.
After configuration, you can use https to access the service

Using HttpClient to access how to configure a client

It is complicated to use programs to call https. To sum up, it can be divided into the following steps:

  1. Read root certificate file stream
  2. Get KeyStore
  3. Load root certificate into KeyStore
  4. Get SSLContexts instance
  5. Take the SSLContexts instance as a parameter and set the object of processing socket link factory corresponding to Protocol http and https
  6. Generate a link manager with a link factory as a parameter
  7. Take the link manager as a parameter to generate the httpclient client
public class SSLContextBuilder {
    public static String build(String keyStorePath, String keyStorepass) {
		SSLContext sc = null;
		FileInputStream instream = null;
		KeyStore trustStore = null;
		try {
			trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
			instream = new FileInputStream(new File(keyStorePath));
			trustStore.load(instream, keyStorepass.toCharArray());
			// Trust your CA and all self signed certificates
			sc = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();
		} catch (KeyStoreException | NoSuchAlgorithmException| CertificateException | IOException | KeyManagementException e) {
			e.printStackTrace();
		} finally {
			try {
				instream.close();
			} catch (IOException e) {
			}
		}
		return sc;
    }
}
public class HttpClientInstanceBuilder {
    public static CloseableHttpClient builde() {
        // If the password is empty, use "nopassword" instead
        SSLContext sslcontext = SSLContextBuilder.build("<Root certificate file path>", "<Certificate password>");
         // Set the object of processing socket link factory corresponding to Protocol http and https
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", PlainConnectionSocketFactory.INSTANCE)
            .register("https", new SSLConnectionSocketFactory(sslcontext))
            .build();

        PoolingHttpClientConnectionManager connManager = 
        new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        
        CloseableHttpClient clientInstance = HttpClients
            .custom()
            .setConnectionManager(connManager)
            .build();
        return clientInstance;
    }
}

In this way, you can get the HTTP client that supports accessing self signed certificates

https bidirectional authentication

If the server enables two-way authentication, the client should also provide a client certificate that belongs to the same root certificate as the server certificate.

Add client certificate and private key to client

The client can add a certificate in PKCS format, which binds the certificate and private key into a file

Then how to load p12 or pfx file to client?

Similar to loading root certificates

public class SSLContextBuilder {
    // If the password is empty, use "nopassword" instead
    public static String build(String keyStorePath, String keyStorepass) {
		SSLContext sc = null;
		FileInputStream instream = null;
		KeyStore trustStore = null;
		try {
			KeyStore trustStore = KeyStore.getInstance("PKCS12");
			instream = new FileInputStream(new File(keyStorePath));
			trustStore.load(instream, keyStorepass.toCharArray());
            // This is the difference from loading the root certificate. The way of loading the certificate is different
            sc = SSLContexts.custom().loadKeyMaterial(trustStore, keyStorepass.toCharArray()).build();
		} catch (KeyStoreException | NoSuchAlgorithmException| CertificateException | IOException | KeyManagementException e) {
			e.printStackTrace();
		} finally {
			try {
				instream.close();
			} catch (IOException e) {
			}
		}
		return sc;
    }
}

Topics: Linux