Self-signed certificates are widely used for testing/development and sometimes in production for internal websites.

Self-signed certificates are created without any CA, thus they don’t have a parent. The issuer is also the subject of the certificate.

In general, the use of self-signed certificates must be discouraged as they present an inherent security risk. For example, there is no way to revoke a self-signed cert. Using an internal CA for issuing all internal certificates is a much better option, we will cover it in a future post. It is also difficult to manage self-signed certificates — imagine refreshing trust stores of all client components when a self-signed cert is extended.

Self-signed certs come at a substantial maintenance cost — issuing a cert for a long period of time is insecure, but the short validity adds to the certificate renewal/distribution overhead.

The following best practices will help to make self-signed and internally-issued certificates more secure:

  • Limit the validity period, it should be as short as you can handle from the maintenance standpoint. Never go beyond 12 months.
  • Do not use wildcards and limit the alt names, make it as specific as possible — the certificate should only be issued for the exact hosts/domains where it is going to be used. Use the alternative names extension to list all the hostnames.
  • Use a meaningful and informative “subject” record. CN must match one of your domain names. You can use OU to specify the name of your application or service. Make sure that the full DN record used in the subject is unique across all of the certs. There are many attributes that can be used in the “subject” to make it more informative, you can find the full list here
  • Make sure that the algorithm used for the signature is at least SHA256WITHRSA (which is the default in OpenSSL)
  • Do not create unencrypted private keys. If a key is for a Java application, use the pkcs12 format, it can be used directly by any modern JVM. OpenSSL initially generates a DER encoded private key encrypted using DES, but it can be converted into pkcs12 using openssl pkcs12 command. PKCS12 is the implementation of the PKCS#11 format which is the universal, cross-platform cryptography interface, so it should be preferred over other formats.
  • Use elliptic curve keys as opposed to the default RSA ones, they provide a number of benefits over RSA
  • You can make your certificate more robust by specifying the certificate’s purpose using extended key usage and “key usage” extensions. “TLS Web Server Authentication” should be the only allowed usage for a server. This will prevent unintended use of the certificate.
  • Make your extensions “critical”. Self-signed certificates/keys are only used internally, so all clients should be able to support the usage extensions.
  • Create a repeatable/scriptable process for issuing certificates and keys. OpenSSL is a de-facto standard command line tool that can be used as the basis for this process.
    OpenSSL allows to externalize certificate information in a separate config file that can be version-controlled; this is highly recommended.

Here is a recommended OpenSSL configuration for certificate extensions:

[ extensions ]
basicConstraints = critical, CA:FALSE
keyUsage =critical, digitalSignature, keyEncipherment
extendedKeyUsage = critical, serverAuth
subjectKeyIdentifier = hash
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = host1
DNS.2 = host2

Here is the OpenSSL command for creating self-signed certificates:

openssl req -config cert_conf/self_signed_cert.conf -x509 -days 60 -new -newkey rsa:2048 -keyout certs/ss_keys/self_signed -out certs/ss_certs/self_signed.pem -verbose -passout pass:<your password>

“cert_conf/self_signed_cert.conf” is the certificate configuration file that contains the certificate information section as well as the extension section from above.