Before getting into 2-way ssl, we need to understand what asymmetric cryptography is.

Asymmetric cryptography

Asymmetric cryptography is a process that uses a pair of related keys— one public key and one private key — to encrypt and decrypt a message.

A public key is a cryptographic key that can be used by any person to encrypt a message so that it can only be deciphered by the intended recipient with their private key.

Initially, a pair of private and public key is generated at the sender’s end and the receiver’s end. These keys can be generated using DSA algorithms. To know about DSA algorithms, you can click here. Then, the public keys are shared between the sender and the receiver. The sender, then, encrypts the payload or the message he/she wants to send with the receiver’s public key, thus creating a ciphertext. This ciphertext is then sent to the receiver, who decrypts it with his/her private key. Although, the public key can be shared among multiple receivers, it can only be decrypted by its corresponding private key, thus providing a certain level of security.

If the public key is used for encryption, then the related private key is used for decryption. If the private key is used for encryption, then the related public key is used for decryption.

SSL(Secure Socket Layer) is a cryptographic protocol used for enabling secure communication between a client and server to ensure data security and integrity.

The communication over SSL always begins with the SSL handshake. The SSL handshake is an asymmetric cryptography which allows the client to verify the web server and establish a secure connection before the beginning of the actual data transfer. Both parties share their public certificates(X.509 certificates signed by CA) to each other and then verification/validation is performed based on that.

Below are the steps involved in the process of handshake and actual data transfer:

  • Client requests a protected resource over HTTPS protocol and the SSL handshake process begins. This message includes the client’s SSL version number, cipher settings, session-specific data and other information that the server needs to communicate with the client using SSL.
  • Server sends a copy of its public certificate to the client. This message includes the server’s SSL version number, cipher settings, session-specific data, an SSL certificate with a public key and other information that the client needs to communicate with the server over SSL.
  • Client checks the certificate root against a list of trusted CAs and that the certificate is valid. If the authentication fails, then the client refuses the SSL connection and throws an exception. If the client trusts the certificate, it creates, encrypts, sends back its public certificate to the server and move on to the next step.
  • Server validates/verifies the received certificate through certification authority (CA) for CA signed certificates.
  • After completion of handshake process, client and server communicate and transfer data with each other encrypted with the secret keys shared between the two during handshake. Please see the pictorial representation of the whole process below:
2 way SSL

Please see a sample golang code given below for actual data transfer i.e when the handshake has been established:

import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"flag"
"io/ioutil"
"log"
"net/http"
)
var (
caFile = flag.String("CA", "publicTest.pem", "A PEM encoded CA's certificate file.")
)
func main() {
flag.Parse()

// Load CA cert
caCert, err := ioutil.ReadFile(*caFile)
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// Setup HTTPS client
tlsConfig := &tls.Config{
RootCAs: caCertPool,
}
tlsConfig.BuildNameToCertificate()
transport := &http.Transport{TLSClientConfig: tlsConfig}
headers := http.Header{}
headers.Set("xyz-Client-Id", "abc-def-ghi-jkl")
headers.Set("xyz-Client-Secret", "jasbdjkabckasnclasncdsv")
var body = []byte(`{
"order_id": 1223
}`)
request, err := http.NewRequest("POST", "https://staging- abc/order/update", bytes.NewBuffer(body))
if err != nil {
log.Fatal(err)
}
request.Header = headers
client := &http.Client{
Transport: transport,
}
// Do POST something
resp, err := client.Do(request)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// Dump response
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
log.Println("data: ", string(data))
}

If you want to know the differences between 1 way and 2 way SSL, you can follow this link.

Software Engineer