Guidelines for using PKCS12 Java KeyStore

Oracle NoSQL Database supports Java KeyStore in PKCS12 format. From the 22.1 release onward, NoSQL Database switched the KeyStore type of default security configuration created by makebootconfig or securityconfig utility to PKCS12.

Note:

Oracle recommends that you switch the KeyStore format of the existing security configuration to PKCS12, which is an industry-standard format.

Default Security Configuration

Starting from release 22.1, in the default security configuration, the database server KeyStore and TrustStore, typically named store.keys and store.trust respectively, are created in PKCS12 format and protected by password specified using -kspwd.

The TrustStore, client.trust, that is used by the client application is created in PKCS12 format and password-less, by default, if no password is specified using -ctspwd. Additionally, if the Java used to run the configuration utilities does not support password-less PKCS12 store, utilities fall back to create the client.trust in JKS format. The Java version supporting password-less PKCS12 must have security properties keystore.pkcs12.certProtectionAlgorithm and keystore.pkcs12.macAlgorithm available. The minimum JAVA versions required for this feature are JDK 8u301 for Java 8, JDK 11.0.12 for Java 11, and the first release of Java 17.

When creating the configuration, you can create the client.trust in PKCS12 format and protected by the password specified using -ctspwd. If you are using the client.trust protected by password, the password must be specified in the login properties file. The following two login properties are supported:
  • oracle.kv.ssl.trustStorePassword
  • oracle.kv.ssl.trustStorePasswordAlias

The client application can specify the password in the login properties file using the oracle.kv.ssl.trustStorePassword property or store the password in External Password Storage and specify only the alias name using the oracle.kv.ssl.trustStorePasswordAlias property.

Example:
#Security property settings for communication with KVStore servers using password
oracle.kv.ssl.trustStore=client.trust
oracle.kv.ssl.trustStoreType=PKCS12
oracle.kv.ssl.trustStorePassword=<client.trust password>
oracle.kv.ssl.protocols=TLSv1.3,TLSv1.2
oracle.kv.ssl.hostnameVerifier=dnmatch(CN\=NoSQL)
oracle.kv.transport=ssl

#Security property settings for communication with KVStore servers using password alias
oracle.kv.ssl.trustStore=client.trust
oracle.kv.ssl.trustStoreType=PKCS12
oracle.kv.ssl.trustStorePasswordAlias=cts
oracle.kv.ssl.protocols=TLSv1.3,TLSv1.2
oracle.kv.ssl.hostnameVerifier=dnmatch(CN\=NoSQL)
oracle.kv.transport=ssl
oracle.kv.auth.wallet.dir=<wallet_directory>
oracle.kv.auth.username=<user_name>

Updating KeyStore Type of an Existing Security Configuration

The security configuration created by releases earlier than NoSQL Database Release 22.1 generates all Java KeyStores in JKS format. You need to perform the following steps to upgrade Java KeyStores to PKCS12 format.

  1. Copy the existing security configuration directory from one of the NoSQL Database storage nodes.
  2. Run the following command to update the KeyStore to PKCS12 format:
    java -jar kvstore.jar securityconfig config update -secdir <security dir> -kstype PKCS12 [-ctspwd <client.trust password>]
    This command converts the existing KeyStore (store.keys) and TrustStore (store.trust) used by the NoSQL Database server to PKCS12 format and reuses the KeyStore password of stores in the existing configuration. Similar to the configuration creation, this command also creates a new password-less client.trust in PKCS12 format, if no password is specified using -ctspwd. If Java doesn't support the password-less PKCS12 store, it falls back to creating a JKS format client.trust.
  3. Run the show security configuration command to verify that the store type is updated to PKCS12 format.
    java -jar kvstore.jar securityconfig config show -secdir security
         Security parameters:
         certMode=shared
         internalAuth=ssl
         keystore=store.keys
         keystorePasswordAlias=keystore
         keystoreType=PKCS12
         securityEnabled=true
         truststore=store.trust
         truststoreType=PKCS12
         walletDir=store.wallet
         
         internal Transport parameters:
         ...
         Keystore: security/store.keys
         Keystore type: PKCS12
         Keystore provider: SUN
    
         Your keystore contains 1 entry
    
         shared, Feb 11, 2022, PrivateKeyEntry,
         Certificate fingerprint (SHA-256): AA:98:B8:C6...
    
         Keystore: security/store.trust
         Keystore type: PKCS12
         Keystore provider: SUN
    
         Your keystore contains 1 entry
    
         mykey, Feb 11, 2022, trustedCertEntry,
         Certificate fingerprint (SHA-256): AA:98:B8:C6...
  4. In the configuration directory, verify that there is a backup of each Java KeyStore named with the suffix '.old'.
    ls kvroot/security
         store.wallet
         store.trust.old
         store.trust
         store.keys.old
         store.keys
         security.xml
         client.trust.old
         client.trust
         client.security
  5. Verify that the base login properties file, client.security, is updated with PKCS12 format.
    cat security/client.security
         #Security property settings for communication with KVStore servers
         #Fri Feb 11 10:59:39 PST 2022
         oracle.kv.ssl.trustStore=client.trust
         oracle.kv.ssl.trustStoreType=PKCS12
         oracle.kv.ssl.protocols=TLSv1.2
         oracle.kv.ssl.hostnameVerifier=dnmatch(CN\=NoSQL)
         oracle.kv.transport=ssl
  6. Copy the updated security directory to each server node (Storage Node) and replace the old security configuration directory. Then, check that all Replication Nodes are online and restart each Storage Node sequentially. Make sure that the last one you restarted is completely up before continuing to the next SN.
    java -jar $KVHOME/lib/kvstore.jar stop -root
        /Users/my_name/tmp/kvroot/kvroot1
        (~/hg/kv/kvstore)=> java -jar $KVHOME/lib/kvstore.jar start -root $KVROOT1 &
    
        kv-> ping
        Pinging components of store HSRStore based upon topology sequence #18
        10 partitions and 3 storage nodes
        Time: 2021-09-04 08:52:02 UTC Version: 21.2.16 
        Shard Status: healthy:1 writable-degraded:0 read-only:0 offline:0
        Admin Status: healthy
        Zone [name=Austin id=zn1 type=PRIMARY allowArbiters=false]
        RN Status: online:3 offline:0 maxDelayMillis:0 maxCatchupTimeSecs:0
        Storage Node [sn1] on localhost:5000    Zone: [name=Austin
        id=zn1 type=PRIMARY allowArbiters=false]   
    
        Status: RUNNING   Ver: 21.2.16 2021-09-04 08:52:02 UTC  Build id: 0d00330822fc
                Admin [admin1] Status: RUNNING,MASTER
                Rep Node [rg1-rn1]   Status: RUNNING,REPLICA
        sequenceNumber:62 haPort:5011 delayMillis:0 catchupTimeSecs:0
    
        Storage Node [sn2] on localhost:6000 Zone: [name=Austin
        id=zn1 type=PRIMARY allowArbiters=false]
        Status: RUNNING Ver: 21.2.16 2021-09-04 08:52:02 UTC Build id: 0d00330822fc
                Rep Node [rg1-rn2] Status: RUNNING,MASTER
        sequenceNumber:62 haPort:6010
    
        Storage Node [sn3] on localhost:7000 Zone: [name=Austin
        id=zn1 type=PRIMARY allowArbiters=false]
        Status: RUNNING Ver: 21.2.16 2021-09-04 08:52:02 UTC Build id: 0d00330822fc
              Rep Node [rg1-rn3] Status: RUNNING,REPLICA
        sequenceNumber:62 haPort:7010 delayMillis:0 catchupTimeSecs:0
    
        Rep Node [rg1-rn1] Status: RUNNING,REPLICA is up, now restart the next SN
        (~/hg/kv/kvstore)=> java -jar $KVHOME/lib/kvstore.jar stop -root /Users/my_name/tmp/kvroot/kvroot2
        kv->ping
        Pinging components of store HSRStore based upon topology sequence #18
        10 partitions and 3 storage nodes
        Time: 2021-09-04 08:52:02 UTC Version: 21.2.16
        Shard Status: healthy:0 writable-degraded:1 read-only:0 offline:0
        Admin Status: healthy
    
        Zone [name=Austin id=zn1 type=PRIMARY allowArbiters=false]
        RN Status: online:2 offline:1 maxDelayMillis:? maxCatchupTimeSecs:?
        Storage Node [sn1] on localhost:5000 Zone: [name=Austin id=zn1 type=PRIMARY allowArbiters=false]
        Status: RUNNING Ver: 21.2.16 2021-09-04 08:54:02  UTC Build id: 0d00330822fc
            Admin [admin1] Status: RUNNING,MASTER
            Rep Node [rg1-rn1]   Status: RUNNING,REPLICA
        sequenceNumber:62 haPort:5011
    
        Storage Node [sn2] on localhost:6000
        Zone: [name=Austin id=zn1 type=PRIMARY allowArbiters=false] UNREACHABLE
           Rep Node [rg1-rn2] Status: UNREACHABLE
    
        Storage Node [sn3] on localhost:7000
        Zone: [name=Austin id=zn1 type=PRIMARY allowArbiters=false]
        Status: RUNNING Ver: 21.2.16 2021-09-04 08:54:02 UTC Build id: 0d00330822fc
           Rep Node [rg1-rn3] Status: RUNNING,REPLICA
        sequenceNumber:62 haPort:7010 delayMillis:? catchupTimeSecs:?
    
        (~/hg/kv/kvstore)=> java -jar $KVHOME/lib/kvstore.jar start -root $KVROOT2 & kv->ping
        Pinging components of store HSRStore based upon topology sequence #18
        10 partitions and 3 storage nodes
        Time: 2021-09-04 08:55:02 UTC Version: 21.2.16
        Shard Status: healthy:1 writable-degraded:0 read-only:0 offline:0
        Admin Status: healthy
        Zone [name=Austin id=zn1 type=PRIMARY allowArbiters=false]
        RN Status: online:3 offline:0 maxDelayMillis:1 maxCatchupTimeSecs:0
        Storage Node [sn1] on localhost:5000 Zone: [name=Austin id=zn1 type=PRIMARY allowArbiters=false]
        Status: RUNNING Ver: 21.2.16 2021-09-04 08:55:02 UTC Build id: 0d00330822fc
            Admin [admin1] Status: RUNNING,MASTER
            Rep Node [rg1-rn1]   Status: RUNNING,REPLICA
        sequenceNumber:63 haPort:5011
        Storage Node [sn2] on localhost:6000
        Zone: [name=Austin id=zn1 type=PRIMARY allowArbiters=false]
        Status: RUNNING Ver: 21.2.16 2021-09-04 08:55:02 UTC Build id: 0d00330822fc
           Rep Node [rg1-rn2] Status: RUNNING,REPLICA
        sequenceNumber:63 haPort:6010 delayMillis:1 catchupTimeSecs:0
        Storage Node [sn3] on localhost:7000
        Zone: [name=Austin id=zn1 type=PRIMARY allowArbiters=false]
        Status: RUNNING Ver: 21.2.16 2021-09-04 08:55:02 UTC Build id: 0d00330822fc
          Rep Node [rg1-rn3] Status: RUNNING,REPLICA
        sequenceNumber:63 haPort:7010 delayMillis:1 catchupTimeSecs:0

Updating SSL Keys and Certificates

When updating the SSL keys and certificates with a new security configuration using Guidelines for Updating SSL Keys and Certificates, the merge-trust command automatically converts the merged truststore (store.trust) used by the NoSQL Database server to PKCS12 format and protected by the original KeyStore password of the existing security configuration. It also creates a new password-less client.trust in PKCS12 format if no password is specified using -ctspwd. If the Java used to run merge-trust command doesn't support the password-less PKCS12 store, it falls back to create a JKS client.trust.

After updating the key and certificate, if you want to keep KeyStore and truststore in JKS format, you need to create the new security configuration to be merged by running the following command:
java -jar $KVHOME/lib/kvstore.jar securityconfig config /
create -root /Users/my_name/tmp/kvroot/newKey -kspwd 123456 -kstype JKS