Sunday, January 8, 2017

Security and self-signed certificates: A primer on digital certificates and generating a self-signed certificate

What is a digital certificate?

The idea behind a certificate is to be assured the person (or service) we are talking to is in fact who the person (or service) claims to be.

Part of the 3 way handshake in establishing the security protocol is for the remote service to provide the client with its public key and certificate.

The certificate aims at assuring the client the public key does in fact belong to the remote party (person or service). The client then uses the public key to encrypt the data passed to the remote party. The remote party then decrypts the data using its private key (never shared).

Therefore, in establishing server authentication, there are 3 elements which come into play:
-          Certificate authority (Trusted 3rd party assuring identity of remote service)
-          Server Certificate (Certificate embedding the remote service’s public key)
-          Private Key (Remote service’s private to decrypt incoming data)

The crux of the public-key cryptographic system is that only the entity with the private key can decrypt the data encrypted with the public key.

In our case, the remote party is the entity holding the private key.

Therefore, the public key is something that a service would send to the client in order to encrypt the data. However, the client needs to know that the public key in fact belongs to the remote service entity. What the service sends is its public key along with its identity together forming the Server Certificate which can be verified by a trustworthy 3rd party which we refer to as the Certificate Authority. The client will take the Server Certificate and contact the Certificate Authority and make the verification.

How is the Server Certificate generated in theory?

If entity A wants to share its public key, it would want everyone who cares about the key to know it is really from A. Entity A makes a request to a known Certificate Authority by sending its public key, contact and identity attributes. The Certificate Authority contacts A to let it know it’s going to “certify” it and return the public key signed by the Certificate Authority with its private key. Now when entity A sends its certificate to a client (signed public key + identity attributes), the client will use the Certificate Authority’s public key to decrypt the entity A’s certificate. Since only the trustworthy Certificate Authority has the private key, we know the public key embedded in the Server Certificate is in fact entity A’s key.

Once the verification is established, the client can proceed in encrypting the data using the public key.

There are numerous reasons for not using self-signed certificates. In general, we resort to using self-signed certificates for testing secure applications in the development environment. A self-signed certificate is a certificate signed by an unknown (sometimes not trustworthy) Certificate Authority. In this case, we are the Certificate Authority and signing our own Server Certificate.

To generate the 3 elements necessary in establishing server authentication, we will use the 3rd party tool cfssl ( https://github.com/cloudflare/cfssl ).

We will run two commands:
-          Generate the Certificate Authority
-          Generate the Server Certificate and Private Key

Both commands will take JSON as in input.

The JSON inputs are key requests containing identity attributes. For the first command, a test request in the JSON format is saved to file mycacsr.json:

{
    "CN": "myDevCa",
    "key" : {"algo": "rsa", "size": 2048},
    "names" : [{"C": "US", "L": "New Jersey", "OU": "WWW", "O": "Example", "ST": "New Jersey"}]
}

To generate the Certificate Authority (or root certificate in our case):

cfssl genkey -initca mycacsr.json | cfssljson -bare ca

At this point, you should have a Certificate Authority saved as ca.pem and a Certificate Authority key ca-key.pem.

The next command is generating the Server Certificate and Private Key which will take a JSON input saved to file myservercert.json:

{
    "key" : {"algo": "rsa", "size": 2048},
    "names" : [{"C": "US", "L": "New Jersey", "OU": "WWW", "O": "Example", "ST": "New Jersey"}]
}

Along with the JSON input, the second command will take the previously generated Certiticate Authority and Certificate Authority Key to generate the Server Certificate and Private Key:

cfssl gencert -ca ca.pem -ca-key ca-key.pem -hostname
localhost myservercert.json | cfssljson -bare localhost

At this point, you have a server certificate localhost.pem and private key localhost-key.pem

Why did we need the Certificate Authority and Certificate Authority’s key to generate our certificate?

As explained before, the Server Certificate will be signed using the Certificate Authority’s private key.

The next blog will be on how to start secured services such as Mesos or Kubernetes using our self-signed certificate.


If you have any questions or feedback, please do not hesitate to drop a note!  

No comments:

Post a Comment