Cryptography

Hash Functions

  • Generally, when verifying a hash visually, you can simply look at the first and last four characters of the string.

SHA-1

  • Message digest

    • 160 bit
  • Use cases

    • Authentication by comparing the checksum of passwords

    • File verification by comparing the checksum of files

Public Key Certificate

SSL/TLS

Mutual TLS

Java

Create a PKCS#12 TrustStore containing the CA certificate

keytool -importcert -noprompt \
    -storetype PKCS12 \
    -keystore "${CA-crt.p12}" \
    -storepass $TRUSTSTORE_PASSWORD \
    -alias $CA_KEYENTRY_ALIAS \
    -file "${CA-crt.pem}"

Convert a JKS KeyStore to PKCS#12 KeyStore

  • Note: private keys cannot be exported from a JKS KeyStore directly, the KeyStore has to be converted to a PKCS#12 KeyStore first.
keytool -importkeystore \
        -srckeystore <old-keystore-path> \
        -srcstoretype jks \
        -srcstorepass <old-keystore-password> \
        -destkeystore <new-keystore-path> \
        -deststoretype pkcs12 \
        -deststorepass <new-keystore-password>

Get a certificate in a PKCS#12 KeyStore

  • keytool -list -v -keystore <domain.p12> -storetype PKCS12 -storepass <EXPORT_PASSWORD>

Get the alias name of a PrivateKeyEntry in the KeyStore

  • keytool -list -v -keystore <domain.p12> -storetype PKCS12 -storepass <EXPORT_PASSWORD> | grep Alias

Get entries in the current JRE TrustStore

Default password: changeit

  • keytool -list -v -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit

    or

  • keytool -list -v -cacerts -storepass changeit (Java SE 11+)

Get the content of a certificate of a service

  • keytool -printcert -v -sslserver <host:port>

Get the content of a certificate of a service in PEM format

  • keytool -printcert -v -rfc -sslserver <host:port>

Get/Validate the content of a local certificate

  • keytool -printcert -v -file "$domain-crt.pem"/"$domain-crt.der"

Get the content of a CSR / Validate a CSR file

  • keytool -printcertreq -v -file <csr.pem>

Import a CA certificate (DER) into the JRE TrustStore

  • keytool -importcert -alias <entry_alias> -cacerts -storepass <truststore-password:changeit> -file <CA-crt.der>

Import a certificate (DER) into a Keystore

  • keytool -importcert -keystore <keystore-file> -storepass <keystore-password:changeit> -storetype <PKCS12 / JKS> -alias <unique-alias> -file "$domain-crt.der" -noprompt

Delete an entry from a Keystore

  • keytool -delete -alias <alias> -keystore <domain-crt.p12> -storetype <PKCS12 / JKS> -storepass <password>

Export a certificate (DER format) from a Keystore

keytool -exportcert \
  -keystore $keystore \
  -storetype $store_type \
  -storepass $keystore_password \
  -alias $alias \
  -file $target_der_file

Java cryptography libraries

OpenSSL

Generate a private key

# Use `ed25519` algorithm
openssl genpkey -algorithm ED25519 > "$private.pem"
# Use `RSA` algorithm with `2048` bits
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 > "$private.pem"

Get the public key of the given private key

Can be used to verify if a private key matches a public key

openssl pkey -in "$private.pem" -pubout -out "$public.pem"

or

cat "$private.pem" | openssl pkey -pubout > "$public.pem"

Generate a CA private key and CA certificate pair with supplied CA Subject

  • CA Subject (Distinguished Name) -> CA private key & CA certificate

    openssl req -x509 -newkey rsa:2048 -noenc -days $number_of_days_to_be_valid \
    -config "$CA-csr.cnf" -keyout "$CA-private.key" > "$CA-crt.pem"

Generate (Sign) a domain CSR with the domain private key

  • Domain Subject (X.500 Distinguished Name) + Domain private key -> Domain CSR

    openssl req -new -key "$domain-private.pem" -config "$domain-csr.cnf" > "$domain-csr.pem"
    # domain.csr.cnf
    [req]
    default_bits = 2048
    prompt = no
    default_md = sha256
    distinguished_name = dn
     
    [dn]
    C=<ISO_COUNTRY_CODE>
    ST=<STATE>
    L=<CITY>
    O=<ORGANIZATION_FULL_NAME>
    OU=<DEPARTMENT_NAME>
    emailAddress=<SERVER_ADMIN_EMAIL_ADDRESS>
    CN=<FQDN>

    CN should match the domain you are trying to access, e.g. localhost.

  • Resources

Sign a domain CSR with CA private key and create a domain certificate

  1. Prepare a X.509 v3 Certificate Extensions file

    # X.509 v3 Certificate Extensions
    # Reference: https://www.openssl.org/docs/man1.1.1/man5/x509v3_config.html
    # domain.v3.ext
    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName = @alt_names
     
    # When CN in CSR doesn't match the domain of URL, DNS names listed here will be used instead.
    # When using curl to access target URL, with -v flag, you will see the following
    # subjectAltName: host "localhost" matched cert's "localhost"
    [alt_names]
    DNS.1 = localhost
    DNS.2 = cq.prototype.microservice.springboot
  2. Create the certificate

    CSR + CA private key -> domain certificate

    # CA Private key pass phrase will be prompted if any
    openssl x509 -req \
      -CA "$CA-crt.pem" \
      -CAkey "$CA-private.pem" \
      -extfile "$domain-v3.ext.cnf" \
      -days $days \
      -CAcreateserial \ # will generate a <CA.srl> file to be used for future signing with option -CAserial
      -in "$domain-csr.pem" \
      -out "$domain-crt.pem"

Create a PKCS#12 keystore to store private key and certificate

openssl pkcs12 \
  -export \
  -name $entry_alias \
  -inkey "$domain-private.pem" \
  -in "$domain-crt.pem" \
  -out "$keystore.p12" \
  -passout pass:$keystore_password \
  -noiter \
  -nomaciter
 
# Use either OpenSSL or Java keytool to view certificate
# OpenSSL
openssl pkcs12 -nokeys -info \
  -in "$keystore.p12" \
  -passin pass:$keystore_password
 
# Java keytool
keytool -list -v -keystore "$keystore.p12" -storetype PKCS12 -storepass $keystore_password

Export everything from a PKCS#12 Keystore

openssl pkcs12 \
  -in "$keystore.p12" \
  -out "$keystore.crt.pem" \
  -passin pass:$keystore_password

Only export client certificates from a PKCS#12 Keystore

openssl pkcs12 \
  -clcerts \
  -in "$keystore.p12" \
  -out "$keystore.crt.pem" \
  -passin pass:$keystore_password

Only export private keys from a PKCS#12 Keystore

openssl pkcs12 \
  -nocerts \
  -in "$keystore.p12" \
  -out <keystore.key.pem> \
  -passin pass:$keystore_password

Get contents of a PEM certificate file

openssl x509 -text -noout -in "$domain-crt.pem"

Get the fingerprint / thumbprint of a PEM certificate file

# SHA-1 fingerprint
openssl x509 -in "$domain-crt.pem" -noout -fingerprint -sha1
# SHA-256 fingerprint
openssl x509 -in "$domain-crt.pem" -noout -fingerprint -sha256

Get contents of a DER-encoded certificate file

openssl x509 -text -noout -inform der -in "$domain-crt.der"

Convert PEM certificate to DER

openssl x509 -outform der -in "$domain-crt.pem" -out "$domain-crt.der"

Convert DER-encoded certificate to PEM

openssl x509 -inform der -in "$domain-crt.der" -out "$domain-crt.pem"

Passphrase input options

  • Options

    • pass:password

      Literals, will be recorded in shell history

    • env:var

      The name of the environment variable storing the passphrase

    • file:pathname

      The first line of the file located at pathname will be used as the passphrase

    • fd:number

      Read the password from the file descriptor number. This can be used to send the data via a pipe for example.

    • stdin

      Default option if no other option is explicitly specified

  • OpenSSL passphrase options (opens in a new tab)

Get the contents of a PEM private key file

Without specifying passphrase, will be prompted for passphrase from stdin

openssl rsa -text -noout -in "${private.pem}"

With passphrase

openssl rsa -text -noout -in "${private.pem}" -passin pass:$passphrase

Decrypt an encrypted private key

openssl rsa \
  -in $encrypted_key_pem \
  -passin pass:$passphrase \
  -out $decrypted_key_pem

Sign a text file and encode signature with Base64

Sign with SHA-256 algorithm

openssl dgst -sha256 -sign ${private.pem} -out ${signature.sha256} ${file-to-be-signed}

Encode the signature with Base64

openssl enc -base64 -in ${signature.sha256} -out ${signature.sha256.base64}

Verify a domain certificate against an intermediate CA certificate

openssl verify -untrusted ${intermediate-CA-crt.pem} ${domain-crt.pem}

Get all ciphers

Get all supported ciphers

openssl ciphers -v

Get supported SSL protocols

openssl ciphers -v | awk '{print $2}' | sort | uniq

Get the contents of a CSR

openssl req -in ${domain-csr.pem} -noout -text

Get the public key of a CSR

openssl req -in ${domain-csr.pem} -noout -pubkey

Can be used to compare if 2 CSRs are signed by the same private key

Connect to and disconnect from a remote SSL server automatically

echo | openssl s_client -connect $host:$port

or

openssl s_client -connect $host:$port < /dev/null

Get the remote site’s root and intermediate certificates

CA certificates have the same Subject and Issuer.

openssl s_client -showcerts -connect $host:$port

Get the serial number of the domain certificate

openssl s_client -connect $host:$port 2>/dev/null | openssl x509 -noout -text | grep -A 1 "Serial Number"

Example:

 openssl s_client -connect localhost:8443 2>/dev/null | openssl x509 -noout -text | grep -A 1 "Serial Number"
        Serial Number:
            70:7f:c8:68:b4:aa:48:4c:70:9e:8b:bd:48:fc:c0:a0:cc:80:4b:65

Get the SHA-1 fingerprint of the domain certificate

Fingerprint with :

openssl s_client -connect $host:$port 2> /dev/null | openssl x509 -noout -fingerprint

Fingerprint without :

openssl s_client -connect $host:$port 2> /dev/null | openssl x509 -noout -fingerprint | tr -d ":"

Get the SHA-1 fingerprint of the domain certificate with sha1sum

openssl s_client -connect $host:$port 2>/dev/null | openssl x509 -outform DER | sha1sum

Get the SHA-256 fingerprint of the domain certificate with sha256sum

openssl s_client -connect $host:$port 2>/dev/null | openssl x509 -outform DER | sha256sum

Get the SHA-256 fingerprint of the domain certificate

Fingerprint with :

openssl s_client -connect $host:$port 2> /dev/null | openssl x509 -noout -fingerprint -sha256

Get the start and expiry dates of the certificate

openssl s_client -connect $host:$port 2> /dev/null | openssl x509 -noout -dates

Connect to the specified remote host and port with SSL/TLS client interactively

  • Can be used to test if the specified host and TCP ports are open

    Display certificate

    openssl s_client -connect $host:$port

    Doesn't display certificate, brief info only

    openssl s_client -brief -connect $host:$port

Send protocol specific message

openssl s_client -connect $host:$port -starttls $protocol

Verify if hostname matches DNS name in Subject Alternative Name or Common Name in the subject certificate

openssl s_client -connect $host:$port -verify_hostname $hostname -brief

Test TLS connection with SNI

openssl s_client -connect $host:$port -servername $hostname

Test TLS connection with client certificate (mutual TLS)

openssl s_client -connect $host:$port -key ${keystore-containing-both-key-and-certificate.pem} -keyform PEM|DER|P12 -pass pass:$keystore_password

Verify if TLS v1.3 is used for the service

openssl s_client -tls1_3 -brief -connect $host:$port

Verify the domain certificate

openssl verify -CAfile ${ca-crt.pem} ${domain-crt.pem}

Get all DNS entries in SAN and CN in Subject of a remote server certificate

openssl s_client -connect $host:$port -showcerts 2> /dev/null | openssl x509 -noout -subject -ext subjectAltName | tr "," "\n" | grep -E "\\bDNS\\b|\\bCN\\b" | tr -d " " | sort | grep -E "[a-z0-9\\.\\*\\-]+"

Get public key's fingerprint

Use private key PEM as input

openssl rsa -pubout -outform DER -in ${private.pem} | openssl md5|sha1|sha256 -c

Use public key PEM as input

openssl rsa -pubin -outform DER -in ${public.pem} | openssl md5|sha1|sha256 -c

Show OpenSSL version and config

openssl version -a

References