All roads lead to Rome – Importing custom TLS certificate into Oracle wallet

It appears that Oracle’s preferred way to get a certificate into a wallet is by generating a key pair and then create certificate signing request using “orapki” (that’s what you mostly see in the docs and on MOS). Once the request is singed by the CA you import the certificate into the wallet.
But, there are situations where you don’t get to create the signing request from the Oracle wallet. For instance, at one of my clients, they create everything at the CA and just send a PKCS#12 file to the DBAs. Since PKCS is a standard and the Oracle wallet itself is a PKCS#12 file one could (naively) assume that these things are compatible. Unfortunately, this is not always the case. When trying to generate an SSO file with “orapki” from an openssl created PKCS#12 file I get the following error:

Exception in thread "main" java.lang.NullPointerException
        at oracle.security.pki.OracleKeyStoreSpi.a(Unknown Source)
        at oracle.security.pki.OracleSSOKeyStoreSpi.a(Unknown Source)
        at oracle.security.pki.OracleFileWalletImpl.b(Unknown Source)
        at oracle.security.pki.OracleWallet.saveLSSO(Unknown Source)
        at oracle.security.pki.textui.OracleWalletTextUI.create(Unknown Source)
        at oracle.security.pki.textui.OracleWalletTextUI.command(Unknown Source)
        at oracle.security.pki.textui.OraclePKITextUI.main(Unknown Source)

This is just one example, I’ve encountered other problems when trying to work with PKCS#12 files that were created by tools other than “orapki” (or mkstore). Therefore you should always create the PKCS#12 file using “orapki” and then work from there.
I’m going to show a few practical ways how to import a “pre-created” custom TLS certificate into an Oracle wallet.

Assuming we get a PKCS#12 file containing everything we need:

  • Root certificate
  • Intermediate certificated
  • Private key
  • Signed certificate
ORACLE_WALLET_LOC=/home/oracle/wallet
ORACLE_WALLET_PWD=*****
SOURCE_PKCS12_FILE/home/oracle/custom-ca.p12
SOURCE_PKCS12_PWD=*****

orapki wallet create -wallet "${ORACLE_WALLET_LOC}" -compat_v12 -pwd "${ORACLE_WALLET_PWD}"
orapki wallet import_pkcs12 \
    -wallet "${ORACLE_WALLET_LOC}" \
   -pkcs12file "${SOURCE_PKCS12_FILE}" \
   -pkcs12pwd "${SOURCE_PKCS12_PWD}" \
   -pwd "${ORACLE_WALLET_PWD}"
orapki wallet create -wallet "${ORACLE_WALLET_LOC}" -compat_v12 -auto_login_local -pwd "${ORACLE_WALLET_PWD}"
orapki wallet display -wallet "${ORACLE_WALLET_LOC}"

Maybe we get a Java key store (JKS) containing everything:

ORACLE_WALLET_LOC=/home/oracle/wallet
ORACLE_WALLET_PWD=*****
SOURCE_JKS_FILE=/home/oracle/custom-ca.jks
SOURCE_JKS_PWD=*****

orapki wallet create -wallet "${ORACLE_WALLET_LOC}" -compat_v12 -pwd "${ORACLE_WALLET_PWD}"
orapki wallet jks_to_pkcs12 \
    -wallet "${ORACLE_WALLET_LOC}" \
    -keystore "${SOURCE_JKS_FILE}" \
    -jkspwd "${SOURCE_JKS_PWD}" \
    -pwd "${ORACLE_WALLET_PWD}"
orapki wallet create -wallet "${ORACLE_WALLET_LOC}" -compat_v12 -auto_login_local -pwd "${ORACLE_WALLET_PWD}"
orapki wallet display -wallet "${ORACLE_WALLET_LOC}"

Or, we might get everything as individual base64 encoded files:

  • root.cer
  • inter.cer
  • private-pwd.key (password protected)
  • custom.cer
CERT_FILES_LOC=/home/oracle
ORACLE_WALLET_LOC=/home/oracle/wallet
ORACLE_WALLET_PWD=*****
PRIVATE_KEY_PWD=*****

orapki wallet create -wallet "${ORACLE_WALLET_LOC}" -compat_v12 -pwd "${ORACLE_WALLET_PWD}"
orapki wallet add \
    -wallet "${ORACLE_WALLET_LOC}" \
    -trusted_cert \
    -cert "${CERT_FILES_LOC}/root.cer" \
    -pwd "${ORACLE_WALLET_PWD}"
orapki wallet add \
    -wallet "${ORACLE_WALLET_LOC}" \
    -trusted_cert \
    -cert "${CERT_FILES_LOC}/inter.cer" \
    -pwd "${ORACLE_WALLET_PWD}"
orapki wallet import_private_key \
    -wallet "${ORACLE_WALLET_LOC}" \
    -pvtkeyfile "${CERT_FILES_LOC}/private-pwd.key" \
    -pvtkeypwd "${PRIVATE_KEY_PWD}" \
    -cert "${CERT_FILES_LOC}/custom.cer" \
    -pwd "${ORACLE_WALLET_PWD}"
orapki wallet create -wallet "${ORACLE_WALLET_LOC}" -compat_v12 -auto_login_local -pwd "${ORACLE_WALLET_PWD}"
orapki wallet display -wallet "${ORACLE_WALLET_LOC}"

“Helper functions”
Extracting individual components from a PKCS#12 file:

CERT_FILES_LOC=/home/oracle
SOURCE_PKCS12_FILE/home/oracle/custom-ca.p12
SOURCE_PKCS12_PWD=*****
PRIVATE_KEY_PWD=*****

# extract private key from PKCS#12 file
openssl pkcs12 -nocerts -in "${SOURCE_PKCS12_FILE}" -out "${CERT_FILES_LOC}/private-pwd.key" -password pass:"${SOURCE_PKCS12_PWD}" -passout pass:"${PRIVATE_KEY_PWD}"
# cleanup file: remove Bag/Key Attribute information
sed -i -n '/-BEGIN ENCRYPTED PRIVATE KEY-/,/-END ENCRYPTED PRIVATE KEY-/p' "${CERT_FILES_LOC}/private-pwd.key"

# remove passphrase from private key file (!!!security risk!!!)
openssl rsa -in "${CERT_FILES_LOC}/private-pwd.key" -out "${CERT_FILES_LOC}/private-nopwd.key" -passin pass:"${PRIVATE_KEY_PWD}"

# extract certificate from PKCS#12 file
openssl pkcs12 -clcerts -nokeys -in "${SOURCE_PKCS12_FILE}" -out "${CERT_FILES_LOC}/custom.cer" -password pass:"${SOURCE_PKCS12_PWD}"

# extract root and intermediate certs from PKCS#12 file
#   manually split ca-chain.cer into root.cer and inter.cer
openssl pkcs12 -in "${SOURCE_PKCS12_FILE}" -cacerts -nokeys -chain -out "${CERT_FILES_LOC}/ca-chain.cer" -password pass:"${SOURCE_PKCS12_PWD}"

Create PKCS#12 file with “openssl”:

CERT_FILES_LOC=/home/oracle
TARGET_PKCS12_FILE/home/oracle/opennssl.p12
TARGET_PKCS12_PWD=*****
PRIVATE_KEY_PWD=*****

cat "${CERT_FILES_LOC}/root.cer" "${CERT_FILES_LOC}/inter.cer" > "${CERT_FILES_LOC}/ca-chain.cer"
openssl pkcs12 -export -out "${TARGET_PKCS12_FILE}" -inkey "${CERT_FILES_LOC}/private-pwd.key" -in "${CERT_FILES_LOC}/custom.cer" -certfile "${CERT_FILES_LOC}/ca-chain.cer" -password pass:"${TARGET_PKCS12_PWD}" -passin pass:"${PRIVATE_KEY_PWD}"

Convert a PKCS#12 file to Java key store (JKS):

OPENSSL_PKCS12_FILE=/home/oracle/wallet/openssl.p12
OPENSSL_PKCS12_PWD=*****
JKS_FILE=/home/oracle/wallet/keystore.jks
JKS_PWD=*****

keytool -v -importkeystore -srckeystore "${OPENSSL_PKCS12_FILE}" -srcstoretype pkcs12 -srcstorepass "${OPENSSL_PKCS12_PWD}" -destkeystore "${JKS_FILE}" -deststoretype jks -deststorepass "${JKS_PWD}"

Footnote: tested “orapki” from Oracle 19.5 database home

One thought on “All roads lead to Rome – Importing custom TLS certificate into Oracle wallet

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.