Posted on ::

OpenSSL & Keytool

  • Extract Certificate from Server
# Extract the server certificates.
$ echo -n | openssl s_client -showcerts -connect google.com:443 \
          | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > google.pem

# OR use java keytool
$ keytool -printcert -rfc -sslserver google.com:443 > google.pem

# Show full cert chain (CN, SAN and Expiry) of TLS server
$ echo | openssl s_client -showcerts -connect google.com:443 2>/dev/null \
       | while openssl x509 -noout \
       -subject -ext subjectAltName -issuer -dates \
       -fingerprint -sha256 -serial 2>/dev/null; \
       do echo "--------------" ; done

# Show just the cert details of a TLS server
$ echo | openssl s_client -showcerts -connect google.com:443 2>/dev/null \
       | openssl x509 -inform pem -noout -text

# Show full cert chain of PEM
$ cat cert.pem | while openssl x509 -noout \
                      -subject -ext subjectAltName -issuer -dates \
                      -fingerprint -sha256 -serial 2>/dev/null; \
                      do echo "**************" ; done
$ keytool -printcert -file cert.pem \
    | grep -i -e "Owner" -e "Issuer:" -e "Serial number:" -e "SHA256:"

# Extract TLS public keys in Cert pinning format
$ openssl s_client -connect 'dns.google.com:443' 2>&1 < /dev/null \
         | sed -n '/-----BEGIN/,/-----END/p' \
         | openssl x509 -noout -pubkey \
         | openssl asn1parse -noout -inform pem -out /dev/stdout \
         | openssl dgst -sha256 -binary \
         | openssl base64

$ curl -vvI https://google.com 2>&1 | grep -i date
  • Create PKCS#12 trust-store from pem
# Create/Add trust store
$ keytool -importcert \
          -trustcacerts \
          -alias globalsign-rootca \
          -storetype PKCS12 \
          -keystore globalsign-rootca.p12 \
          -storepass changeit \
          -file globalsign.crt

# Add intermediate certs (Optional)
$ keytool -importcert \
          -keystore globalsign-rootca.p12 \
          -alias CA-intermediate \
          -storepass changeit \
          -file CA-intermediate.cer

# Create PKCS12 truststore using OpenSSL
$ openssl pkcs12 -export \
                 -jdktrust anyExtendedKeyUsage \
                 -nokeys \
                 -in server.pem \
                 -password pass: \
                 -out truststore-openssl.p12
              
# Show PKCS#12 info.
$ openssl pkcs12 -info -password pass:changeit -in globalsign-rootca.p12
$ keytool -list \
          -keystore globalsign-rootca.p12 \
          --storetype pkcs12 \
          -storepass changeit \
          -v

# OpenSSL: Create a new PKCS#12 store from certs
$ openssl pkcs12 -export -chain -out keystore.p12 \
                  -inkey private.key -password pass:test123 \
                  -in client.crt -certfile client.crt \
                  -CAfile cacert.crt -caname root-ca \
                  -name client-key

# Convert a PEM certificate file to PKCS#12 without private key.
$ openssl pkcs12 -export -nokeys -in certificate.pem -out keystore.p12

# Change the keystore password
# Convert PKCS#12 to PEM (don't encrypt private keys)
$ openssl pkcs12 -in keystore.p12 -out keystore.pem -nodes

# Export to PKCS#12 with new password
$ openssl pkcs12 -export -in keystore.pem -nodes -out keystore.p12

# Verify if a Private Key Matches a Certificate
$ openssl x509 -noout -modulus -in cert.pem | openssl md5
$ openssl rsa  -noout -modulus -in cert.key | openssl md5
  • Extract certs from PKCS#12
# Client Certificate (Remove "-clcerts" to include intermediate/root certs)
$ openssl pkcs12 -in keystore.p12 -nodes -clcerts -nokeys -passin pass:<password>  -out client.crt

# Certificate Key (Remove "-nodes" for encrypted)
$ openssl pkcs12 -in keystore.p12 -nodes -nocerts -passin pass:<password> -out client.key

# Decrypt Key
$ openssl rsa -in client-encrypted.key -passin pass:<password> -out client.key

# CA cert
$ openssl pkcs12 -in keystore.p12 -nodes -nokeys -cacerts -passin pass:<password> -out cacert.crt

# Remove attribtes (Optional)
# openssl pkcs12 -in keystore.p12 -nodes  -nokeys -passin pass:<password> | openssl x509 -out client.crt
# openssl pkcs12 -in keystore.p12 -nodes -nocerts -passin pass:<password> | openssl rsa -out client.key
# openssl pkcs12 -in keystore.p12 -nodes -nokeys -cacerts -passin pass:<password> | openssl x509 -out cacert.crt

# Convert to PKCS8 private key (For java)
$ openssl pkcs8 -topk8 -inform PEM -outform DER -in cert.pem -out out.pem -nocrypt
  • PEM to single line
$ awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}'  cert.pem > cert.cer
# Revert singleline to multiline
$ echo -ne $(cat cert.cer)
# Check if the reverted format is ok
$ echo -ne $(cat cert.cer) | openssl rsa -check
  • PEM to JSON
# Convert the PEM text to JSON
$ jq -sR . test.pem > test.txt
  • Show all certs from System truststore
# Using Openssl (CentOS/Ubuntu)
$ while openssl x509 -noout -subject -issuer -dates; do echo ........... ; done < $(find -L /etc/ssl/certs -regex ".*/ca-\(bundle\|certificates\).crt") 2>/dev/null | grep -i subject

# Using java keytool
$ keytool -printcert -file /etc/ssl/certs/ca-bundle.crt \
   | grep -i -e "Owner" -e "Issuer:" -e "Serial number:" -e "SHA256:"

OpenJDK

  • List all JDK cacerts using OpenSSL

    # Since JDK 18, cacert migrated to Password-Less PKCS12(https://jdk.java.net/18/release-notes#JDK-8275252)
    $ openssl pkcs12 \
              -cacerts \
              -chain \
              -nokeys \
              -nomacver \
              -in "$(find -L $JAVA_HOME -name cacerts)" \
              -passin pass: | grep -i "subject="
  • Show all JDK CA Certs using Keytool

    # JDK 17+
    $ keytool -list -rfc -cacerts
    
    # Or using cacerts location.
    $ JDK_CACERT="$(find -L "${JAVA_HOME:-$(dirname $(readlink -f "$(which java)"))/..}" -name cacerts -print -quit)"
    
    $ keytool -list \
              -rfc \
              -storetype pkcs12 \
              -storepass changeit \
              -keystore "${JDK_CACERT}"
    
    # Older JDKs
    $ keytool -list \
          -storetype jks \
          -storepass changeit \
          -keystore "${JDK_CACERT}"
  • Use Mac System truststore in Java

    $ java -Djavax.net.ssl.trustStoreType=KeychainStore \
           -Djavax.net.ssl.trustStore=/Library/Keychains/System.keychain \
           -jar app.jar

Self Signed Certs

Using OpenSSL

$ openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
          -keyout example.key -out example.pem \
          -subj "/C=US/ST=CA/L=SanJose/O=Company Name/OU=Org/CN=www.example.com" \
          -addext "subjectAltName=DNS:example.com,DNS:www.example.net,IP:10.0.0.1"

# For ECC
$ openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -days 3650 \
          -nodes -keyout example.key -out example.pem -subj "/CN=localhost" \
          -addext "subjectAltName=DNS:example.com,DNS:*.example.com,IP:127.0.0.1"

# See certificate details (in text format, no cert output)
$ openssl x509 -in example.pem -text -noout

# Instead of text form, just print subject/issuer/dates
$ openssl x509 -in example.pem -noout -subject -ext subjectAltName -issuer -dates  -fingerprint

# Show SAN entries
$ openssl x509 -text -in example.pem -noout | grep -A1 'Subject Alternative Name'
$ openssl x509 -text -noout -in example.pem -certopt no_subject,no_header,no_version,no_serial,no_signame,no_validity,no_issuer,no_pubkey,no_sigdump,no_aux

# Show public key of a cert
$ openssl x509 -in example.pem -pubkey -noout

# Get public key from a private key
$ openssl pkey -check -in example.key -pubout -outform PEM

# Check if the private key belongs to the cert
$ diff <(openssl x509 -pubkey -in example.pem -noout) <(openssl pkey -check -in example.key -pubout -outform PEM)

# OR create a test TLS server that will verify that a key and certificate match
$ openssl s_server -accept 443 -www -key example.key -cert example.pem

Using OpenJDK Keytool

# Generate self signed cert
$ keytool -genkeypair \
          -keyalg RSA \
          -keysize 4096 \
          -sigalg SHA256withRSA \
          -alias server \
          -storetype JKS \
          -keystore keystore.jks \
          -storepass changeit \
          -keypass changeit \
          -dname "CN=localhost, OU=app, O=app, L=Unspecified, ST=Unspecified, C=US" \
          -ext "SAN=dns:test.server.com,ip:127.0.0.1" \
          -validity 7200

# Migrate from  JKS to PKCS12 
$ keytool -importkeystore \
          -srckeystore keystore.jks \
          -srcstoretype JKS \
          -srcstorepass changeit \
          -destkeystore keystore.p12 \
          -deststoretype PKCS12 \
          -deststorepass changeit
          
# List cert entries
$ keytool -keystore keystore.jks -storepass changeit -list -v          

Add CACerts

  • To JDK Truststore

    #!/usr/bin/env bash
    
    certs=("https://pki.service.com/cacert1.crt"
           "https://pki.service.com/cacert2.crt")
    
    JDK_CACERT="$(find -L "${JAVA_HOME:-$(dirname $(readlink -f "$(which java)"))/..}" -name cacerts -print -quit)"
    echo "Using JDK CACert: ${JDK_CACERT}"
    
    pushd /tmp >/dev/null || exit 1
    
    for cert in "${certs[@]}"; do
      echo "Downloading $cert ..."
      cert_file="$(basename "$cert")"
      curl -fsSL "$cert" -o "${cert_file}"
    
      echo "Installing ${cert_file} ..."
      keytool -importcert \
              -noprompt \
              -trustcacerts \
              -file "${cert_file}" \
              -alias "${cert_file}" \
              -keystore "${JDK_CACERT}" \
              -storepass changeit
    
      rm -f "${cert_file}"
    done
    
    popd >/dev/null || exit 1

cURL: Auth/Mutual TLS

# mTLS Authentication using PKCS#12 bundle
$ curl -v \
       --cert-type P12 \
       --cert ~/keystore.p12:xxxxx \
       -X GET "https://my-server:443/api"


# Mutual TLS using PEM files
$ curl -v \
       --cacert ca.pem \
       --key client.key \
       --cert client.pem \
       --resolve "my-server:443:8.8.8.8" \
       -X GET "https://my-server:443/api"

CA Certs and Certificate Transparency Logs

GPG/OpenPGP

  • Setup GPG on MacOS - IntelliJ Doc

  • GPG Key Prepare

  • GPG commands

    # GPU key files
    $ ~/.gnupg
    
    # Show all keys
    $ gpg --list-keys --keyid-format=[long|short]
    
    # List secrets keys
    $ gpg --list-secret-keys --keyid-format=short
    
    # Update all keys from a keyserver
    $ gpg --refresh-keys [--keyserver pgp.mit.edu]
    
    $ gpg --recv-key XXXXXX
    $ gpg --delete-key  "xxx@gmail.com"
  • Renew GPG Key

    # Note: The private key can never expire
    
    # Get the key id
    $ gpg --list-keys --keyid-format SHORT
    
    # Comment out 'no-tty' in ~/.gnupg/gpg.conf
    $ gpg --edit-key C8B5XXXX
    $ gpg> list
           expire // type 1y
           key 1  // renew encryption subkey
           expire // type 1y
           trust
           save
           quit
    
    # Export for backup
    $ gpg -a --export C8B5XXXX > sureshg.gpg.public
    $ gpg -a --export-secret-keys C8B5XXXX > sureshg.gpg.private
    
    # Send it to key servers
    $ gpg --keyserver keyserver.ubuntu.com --send-keys C8B5XXXX
    $ gpg --keyserver pgp.mit.edu --send-keys C8B5XXXX
    
    # Update GPG key in Github
    $ cat sureshg.gpg.public| pbcopy
    $ https://github.com/settings/gpg/new
  • Change Secret Password

    $ gpg --list-secret-keys --keyid-format=short
    $ gpg --edit-key C8B5XXXX
    $ gpg>  passwd

Tools

TLS Debugging

$ java -Djavax.net.debug=help MyApp
# java -Djavax.net.debug=all MyApp
# java -Djavax.net.debug=ssl,handshake,data,trustmanager MyApp

help           print the help messages
expand         expand debugging information

all            turn on all debugging
ssl            turn on ssl debugging

The following can be used with ssl:
  record       enable per-record tracing
  handshake    print each handshake message
  keygen       print key generation data
  session      print session activity
  defaultctx   print default SSL initialization
  sslctx       print SSLContext tracing
  sessioncache print session cache tracing
  keymanager   print key manager tracing
  trustmanager print trust manager tracing
  pluggability print pluggability tracing

  handshake debugging can be widened with:
  data         hex dump of each handshake message
  verbose      verbose handshake message printing

  record debugging can be widened with:
  plaintext    hex dump of record plaintext
  packet       print raw SSL/TLS packets

Misc

TrustStore

Cryptography

  • https://www.udacity.com/course/applied-cryptography–cs387
  • https://www.coursera.org/learn/crypto#syllabus
Table of Contents