DEV Community

Voy
Voy

Posted on

Generating pair of .jks and .pem certificates.

I recently run into needing a pair of *.pem and *.jks
self-signed certificates for local TLS verification. After some reading I put together this guide for generating either and converting it to the other.

You can use two approaches:


Note: This guide is based on documentation for an open source library I built recently called IBeam. It is a wrapper working with IBKR Client Portal Web API Gateway. For that reason all example URLs below point to localhost:5000/v1/api/one/user. Modify this URL to whatever routes your server supports.

Generating Certificates

You can generate your own self-signed certificate in two ways:

Either way you chose, you will then need to convert one certificate into the other. Therefore, you will need both Keytool and OpenSSL to generate your certificates.

Note that you can't generate cacert.jks and cacert.pem independently. You must generate only one certificate first using either method and then convert it into the other format.

Using Keytool

Generate JKS

Keytool is a Java tool shipped with Java Runtime Environment (JRE). It can be found in JRE_ROOT/bin/keytool.

  1. To generate the cacert.jks run:

    keytool -genkey -keyalg RSA -alias selfsigned \
     -keystore cacert.jks -storepass YOUR_CERTIFICATE_PASSWORD \
     -validity 730 -keysize 2048 
    

    Note the YOUR_CERTIFICATE_PASSWORD field. Replace it which certificate password you want to use. You will need to use this same password in later steps.

    Optionally, you may want to add additional option to provide Subject Alternative Names (SAN) in order for the certificate to accept requests from your client hosts. For instance, if the server is to be communicated with from two client machines, one with IP address of 10.148.0.0 and one with DNS of my-client.machine.com, your keytool command line should include:

    -ext SAN=ip:10.147.0.0,dns:my-client.machine.com
    
  2. Upon running command from Step 1, you will be asked the following questions which you may chose to ignore:

    • What is your first and last name?
    • What is the name of your organizational unit?
    • What is the name of your organization?
    • What is the name of your City or Locality?
    • What is the name of your State or Province?
    • What is the two-letter country code for this unit?
  3. Eventually, Keytool will ask for your confirmation, along the lines of:

    Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?

    Type yes to continue if the information is correct.

  4. Finally, Keytool will ask you for the key password. You may simply hit return to use the same password as specified in the -storepass flag in Step 1. DO NOT provide a different password than YOUR_CERTIFICATE_PASSWORD specified above.

  5. You should now have the cacert.jks file generated in your current directory.

Convert JKS to PEM

To convert a cacert.jks to cacert.pem file you need to:

  1. Convert cacert.jks to cacert.p12 using Keytool:

    keytool -importkeystore -srckeystore cacert.jks \
     -destkeystore cacert.p12 -srcstoretype jks -deststoretype pkcs12
    

    You will be asked for a new password for cacert.p12, as well as for the original password of cacert.jks. Ensure you use the same password as when generating the cacert.jks.

  2. Convert cacert.p12 to cacert.pem using OpenSSL:

    openssl pkcs12 -in cacert.p12 -out cacert.pem
    

    Again, you will be asked for a new password for cacert.pem, as well as for the original password of cacert.p12. Ensure you use the same password as when generating the cacert.jks and cacert.p12.

  3. You should now have the cacert.pem file generated in your current directory.

You should now have cacert.jks, cacert.p12 and cacert.pem. You will only need the .jks and .pem files. You may delete the redundant cacert.p12 file.

Using OpenSSL

Generate PEM

  1. To generate a cacert.pem using OpenSSL run:

    openssl req -x509 -days 730 -newkey rsa:2048 \
     -keyout key.pem -out cert.pem
    

    Optionally, you may want to add additional option to provide Subject Alternative Names (SAN) in order for the certificate to accept requests from your client hosts. To do so, you must create a san.cnf used as a configuration file for openssl, and add the following to the openssl command line:

    -config san.cnf
    

    Your san.cnf can take multiple forms, yet to support SAN it requires the subjectAltName field. Have a look at this template san.cnf file that you can use as a basis to specify your SANs.

    For instance, if the server is to be communicated with from two client machines, one with IP address of 10.148.0.0 and one with DNS of my-client.machine.com, your san.cnf should contain:

    [alt_names]
    IP.1 = 10.148.0.0
    DNS.1 = my-client.machine.com
    
  2. You will be asked for a password. You will need to use this same password in later steps.

  3. You should now have key.pem and cert.pem files in your current directory.

  4. Combine key.pem and cert.pem to create cacert.pem:

    cat key.pem cert.pem > cacert.pem 
    

    You can also merge these two files manually if you prefer.

  5. You should now have cacert.pem, key.pem and cert.pem. You will only need the cacert.pem file. You may delete the redundant key.pem and cert.pem files.

PEM to JKS

To convert a cacert.pem to cacert.jks file you need to:

  1. Convert cacert.pem to cacert.p12 using OpenSSL:

    openssl pkcs12 -export -in cacert.pem -out cacert.p12
    

    You will be asked for a new password for cacert.p12, as well as for the original password of cacert.pem. Ensure you use the same password as when generating the cacert.pem.

  2. Convert cacert.p12 to cacert.jks using Keytool:

    keytool -importkeystore -srckeystore cacert.p12 \
     -srcstoretype pkcs12 -destkeystore cacert.jks
    

    Again, you will be asked for a new password for cacert.jks, as well as for the original password of cacert.p12. Ensure you use the same password as when generating the cacert.pem and cacert.p12.

  3. You should now have the cacert.jks file generated in your current directory.

You should now have cacert.pem, cacert.p12 and cacert.jks. You will only need the .jks and .pem files. You may delete the redundant cacert.p12 file.

Use your certificate

cURL

cURL accepts --cacert flag that can be used to pass the certificate. See cURL documentation for more.

curl -X GET "https://localhost:5000/v1/api/one/user" \
  --cacert cacert.pem
Enter fullscreen mode Exit fullscreen mode

Python urllib3

Python urllib3 library allows you to specify a SSL context through which you can specify the location of your certificate.

context = ssl.create_default_context()
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_verify_locations('cacert.pem')
urllib.request.urlopen("https://localhost:5000/v1/api/one/user", 
    context=context)
Enter fullscreen mode Exit fullscreen mode

Python requests

Python requests library allows you to set the verify parameter to specify the location of your certificate.

requests.get("https://localhost:5000/v1/api/one/user", 
    verify='cacert.pem')
Enter fullscreen mode Exit fullscreen mode

Ignoring the TLS verification

For debugging and development, you may chose to ignore the TLS verification. This section describes ways of doing so in cURL, Python's urllib3 and requests libraries.

cURL

cURL accepts --insecure or -k flags that can be used to ignore verifying certificates. See [cURL documentation][curl-k] for more.

curl -X GET "https://localhost:5000/v1/api/one/user" -k
Enter fullscreen mode Exit fullscreen mode

Python urllib3

Python urllib3 library allows you to specify an empty SSL context, which effectively will ignore verifying the certificates.

empty_context = ssl.SSLContext()
urllib.request.urlopen("https://localhost:5000/v1/api/one/user", 
    context=empty_context)
Enter fullscreen mode Exit fullscreen mode

Python requests

Python requests library allows you to set the verify parameter to False when making requests, which effectively will ignore verifying the certificates.

requests.get("https://localhost:5000/v1/api/one/user", 
    verify=False)
Enter fullscreen mode Exit fullscreen mode

Hope you guys find this guide useful 👋


Final word: It's a whole another conversation whether it is a good idea to create self-signed certificates and where do they belong. This guide is merely showing you how to create a pair of certificates. It is recommended to verify whether self-signed certificates would be the right choice for your use case.

Top comments (0)