Java Keytool is a key pair and certificate management tool that is used to manipulate Java Keystores, and is included with Java. A Java Keystore is a container for authorization certificates or public key certificates, and is often used by Java-based applications for encryption, authentication, and serving over HTTPS. Its entries are protected by a keystore password. A keystore entry is identified by an alias, and it consists of keys and certificates that form a trust chain.

Public–key cryptography uses a public key to encrypt a piece of data, such as a password, then the recipient uses the private key to decrypt the data. The public and private keys are known as a key pair.

KeyStore Manager is a JavaScript extension library replacement for the Java command-line utilities Java Keytool and jarsigner.

KeyStoreManager can be used from SWT UI interface launched from Axional DBStudio.

1 Creating a keystore

You can create a new KeyStore of any of the following formats:

JKS Java Key Store (default till java 9). This keystore is Java specific, it usually has an extension of jks. This type of keystore can contain private keys and certificates, but it cannot be used to store secret keys. Since it's a Java specific keystore, so it cannot be used in other programming languages.
JCEKS JCE key store. This keystore has an extension of jceks. The entries which can be put in the JCEKS keystore are private keys, secret keys and certificates.
PKCS12 PKCS12 is a standard keystore type (default since java 9) which can be used in Java and other languages. This type is portable and can be operated with other libraries written in other languages such as C, C++ or C#. It usually has an extension of p12 or pfx. You can store private keys, secret keys and certificates on this type.
BKS-V1 Bouncy Castle BKS version 1. Notice that this keystore files use an HMAC that is only 16 bits long, which can allow an attacker to compromise the integrity of a BKS-V1 keystore.
BKS BKS a keystore format provided by the popular third party Java cryptographic library provider -- BouncyCastle. It is a keystore similar to the JKS provided by Oracle JDK.
UBER UBER is a BouncyCastle Keystore. UBER keystores are similar to BKS, but they have an additional design goal: protect the store from introspection. This is done by additionally encrypting the entire keystore using (a key derived from) the store password.
BCFKS Unlike PKCS12, the BCFKS format can store certificates, private keys, and some types of secret key. The key store is built around AES-256, SHA-512, and the NIST PBKDF, with PKCS#8 EncryptedPrivateKeyInfo structures being used to carry private keys and octet strings containing wrapped secret keys where required.

Copy
<script>

    // Create a new (empty) KeyStore in PKCS12 format
    var ks = new Ax.ks.KeyStoreManager('PKCS12');

    // Write to file using given password
    ks.writeTo(new Ax.io.File("/tmp/keystore.p12"), 'secret');
</script>
Dialog for keystore generation in Eclipse SWT

2 KeyStore and certificate examples

Before start, let's explain some keystores and certificates we will use in the following examples. It consists of sample collection of X.509 digital certificates with associated public/private keys in Java Key Store (.jks) format.

Examples contains Keys and certiciates for 4 owners:

  1. swviewca (A self signed certificate authority)
  2. myservice (Meant to be used with a service - like a Web service)
  3. jack (Represents a client that uses the service)
  4. johnie (Represents another client that uses the service)

They are stored in 4 keystores for the above 4 principles. What's included in Java Key Store (.jks) files is described below.


File Type Password Content
swviewca.jks Keystore secret
  • public/private keys of swviewca
  • self signed certificate
myservice.jks Keystore secret
  • public/private keys of myservice
  • swviewca signed certificate of myservice
  • swviewca signed certificate of jack
  • swviewca signed certificate of johnie
  • swviewca's certificate
jack.jks Keystore secret
  • public/private keys of jack
  • swviewca signed certificates of jack
  • swviewca signed certificate of myservice
  • swviewca's certificate
johnnie.jks Keystore secret
  • public/private keys of johnie
  • swviewca signed certificates of johnie
  • swviewca signed certificate of myservice
  • swviewca's certificate

In each keystore the alias password is moon.

3 Opening and inspecting a KeyStore

To open an existin keystore you can use the static loaded in KeyStoreManager class. It accepts any convetible to inputStream like http, https, file or base64 URI resource.

To iterate over keystore content, you can get a ResultSet for KeyStore entries by using the toResultSet method.

Copy
<script>
    // load using https: (for a file use file:filename)
    var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
    console.log(ks.toResultSet());
</script>
+--------------+----+------+---------+---------+-------+-------------------+-----------------------+
|type          |lock|expiry|name     |algorithm|keysize|cerificate_expiry  |last_modified          |
+--------------+----+------+---------+---------+-------+-------------------+-----------------------+
|KeyPairEntry  |true|false |jack     |RSA      |   1024|2024-03-18T07:33:18|2019-03-22T17:06:06.714|
|TrustCertEntry|    |false |myservice|RSA      |   1024|2024-03-18T07:33:03|2010-07-10T08:33:19.914|
|TrustCertEntry|    |false |swviewca |RSA      |   1024|2026-12-13T07:32:55|2010-07-10T08:33:19.109|
+--------------+----+------+---------+---------+-------+-------------------+-----------------------+

A more advanced example, iterating keypairs included in an existing keystore and getting its entries

Copy
<script>
    var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
    
     // iterate entries in keystore
    for (var row of ks.toResultSet()) {
        var alias = row.name;
        console.log("======================== " + alias + "========================");
        console.log(row);
        console.log(ks.getEntryType(alias));
        if (ks.getEntryType(row.name) == "KeyPairEntry")
            console.log("   " + ks.getPublicKey(alias));
        if (ks.getEntryType(row.name) == "TrustCertEntry")
            console.log("   " + ks.getCertificate(alias));
    }
</script>
======================== jack========================
{keysize=1024, cerificate_expiry=Mon Mar 18 07:33:18 CET 2024, name=jack, lock=true, expiry=false, type=KeyPairEntry, last_modified=Fri Mar 22 17:06:06 CET 2019, algorithm=RSA}
KeyPairEntry
   RSA Public Key [72:b0:1e:89:74:82:ac:7a:2c:11:e9:e1:8b:ea:00:37:6d:11:8d:1c]
            modulus: a8022c5ebbb6916ccd5e276b8326a90dbec6766854c0d171d6b3a2983caed91ac937db08bf4662d81d0aa75c5242204f59a6d76edb77c01d4bcd2d8fd7db4c0be316ec14d8cf49918389fdbd2a1afa64c9dc46bafefe16f7b6bbd3505210e953c72b1596daa03be0f7803f6e355a638823635cfdc5957af0e386839d7c267b7b
    public exponent: 10001

======================== myservice========================
{keysize=1024, cerificate_expiry=Mon Mar 18 07:33:03 CET 2024, name=myservice, lock=null, expiry=false, type=TrustCertEntry, last_modified=Sat Jul 10 08:33:19 CEST 2010, algorithm=RSA}
TrustCertEntry
   [
[
  Version: V3
  Subject: CN=My Test Service, OU=Training, O=Software View, L=Colombo, ST=Western, C=LK
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

....

3.1 Unlock an entry

Entries may be secured with password. It's content (KeyPair or certificate) will not be accessible until unlocked. To unlock an entry simplye use:

Copy
<script>
    // laod using https: (for a file use file:filename)
    var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
    ks.unlockEntry("jack", "moon");
    console.log(ks.toResultSet());
</script>
+--------------+-----+------+---------+---------+-------+-------------------+-----------------------+
|type          |lock |expiry|name     |algorithm|keysize|cerificate_expiry  |last_modified          |
+--------------+-----+------+---------+---------+-------+-------------------+-----------------------+
|KeyPairEntry  |false|false |jack     |RSA      |   1024|2024-03-18T07:33:18|2019-03-22T17:06:06.714|
|TrustCertEntry|     |false |myservice|RSA      |   1024|2024-03-18T07:33:03|2010-07-10T08:33:19.914|
|TrustCertEntry|     |false |swviewca |RSA      |   1024|2026-12-13T07:32:55|2010-07-10T08:33:19.109|
+--------------+-----+------+---------+---------+-------+-------------------+-----------------------+

4 Modifying Keystore

4.1 Change Keystore Password

You can change KeyStore password prior to save it or provide password as an argument before write.

Copy
<script>

    // Open an existing PKCS12 Keystore
    var ks = new Ax.ks.KeyStoreManager(new Ax.io.File("/tmp/keystore.p12"), 'secret');
    
    // Change keystore password
    ks.setPassword('NewPass');
    ks.writeTo(new Ax.io.File("/tmp/keystore_new.p12"));

    // Open keystore with new password
    var ks2 = new Ax.ks.KeyStoreManager(new Ax.io.File("/tmp/keystore_new.p12"), 'NewPass');
    // Show keystore content
    console.log(ks2.toResultSet());
	
    // Now, we'll save keystore with provided password
    ks.writeTo(new Ax.io.File("/tmp/keystore_tok.p12"), "PassToken");
	
    // Open keystore with PassToken
    var ks2 = new Ax.ks.KeyStoreManager(new Ax.io.File("/tmp/keystore_tok.p12"), 'PassToken');
    // Show keystore content
    console.log(ks2.toResultSet());

</script>
+------------+----+------+-------+---------+-------+----------------------------+-------------+
|type        |lock|expiry|name   |algorithm|keysize|cerificate_expiry           |last_modified|
+------------+----+------+-------+---------+-------+----------------------------+-------------+
|KeyPairEntry|true|false |alias  |RSA      |   2048|Thu Mar 19 12:28:45 CET 2020|             |
+------------+----+------+-------+---------+-------+----------------------------+-------------+

+------------+----+------+-------+---------+-------+----------------------------+-------------+
|type        |lock|expiry|name   |algorithm|keysize|cerificate_expiry           |last_modified|
+------------+----+------+-------+---------+-------+----------------------------+-------------+
|KeyPairEntry|true|false |alias  |RSA      |   2048|Thu Mar 19 12:28:45 CET 2020|             |
+------------+----+------+-------+---------+-------+----------------------------+-------------+

4.2 Delete key pair

Deleting a key pair implies removing it from KeyStore. Changes will not take effect until KeyStore is saved.

Copy
<script>
    var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
    console.log(ks.toResultSet());
    ks.deleteKeyPair("jack");
    console.log(ks.toResultSet());
</script>
+--------------+----+------+---------+---------+-------+-----------------------+------------------------+
|type          |lock|expiry|name     |algorithm|keysize|cerificate_expiry      |last_modified           |
+--------------+----+------+---------+---------+-------+-----------------------+------------------------+
|KeyPairEntry  |true|false |jack     |RSA      |   1024|2024-03-18 07:33:18 CET|2019-03-22 17:06:06 CET |
|TrustCertEntry|    |false |myservice|RSA      |   1024|2024-03-18 07:33:03 CET|2010-07-10 08:33:19 CEST|
|TrustCertEntry|    |false |swviewca |RSA      |   1024|2026-12-13 07:32:55 CET|2010-07-10 08:33:19 CEST|
+--------------+----+------+---------+---------+-------+-----------------------+------------------------+

+--------------+----+------+---------+---------+-------+-----------------------+------------------------+
|type          |lock|expiry|name     |algorithm|keysize|cerificate_expiry      |last_modified           |
+--------------+----+------+---------+---------+-------+-----------------------+------------------------+
|TrustCertEntry|    |false |myservice|RSA      |   1024|2024-03-18 07:33:03 CET|2010-07-10 08:33:19 CEST|
|TrustCertEntry|    |false |swviewca |RSA      |   1024|2026-12-13 07:32:55 CET|2010-07-10 08:33:19 CEST|
+--------------+----+------+---------+---------+-------+-----------------------+------------------------+

4.3 Rename Alias

Renaming a key pair implies changing it's alias name. Changes will not take effect until KeyStore is saved.

Copy
<script>
    var ks = new Ax.ks.KeyStoreManager(new Ax.io.File("/tmp/keystore.p12"), 'secret');
    console.log(ks.toResultSet());
    
    // Unlock keypair to be able to rename
    ks.unlockEntry("alias", "changeit");

    ks.renameKeyPair("alias", "alias2");
    console.log(ks.toResultSet());
</script>
+------------+----+------+-------+---------+-------+----------------------------+-------------+
|type        |lock|expiry|name   |algorithm|keysize|cerificate_expiry           |last_modified|
+------------+----+------+-------+---------+-------+----------------------------+-------------+
|KeyPairEntry|true|false |alias  |RSA      |   2048|Thu Mar 19 12:28:45 CET 2020|             |
+------------+----+------+-------+---------+-------+----------------------------+-------------+

+------------+-----+------+------+---------+-------+----------------------------+-------------+
|type        |lock |expiry|name  |algorithm|keysize|cerificate_expiry           |last_modified|
+------------+-----+------+------+---------+-------+----------------------------+-------------+
|KeyPairEntry|false|false |alias2|RSA      |   2048|Thu Mar 19 12:28:45 CET 2020|             |
+------------+-----+------+------+---------+-------+----------------------------+-------------+

5 Creating Keystore Entries

This section covers methods that are related to generating key pairs and certificates.

5.1 Generate Keys in New/Existing Keystore

Use this method if you want to use HTTP (HTTP over TLS) to secure your Java application. This will create a new key pair in a new or existing Java Keystore, which can be used to create a CSR, and obtain an SSL certificate from a Certificate Authority.

You can create key pairs using RSA, DSA or EC key pair types.

This command generates a 2048-bit RSA key pair, under the specified alias (domain) and password, in the specified keystore object. The Distinguished Name (X500name) is supplied as a consumer function.

Copy
<script>
// openssl genrsa -out privatekey.pem 2048
// openssl req -new -x509 -key privatekey.pem -out publickey.cer
// openssl pkcs12 -export -out public_privatekey.p12 -inkey privatekey.pem -in publickey.cer
// openssl pkcs12 -in public_privatekey.p12 -nokeys | openssl x509 -dates -email -alias -issuer -subject -noout
// openssl pkcs12 -in public_privatekey.p12 -info 

var ks = new Ax.ks.KeyStoreManager('PKCS12');

ks.generateKeyPair("alias1", "alias1", "RSA", 2048, config => {
	config.setCommonName("CN");
	config.setOrganisationUnit("OU");
	config.setOrganisationName("ON");
	config.setLocalityName("LN");
	config.setStateName("SN");
	config.setCountryCode("CC");
	config.setEmailAddress("EA");
    // Start date on next year (from now)
	config.setValidityStart(new Ax.sql.Date().addYear(1));
	// And give a vaility of 60 days
	config.setValidityEnd(60);
});

</script>

6 Exporting Keys and Certificates

You can export keys and certificates from your KeyStore using different data formats. Let's first take a look at them.

6.1 Export KeyPair

You can export a KeyPair using PKCS#12 or PEM encoding format.

Format Description
PKCS#12

PKCS#12 defines an archive file format for storing many cryptography objects as a single file. It is commonly used to bundle a private key with its X.509 certificate or to bundle all the members of a chain of trust.

A PKCS #12 file may be encrypted and signed. The internal storage containers, called "SafeBags", may also be encrypted and signed. A few SafeBags are predefined to store certificates, private keys and CRLs. Another SafeBag is provided to store any other data at individual implementer's choice.[1][2]

PKCS #12 is one of the family of standards called Public-Key Cryptography Standards (PKCS) published by RSA Laboratories.

The filename extension for PKCS #12 files is ".p12" or ".pfx

PEM

Privacy-Enhanced Mail (PEM) is a de facto file format for storing and sending cryptographic keys, certificates, and other data, based on a set of 1993 IETF standards defining "privacy-enhanced mail." While the original standards were never broadly adopted, and were supplanted by PGP and S/MIME, the textual encoding they defined became very popular. The PEM format was eventually formalized by the IETF in RFC 7468.

Many cryptography standards use ASN.1 to define their data structures, and Distinguished Encoding Rules (DER) to serialize those structures.[1] Because DER produces binary output, it can be challenging to transmit the resulting files through systems, like electronic mail, that only support ASCII. The PEM format solves this problem by encoding the binary data using base64. PEM also defines a one-line header, consisting of:

"-----BEGIN ", a label, and "-----", and a one-line footer, consisting of "-----END ", a label, and "-----".

The label determines the type of message encoded. Common labels include "CERTIFICATE", "CERTIFICATE REQUEST", "PRIVATE KEY" and "X509 CRL".

PEM data is commonly stored in files with a ".pem" suffix, a ".cer" or ".crt" suffix (for certificates), or a ".key" suffix (for public or private keys).[2] The label inside a PEM file represents the type of the data more accurately than the file suffix, since many different types of data can be saved in a ".pem" file.

A PEM file may contain multiple instances. For instance, an operating system might provide a file containing a list of trusted CA certificates, or a web server might be configured with a "chain" file containing an end-entity certificate plus a list of intermediate certificates.

6.1.1 Export KeyPair as PKCS12

PKCS#12 format returns a byte[].

Copy
<script>
 	var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");

	ks.unlockEntry("jack", "moon");
    var pkcs12 = ks.exportKeyPairAsPKCS12("jack", "secret2");
    new Ax.io.File("/tmp/jack.p12").write(pkcs12);
    console.log(pkcs12);
</script>
00000000 30 82 0B CF 02 01 03 30 82 0B 88 06 09 2A 86 48 0......0.....*.H
00000010 86 F7 0D 01 07 01 A0 82 0B 79 04 82 0B 75 30 82 .........y...u0.
00000020 0B 71 30 82 03 1D 06 09 2A 86 48 86 F7 0D 01 07 .q0.....*.H.....
00000030 01 A0 82 03 0E 04 82 03 0A 30 82 03 06 30 82 03 .........0...0..
00000040 02 06 0B 2A 86 48 86 F7 0D 01 0C 0A 01 02 A0 82 ...*.H..........
00000050 02 B3 30 82 02 AF 30 29 06 0A 2A 86 48 86 F7 0D ..0...0)..*.H...
00000060 01 0C 01 03 30 1B 04 14 74 B2 46 2D 23 80 05 BA ....0...t.F-#...
00000070 1F FC 85 E1 0F AE 70 97 B9 89 CF CC 02 03 00 C3 ......p.........
00000080 50 04 82 02 80 D2 44 9F 4D CC EF 36 4D 9E CB 5A P.....D.M..6M..Z
00000090 FE 22 A8 52 9D E6 BE 08 69 33 D8 16 75 D3 46 3E .".R....i3..u.F>
2877 byte(s) more

6.1.2 Export KeyPair as PEM

PEM format returns a ASCII String.

Copy
<script>
	var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
	ks.unlockEntry("jack", "moon");
    
    var pem = ks.exportKeyPairAsPEM("jack", "secret2");
    new Ax.io.File("/tmp/jack.pem").write(pem);
    console.log(pem);
</script>
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIICojAcBgoqhkiG9w0BDAEDMA4ECJNqsSC022DWAgIEKwSCAoBp6ldJCZ28KKou
oHgRPnILlPj9vMPT1ptmch70/SfEKpFK3wpiwebxUcAD8ncn2N64eO8EJjozUSTK
puEbWvlpsBPTYncdKMrcwvhuP6wcQKySkFz2wBZdlSn1BsbLCKeNF9NYnJy4W/T2
AS7Al5jFKTaG/HT2VfN8A6EQ52QNKL1F8bFnR3q7ibD97Q4q4JVSnyMOCitRehjs
x+n8D5K5y/HF/MGZ2xmUJGAUWOOVSoyEub/7tkwP4/6b8M7UR2bkckm8BI1oLC+z
l8FTvjX3/EMygH1Al4zjbNIqDohZnwNkWeRvQ8J9fFDEWP0P2/hBHAwRyJih/Xa4
lbcTMxqQnB7KJnTE7NY3KPRiwFmsDzj78G1sl8FOFCI8BMB/WFpX7uMid1SVVtxK
cg6ZLmC3Mhg4Q7FnttZLF6jl8eRZ/Wy95k68AI7dN5ut5eWU61a4s8+Iuq6R5CL3
tj4/lVHN0XFdBA7AaJ6eQtXOWHL3eW8rpKzhIdQauxaQJcj7mF4UA6UVEuDObWwn
pxsAaYyyV43BKYFrluQhAzW8OCI7wGnRKf62aMdIB3yfq3thjUF1PcyG3FPi4+ZG
nMGfPSusUne/MYXfGKh7Z0qrIRxgW6WmCkDq9egLD3WHBPefy6mYB7rEG8hCf7wb
IPiQA6syXwub+toSUETzEa/fQwST3j66vpD6i2ji206FQMdKBVHUNZod2xgR1nSq
TNqxj8n4JbuLVRkaoA9q+zm5dvUl8HIOHW+ECh2eC7qM8F9l/hymXvDe00deXODi
vTlga4stgbvtUpYF5s3HHDBavd0G1tiNvDs5ccpAz2xF7OwNrgyJCc3JCHpmMvtt
FTrPXeLZ
-----END ENCRYPTED PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIC9jCCAl+gAwIBAgIJAParOnPwEkKlMA0GCSqGSIb3DQEBBQUAMIGKMQswCQYD
VQQGEwJMSzEQMA4GA1UECBMHV2VzdGVybjEQMA4GA1UEBxMHQ29sb21ibzEWMBQG
A1UEChMNU29mdHdhcmUgVmlldzERMA8GA1UECxMIVHJhaW5pbmcxLDAqBgNVBAMT
I1NvZnR3YXJlIFZpZXcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDcxMDA2
MzMxOFoXDTI0MDMxODA2MzMxOFowcjELMAkGA1UEBhMCTEsxEDAOBgNVBAgTB1dl
c3Rlcm4xEDAOBgNVBAcTB0NvbG9tYm8xFjAUBgNVBAoTDVNvZnR3YXJlIFZpZXcx
ETAPBgNVBAsTCFRyYWluaW5nMRQwEgYDVQQDEwtKYWNrIERhbmllbDCBnzANBgkq
hkiG9w0BAQEFAAOBjQAwgYkCgYEAqAIsXru2kWzNXidrgyapDb7GdmhUwNFx1rOi
mDyu2RrJN9sIv0Zi2B0Kp1xSQiBPWabXbtt3wB1LzS2P19tMC+MW7BTYz0mRg4n9
vSoa+mTJ3Ea6/v4W97a701BSEOlTxysVltqgO+D3gD9uNVpjiCNjXP3FlXrw44aD
nXwme3sCAwEAAaN7MHkwCQYDVR0TBAIwADAdBgNVHQ4EFgQUDp+pbeXQHmYiubDc
tF8b+C4g6V0wHwYDVR0jBBgwFoAU1rdiaEM7sE7BtSqZhTWT9Tqn9RQwLAYJYIZI
AYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMA0GCSqGSIb3
DQEBBQUAA4GBACcLqPwC9cATSqe+Kes5r6kcgo8eN3QME+HVSQocFSaRVrZ8iOrl
0NAXway2JOGdjIFCn2gU4NAkrDAzjJ1AlwrfCT/1FDL5hu4BTdY13ZpwBf5MU6LB
6x2tc+Jbo4bQrskEEIfGpOcyuB/wBJtJQeONjLuY2ouX9pvaaHj2cpzS
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDhzCCAvCgAwIBAgIJANoN6RLOJhj7MA0GCSqGSIb3DQEBBQUAMIGKMQswCQYD
VQQGEwJMSzEQMA4GA1UECBMHV2VzdGVybjEQMA4GA1UEBxMHQ29sb21ibzEWMBQG
A1UEChMNU29mdHdhcmUgVmlldzERMA8GA1UECxMIVHJhaW5pbmcxLDAqBgNVBAMT
I1NvZnR3YXJlIFZpZXcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDcxMDA2
MzI1NVoXDTI2MTIxMzA2MzI1NVowgYoxCzAJBgNVBAYTAkxLMRAwDgYDVQQIEwdX
ZXN0ZXJuMRAwDgYDVQQHEwdDb2xvbWJvMRYwFAYDVQQKEw1Tb2Z0d2FyZSBWaWV3
MREwDwYDVQQLEwhUcmFpbmluZzEsMCoGA1UEAxMjU29mdHdhcmUgVmlldyBDZXJ0
aWZpY2F0ZSBBdXRob3JpdHkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJgo
2C8xtpSjesmsZeVkiLNJe7XqjMLIAr+htrOhW/T2rV9ht0kuqhxfUqrejguJxibv
+Nqd1/VuNV5ZPnpUxvx8nzLNeSBzznYvpPNO+fnr9YsdWoYBhTUTKJXyzgKA/mLp
SALujiFrHCHFWKx5jEB1Dc6w5C+Y+7Kj7A3LCg29AgMBAAGjgfIwge8wDAYDVR0T
BAUwAwEB/zAdBgNVHQ4EFgQU1rdiaEM7sE7BtSqZhTWT9Tqn9RQwgb8GA1UdIwSB
tzCBtIAU1rdiaEM7sE7BtSqZhTWT9Tqn9RShgZCkgY0wgYoxCzAJBgNVBAYTAkxL
MRAwDgYDVQQIEwdXZXN0ZXJuMRAwDgYDVQQHEwdDb2xvbWJvMRYwFAYDVQQKEw1T
b2Z0d2FyZSBWaWV3MREwDwYDVQQLEwhUcmFpbmluZzEsMCoGA1UEAxMjU29mdHdh
cmUgVmlldyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCCQDaDekSziYY+zANBgkqhkiG
9w0BAQUFAAOBgQBbDIVh5BPJeI/X1hd87Ej2OuIWh+10IEPiRxb+6gHYG1/c7hb4
fXRHGaDVtAeHH0FkFiifZiVpOZkidsTkD+UKAUzYo1uo8AvfG1dx6JzccSNnWIvf
2I/YrWMHefx4KdyCt/DtRqnOHooRm18Gnqs6dZ/FHKOu1HDCRjD2kTccTw==
-----END CERTIFICATE-----

6.2 Export Certificate chain

You can export a KeyPair certificate or certificate chain using any of the following formats. Some suport PEM encoding while others not.

Format Cert head (PEM) Cert chain (PEM) Extension
X509     .cer
PKCS7     .p7b
PKIPATH     .pkipath
SPC     .spc

Copy
<script>
    var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
    console.log(ks.toResultSet());
    
    var pem = ks.exportKeyPairCertificate("jack", config => {
    	config.setExportFormat("X509");
    	config.setPemEncode(true);
    	config.setExportChain(false);
    });
    console.log(new Ax.lang.String(pem));
</script>
+--------------+----+------+---------+---------+-------+-----------------------+------------------------+
|type          |lock|expiry|name     |algorithm|keysize|cerificate_expiry      |last_modified           |
+--------------+----+------+---------+---------+-------+-----------------------+------------------------+
|KeyPairEntry  |true|false |jack     |RSA      |   1024|2024-03-18 07:33:18 CET|2019-03-22 17:06:06 CET |
|TrustCertEntry|    |false |myservice|RSA      |   1024|2024-03-18 07:33:03 CET|2010-07-10 08:33:19 CEST|
|TrustCertEntry|    |false |swviewca |RSA      |   1024|2026-12-13 07:32:55 CET|2010-07-10 08:33:19 CEST|
+--------------+----+------+---------+---------+-------+-----------------------+------------------------+

00000000 2D 2D 2D 2D 2D 42 45 47 49 4E 20 43 45 52 54 49 -----BEGIN CERTI
00000010 46 49 43 41 54 45 2D 2D 2D 2D 2D 0A 4D 49 49 43 FICATE-----.MIIC
00000020 39 6A 43 43 41 6C 2B 67 41 77 49 42 41 67 49 4A 9jCCAl+gAwIBAgIJ
00000030 41 50 61 72 4F 6E 50 77 45 6B 4B 6C 4D 41 30 47 AParOnPwEkKlMA0G
00000040 43 53 71 47 53 49 62 33 44 51 45 42 42 51 55 41 CSqGSIb3DQEBBQUA
00000050 4D 49 47 4B 4D 51 73 77 43 51 59 44 0A 56 51 51 MIGKMQswCQYD.VQQ
00000060 47 45 77 4A 4D 53 7A 45 51 4D 41 34 47 41 31 55 GEwJMSzEQMA4GA1U
00000070 45 43 42 4D 48 56 32 56 7A 64 47 56 79 62 6A 45 ECBMHV2VzdGVybjE
00000080 51 4D 41 34 47 41 31 55 45 42 78 4D 48 51 32 39 QMA4GA1UEBxMHQ29
00000090 73 62 32 31 69 62 7A 45 57 4D 42 51 47 0A 41 31 sb21ibzEWMBQG.A1
936 byte(s) more
-----BEGIN CERTIFICATE-----
MIIC9jCCAl+gAwIBAgIJAParOnPwEkKlMA0GCSqGSIb3DQEBBQUAMIGKMQswCQYD
VQQGEwJMSzEQMA4GA1UECBMHV2VzdGVybjEQMA4GA1UEBxMHQ29sb21ibzEWMBQG
A1UEChMNU29mdHdhcmUgVmlldzERMA8GA1UECxMIVHJhaW5pbmcxLDAqBgNVBAMT
I1NvZnR3YXJlIFZpZXcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDcxMDA2
MzMxOFoXDTI0MDMxODA2MzMxOFowcjELMAkGA1UEBhMCTEsxEDAOBgNVBAgTB1dl
c3Rlcm4xEDAOBgNVBAcTB0NvbG9tYm8xFjAUBgNVBAoTDVNvZnR3YXJlIFZpZXcx
ETAPBgNVBAsTCFRyYWluaW5nMRQwEgYDVQQDEwtKYWNrIERhbmllbDCBnzANBgkq
hkiG9w0BAQEFAAOBjQAwgYkCgYEAqAIsXru2kWzNXidrgyapDb7GdmhUwNFx1rOi
mDyu2RrJN9sIv0Zi2B0Kp1xSQiBPWabXbtt3wB1LzS2P19tMC+MW7BTYz0mRg4n9
vSoa+mTJ3Ea6/v4W97a701BSEOlTxysVltqgO+D3gD9uNVpjiCNjXP3FlXrw44aD
nXwme3sCAwEAAaN7MHkwCQYDVR0TBAIwADAdBgNVHQ4EFgQUDp+pbeXQHmYiubDc
tF8b+C4g6V0wHwYDVR0jBBgwFoAU1rdiaEM7sE7BtSqZhTWT9Tqn9RQwLAYJYIZI
AYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMA0GCSqGSIb3
DQEBBQUAA4GBACcLqPwC9cATSqe+Kes5r6kcgo8eN3QME+HVSQocFSaRVrZ8iOrl
0NAXway2JOGdjIFCn2gU4NAkrDAzjJ1AlwrfCT/1FDL5hu4BTdY13ZpwBf5MU6LB
6x2tc+Jbo4bQrskEEIfGpOcyuB/wBJtJQeONjLuY2ouX9pvaaHj2cpzS
-----END CERTIFICATE-----

6.3 Export Public Key

You can export a KeyPair private key identified by it's alias in binary or PEM format.

Copy
<script>

    var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
    console.log(ks.toResultSet());
    
    var pub = ks.exportKeyPairPublicKey("jack", false); 
    console.log(pub);
    var pem = ks.exportKeyPairPublicKey("jack", true); 
    console.log(pem);

</script>
00000000 30 81 9F 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 0..0...*.H......
00000010 05 00 03 81 8D 00 30 81 89 02 81 81 00 A8 02 2C ......0........,
00000020 5E BB B6 91 6C CD 5E 27 6B 83 26 A9 0D BE C6 76 ^...l.^'k.&....v
00000030 68 54 C0 D1 71 D6 B3 A2 98 3C AE D9 1A C9 37 DB hT..q....<....7.
00000040 08 BF 46 62 D8 1D 0A A7 5C 52 42 20 4F 59 A6 D7 ..Fb....\RB OY..
00000050 6E DB 77 C0 1D 4B CD 2D 8F D7 DB 4C 0B E3 16 EC n.w..K.-...L....
00000060 14 D8 CF 49 91 83 89 FD BD 2A 1A FA 64 C9 DC 46 ...I.....*..d..F
00000070 BA FE FE 16 F7 B6 BB D3 50 52 10 E9 53 C7 2B 15 ........PR..S.+.
00000080 96 DA A0 3B E0 F7 80 3F 6E 35 5A 63 88 23 63 5C ...;...?n5Zc.#c\
00000090 FD C5 95 7A F0 E3 86 83 9D 7C 26 7B 7B 02 03 01 ...z.....|&{{...
12 byte(s) more
00000000 2D 2D 2D 2D 2D 42 45 47 49 4E 20 50 55 42 4C 49 -----BEGIN PUBLI
00000010 43 20 4B 45 59 2D 2D 2D 2D 2D 0A 4D 49 47 66 4D C KEY-----.MIGfM
00000020 41 30 47 43 53 71 47 53 49 62 33 44 51 45 42 41 A0GCSqGSIb3DQEBA
00000030 51 55 41 41 34 47 4E 41 44 43 42 69 51 4B 42 67 QUAA4GNADCBiQKBg
00000040 51 43 6F 41 69 78 65 75 37 61 52 62 4D 31 65 4A QCoAixeu7aRbM1eJ
00000050 32 75 44 4A 71 6B 4E 76 73 5A 32 0A 61 46 54 41 2uDJqkNvsZ2.aFTA
00000060 30 58 48 57 73 36 4B 59 50 4B 37 5A 47 73 6B 33 0XHWs6KYPK7ZGsk3
00000070 32 77 69 2F 52 6D 4C 59 48 51 71 6E 58 46 4A 43 2wi/RmLYHQqnXFJC
00000080 49 45 39 5A 70 74 64 75 32 33 66 41 48 55 76 4E IE9Zptdu23fAHUvN
00000090 4C 59 2F 58 32 30 77 4C 34 78 62 73 0A 46 4E 6A LY/X20wL4xbs.FNj
122 byte(s) more

6.4 Export Private Key

You can export Private Key using any of the following formats. Some suport PEM encoding while others not.

Format ... Extension
PKV

Microsoft PVK encoded RSA and DSS (DSA)

.pkv
PKCS#8

PKCS #8 is a standard syntax for storing private key information. PKCS #8 is one of the family of standards called Public-Key Cryptography Standards (PKCS) created by RSA Laboratories.

The PKCS #8 private key may be encrypted with a passphrase using the PKCS #5 standards, which supports multiple ciphers.

PKCS #8 private keys are typically exchanged in the PEM base64-encoded format

.pkcs8
OPEN SSL

OpenSSL private key encoding

.key

6.4.1 Export as PKV

To export a Private Key in PVK format:

Copy
<script>
    var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
    ks.unlockEntry("jack", "moon");
    var data = ks.exportKeyPairPrivateKeyAsPKV("jack", "password");
    console.log(data);
</script>
00000000 1E F1 B5 B0 00 00 00 00 01 00 00 00 01 00 00 00 ................
00000010 10 00 00 00 54 02 00 00 70 BF BC 2C B1 88 D8 CF ....T...p..,....
00000020 F0 A1 22 D3 84 47 29 2A 07 02 00 00 00 A4 00 00 .."..G)*........
00000030 A9 4A AC BB 03 AA 89 FA 11 FE 9B 96 77 5D 20 79 .J..........w] y
00000040 67 8D 4A 87 6F FC F3 9C 3C 8B 11 B7 50 50 37 36 g.J.o...<...PP76
00000050 ED C1 D0 C0 B1 72 15 6F 25 68 EF 53 F6 81 25 A6 .....r.o%h.S..%.
00000060 FB 85 C3 02 07 73 08 42 CD 1E 1B BD 02 2D BD 2F .....s.B.....-./
00000070 B8 85 60 05 F7 DA BB 0E 83 5B 23 8D F2 0D 76 79 ..`......[#...vy
00000080 EC C0 5F 21 1A 1C CE 9A 00 21 73 F5 3C C6 35 5A .._!.....!s.<.5Z
00000090 12 74 2E 3A AF D6 75 04 A3 9A C7 90 02 CB 04 73 .t.:..u........s
486 byte(s) more

6.4.2 Export as PKCS8

You can export Private Key using any of the supported encryption algorithms for PKCS#8.

Copy
<script>
    console.log(Ax.ks.KeyStoreManager.Pkcs8PbeTypes);
</script>
[SHA1_3KEY_DESEDE, SHA1_40BIT_RC2, SHA1_40BIT_RC4, SHA1_2KEY_DESEDE, SHA1_128BIT_RC4, SHA1_128BIT_RC2]

To export a Private Key in PKCS#8 format with PEM encode and default algorithm:

Copy
<script>
    var ks = Ax.ks.KeyStoreManager.load("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
    ks.unlockEntry("jack", "moon");
    var data = ks.exportKeyPairPrivateKeyAsPKCS8("jack", "password");
    console.log(data);
</script>
00000000 2D 2D 2D 2D 2D 42 45 47 49 4E 20 45 4E 43 52 59 -----BEGIN ENCRY
00000010 50 54 45 44 20 50 52 49 56 41 54 45 20 4B 45 59 PTED PRIVATE KEY
00000020 2D 2D 2D 2D 2D 0A 4D 49 49 43 6F 6A 41 63 42 67 -----.MIICojAcBg
00000030 6F 71 68 6B 69 47 39 77 30 42 44 41 45 46 4D 41 oqhkiG9w0BDAEFMA
00000040 34 45 43 4D 75 50 74 43 76 51 30 78 6A 72 41 67 4ECMuPtCvQ0xjrAg
00000050 49 47 4B 77 53 43 41 6F 41 54 30 4C 6F 48 61 32 IGKwSCAoAT0LoHa2
00000060 6D 41 4B 62 6D 6F 0A 6F 63 42 39 62 69 6D 6E 51 mAKbmo.ocB9bimnQ
00000070 32 77 61 33 37 4E 73 2F 4B 47 63 4A 48 45 50 6E 2wa37Ns/KGcJHEPn
00000080 75 71 36 50 42 34 59 70 65 44 55 38 66 72 6B 38 uq6PB4YpeDU8frk8
00000090 6D 52 41 35 44 73 39 37 50 32 4B 2F 6E 31 45 6F mRA5Ds97P2K/n1Eo
843 byte(s) more

You can disable PEM encoding or algorithm using:

Copy
ks.exportKeyPairPrivateKeyAsPKCS8("jack", "password", false, Ax.ks.KeyStoreManager.Pkcs8PbeTypes.SHA1_3KEY_DESEDE);

6.4.3 Export as OPEN SSL

You can export Private Key using any of the supported encryption algorithms for OPEN SSL.

Copy
<script>
    console.log(Ax.ks.KeyStoreManager.OpenSslPbeTypes);
</script>
[DES_CBC, AES_128BIT_CBC, DESEDE_CBC, AES_256BIT_CBC, AES_192BIT_CBC]

To export a Private Key in Open SSL format with PEM encode and default algorithm:

Copy
<script>
    var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
    ks.unlockEntry("jack", "moon");
    var data = ks.exportKeyPairPrivateKeyAsOpenSSL("jack", "password");
    console.log(data);
</script>
00000000 2D 2D 2D 2D 2D 42 45 47 49 4E 20 52 53 41 20 50 -----BEGIN RSA P
00000010 52 49 56 41 54 45 20 4B 45 59 2D 2D 2D 2D 2D 0A RIVATE KEY-----.
00000020 50 72 6F 63 2D 54 79 70 65 3A 20 34 2C 45 4E 43 Proc-Type: 4,ENC
00000030 52 59 50 54 45 44 0A 44 45 4B 2D 49 6E 66 6F 3A RYPTED.DEK-Info:
00000040 20 41 45 53 2D 32 35 36 2D 43 42 43 2C 45 36 30  AES-256-CBC,E60
00000050 32 46 42 32 42 35 30 34 38 41 31 42 30 38 44 34 2FB2B5048A1B08D4
00000060 33 37 32 36 42 43 42 45 41 43 45 39 39 0A 0A 33 3726BCBEACE99..3
00000070 30 65 52 65 2F 41 70 74 4F 74 70 4A 75 41 71 56 0eRe/AptOtpJuAqV
00000080 7A 35 44 4A 4B 75 4C 30 44 6F 64 7A 74 63 62 6B z5DJKuL0Dodztcbk
00000090 49 46 73 79 4A 64 75 51 49 78 59 46 51 4E 57 67 IFsyJduQIxYFQNWg
836 byte(s) more

You can disable PEM encoding or algorithm using:

Copy
ks.exportKeyPairPrivateKeyAsOpenSSL("jack", "password", false, Ax.ks.KeyStoreManager.OpenSslPbeTypes.AES_256BIT_CBC);

7 Importing Keys and Certificates

This section describes how to import an existing private/public key pair into Java keystore.

Copy
<script>
    // laod using https: (for a file use file:filename)
    var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
    console.log(ks.toResultSet());
</script>
+--------------+----+------+---------+---------+-------+-------------------+-----------------------+
|type          |lock|expiry|name     |algorithm|keysize|cerificate_expiry  |last_modified          |
+--------------+----+------+---------+---------+-------+-------------------+-----------------------+
|KeyPairEntry  |true|false |jack     |RSA      |   1024|2024-03-18T07:33:18|2019-03-22T17:06:06.714|
|TrustCertEntry|    |false |myservice|RSA      |   1024|2024-03-18T07:33:03|2010-07-10T08:33:19.914|
|TrustCertEntry|    |false |swviewca |RSA      |   1024|2026-12-13T07:32:55|2010-07-10T08:33:19.109|
+--------------+----+------+---------+---------+-------+-------------------+-----------------------+

When importing a new key pair, if the KeyStore already contains one with the same alias it will be replaced.

7.1 Import PKCS 12 key pair

Copy
<script>
    // Load PKCS #12 private key file from resources
    var privateKey = new Ax.net.URL("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jack-files/jack.p12");
    
    // importKeyPairPrivateKeyAsPkcs12(alias, keypair_new_pass, importing_keypair_file, keypair_pass)
    ks.importKeyPairPrivateKeyAsPkcs12("jack_pkcs12", "moon", privateKey, "moon");
    console.log(ks.toResultSet());
</script>
+--------------+-----+------+-----------+---------+-------+-----------------+-------------+
|type          |lock |expiry|name       |algorithm|keysize|cerificate_expiry|last_modified|
+--------------+-----+------+-----------+---------+-------+-----------------+-------------+
|KeyPairEntry  |true |false |jack       |RSA      |   1024|Mar 18, 2024     |Mar 22, 2019 |
|KeyPairEntry  |false|false |jack_pkcs12|RSA      |   1024|Mar 18, 2024     |Jul 10, 2019 |
|TrustCertEntry|     |false |myservice  |RSA      |   1024|Mar 18, 2024     |Jul 10, 2010 |
|TrustCertEntry|     |false |swviewca   |RSA      |   1024|Dec 13, 2026     |Jul 10, 2010 |
+--------------+-----+------+-----------+---------+-------+-----------------+-------------+

7.2 Import PKCS 8 key pair

Copy
<script>
    // Load PKCS #8 private key file from resources
    var privateKey = new Ax.net.URL("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jack-files/jack.pkcs8");
    
    // Load certificates for previously loaded private key
    var certificates = new Ax.net.URL("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jack-files/jack.cer");
    
    ks.importKeyPairPrivateKeyAsPkcs8("jack_pkcs8", "newPassword", privateKey, certificates, "moon");
    console.log(ks.toResultSet());
</script>
+--------------+-----+------+-----------+---------+-------+-----------------+-------------+
|type          |lock |expiry|name       |algorithm|keysize|cerificate_expiry|last_modified|
+--------------+-----+------+-----------+---------+-------+-----------------+-------------+
|KeyPairEntry  |true |false |jack       |RSA      |   1024|Mar 18, 2024     |Mar 22, 2019 |
|KeyPairEntry  |false|false |jack_pkcs12|RSA      |   1024|Mar 18, 2024     |Jul 10, 2019 |
|KeyPairEntry  |false|false |jack_pkcs8 |RSA      |   1024|Mar 18, 2024     |Jul 10, 2019 |
|TrustCertEntry|     |false |myservice  |RSA      |   1024|Mar 18, 2024     |Jul 10, 2010 |
|TrustCertEntry|     |false |swviewca   |RSA      |   1024|Dec 13, 2026     |Jul 10, 2010 |
+--------------+-----+------+-----------+---------+-------+-----------------+-------------+

7.3 Import PVK key pair

Copy
<script>
    // Load PVK private key file from resources
    var privateKey = new Ax.net.URL("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jack-files/jack.pvk");
    
    // Load certificates for previously loaded private key
    var certificates = new Ax.net.URL("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jack-files/jack.cer");
    
    ks.importKeyPairPrivateKeyAsPvk("jack_pvk", "newPassword", privateKey, certificates, "moon");
    console.log(ks.toResultSet());
</script>
+--------------+-----+------+-----------+---------+-------+-----------------+-------------+
|type          |lock |expiry|name       |algorithm|keysize|cerificate_expiry|last_modified|
+--------------+-----+------+-----------+---------+-------+-----------------+-------------+
|KeyPairEntry  |true |false |jack       |RSA      |   1024|Mar 18, 2024     |Mar 22, 2019 |
|KeyPairEntry  |false|false |jack_pkcs12|RSA      |   1024|Mar 18, 2024     |Jul 10, 2019 |
|KeyPairEntry  |false|false |jack_pkcs8 |RSA      |   1024|Mar 18, 2024     |Jul 10, 2019 |
|KeyPairEntry  |false|false |jack_pvk   |RSA      |   1024|Mar 18, 2024     |Jul 10, 2019 |
|TrustCertEntry|     |false |myservice  |RSA      |   1024|Mar 18, 2024     |Jul 10, 2010 |
|TrustCertEntry|     |false |swviewca   |RSA      |   1024|Dec 13, 2026     |Jul 10, 2010 |
+--------------+-----+------+-----------+---------+-------+-----------------+-------------+

7.4 Import OpenSSL key pair

Copy
<script>
    // Load OpenSSL private key file from resources
    var privateKey = new Ax.net.URL("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jack-files/jack.key");
    
    // Load certificates for previously loaded private key
    var certificates = new Ax.net.URL("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jack-files/jack.cer");
    
    console.log("Import KeyPair As OpenSSL");
    ks.importKeyPairPrivateKeyAsOpenSSL("jack_openSSL", "newPassword", privateKey, certificates, "moon");
    console.log(ks.toResultSet());
</script>
+--------------+-----+------+------------+---------+-------+-----------------+-------------+
|type          |lock |expiry|name        |algorithm|keysize|cerificate_expiry|last_modified|
+--------------+-----+------+------------+---------+-------+-----------------+-------------+
|KeyPairEntry  |true |false |jack        |RSA      |   1024|Mar 18, 2024     |Mar 22, 2019 |
|KeyPairEntry  |true |false |jack_openssl|RSA      |   1024|Mar 18, 2024     |Jul 10, 2019 |
|KeyPairEntry  |false|false |jack_pkcs12 |RSA      |   1024|Mar 18, 2024     |Jul 10, 2019 |
|KeyPairEntry  |false|false |jack_pkcs8  |RSA      |   1024|Mar 18, 2024     |Jul 10, 2019 |
|KeyPairEntry  |false|false |jack_pvk    |RSA      |   1024|Mar 18, 2024     |Jul 10, 2019 |
|TrustCertEntry|     |false |myservice   |RSA      |   1024|Mar 18, 2024     |Jul 10, 2010 |
|TrustCertEntry|     |false |swviewca    |RSA      |   1024|Dec 13, 2026     |Jul 10, 2010 |
+--------------+-----+------+------------+---------+-------+-----------------+-------------+

7.5 Import trusted certificate

Copy
<script>
    var ks = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jack-files/jack.jks", "secret");
    console.log(ks.toResultSet());
    
    // Trusted Certificate file (jack.cer)
    var certificate = new Ax.net.URL("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jack-files/jack.cer");
    
    ks.importTrustedCertificate(certificate, "jack_cer");
    console.log(ks.toResultSet());
</script>
Original KeyStore
+--------------+----+------+---------+---------+-------+-----------------+-------------+
|type          |lock|expiry|name     |algorithm|keysize|cerificate_expiry|last_modified|
+--------------+----+------+---------+---------+-------+-----------------+-------------+
|KeyPairEntry  |true|false |jack     |RSA      |   1024|Mar 18, 2024     |Mar 22, 2019 |
|TrustCertEntry|    |false |myservice|RSA      |   1024|Mar 18, 2024     |Jul 10, 2010 |
|TrustCertEntry|    |false |swviewca |RSA      |   1024|Dec 13, 2026     |Jul 10, 2010 |
+--------------+----+------+---------+---------+-------+-----------------+-------------+

KeyStore after import of certificate (jack_cer)
+--------------+----+------+---------+---------+-------+-----------------+-------------+
|type          |lock|expiry|name     |algorithm|keysize|cerificate_expiry|last_modified|
+--------------+----+------+---------+---------+-------+-----------------+-------------+
|KeyPairEntry  |true|false |jack     |RSA      |   1024|Mar 18, 2024     |Mar 22, 2019 |
|TrustCertEntry|    |false |jack_cer |RSA      |   1024|Mar 18, 2024     |Jul 10, 2019 |
|TrustCertEntry|    |false |myservice|RSA      |   1024|Mar 18, 2024     |Jul 10, 2010 |
|TrustCertEntry|    |false |swviewca |RSA      |   1024|Dec 13, 2026     |Jul 10, 2010 |
+--------------+----+------+---------+---------+-------+-----------------+-------------+

8 Cloning a KeyStore entry

In some cases you may want to create a new KeyStore from an existing one taking only an alias. For example, having a KeyStore with a KeyPair and a certificate we may want to create a new KeyStore with only the certificate.

Copy
<script>
    var ks1 = new Ax.ks.KeyStoreManager("https://bitbucket.org/deister/axional-docs-resources/raw/master/KeyStores/swview/jks-files/jack.jks", "secret");
    console.log(ks1.toResultSet());
    ks1.unlockEntry("jack", "moon");
    
    var ks2 = ks1.fromAlias("jack", "secret2");
    var ksm = new Ax.ks.KeyStoreManager(ks2, "secret2");
    console.log(ksm.toResultSet());
    
    var ks2 = ks1.fromAlias("myservice", "secret2");
    var ksm = new Ax.ks.KeyStoreManager(ks2, "secret2");
    console.log(ksm.toResultSet());
    
    var ks2 = ks1.fromAlias("swviewca", "secret2");
    var ksm = new Ax.ks.KeyStoreManager(ks2, "secret2");
    console.log(ksm.toResultSet());    
</script>
TODO: Add result!

9 Managing database KeyStores

Before we start we wil create a new table named keystores with wich we can work with.

Copy
DROP TABLE IF EXISTS keystores;

CREATE TABLE keystores (
   ks_name char(20) PRIMARY KEY,
   ks_data blob,
   ks_date datetime year to second default current year to second
);

9.1 Create and write a KeyStore into database

The code below creates a new empty KeySotre, writes it into a blob and it's then inserted into the previously created table.

Copy
<script>
    Ax.db.getMetaData().refreshTable("keystores");

    // Create a new (empty) KeyStore in PKCS12 format
    var ks = new Ax.ks.KeyStoreManager('PKCS12');
    ks.setPassword("secret");
 
    Ax.db.insert("keystores", { 
        "ks_name" : "ceo_keys", 
        "ks_data" : ks
    });
</script>

9.2 Generate KeyPair and update KeyStore

Now let's use the recently created KeyStore. We can load it, generate a new KeyPair and update it.

Copy
<script>
    // 1. Load keystore by primary key and convert to one single json store
    var json = Ax.db.executeQuery("SELECT * FROM keystores WHERE ks_name = 'ceo_keys'").toOne();
    var ks = new Ax.ks.KeyStoreManager(json.ks_data, "secret"); 

    // 2. Generate KeyPair
    ks.generateKeyPair("markjones", "secret", "RSA", 2048, config => {
    	config.setCommonName("Mark Jones");
    	config.setOrganisationUnit("Tivoli");
    	config.setOrganisationName("IBM");
    	config.setLocalityName("US");
    	config.setStateName("CA");
    	config.setCountryCode("US");
    	config.setEmailAddress("EA");
    	// Start date on next year (from now)
    	config.setValidityStart(new Ax.sql.Date());
    	// And give a vaility of 60 days
    	config.setValidityEnd(60);
    });
    
    // 3. Update keypair in database blob using it's primary key
    Ax.db.update("keystores", { 
        "ks_data" : ks
    },
    { 
        "ks_name" : "ceo_keys", 
    });
</script>

9.3 View KeyStore content

Now, let's load again the KeyStore from database to view it's contents.

Copy
<script>
    var json = Ax.db.executeQuery("SELECT * FROM keystores WHERE ks_name = 'ceo_keys'").toOne();
    var ks = new Ax.ks.KeyStoreManager(json.ks_data, "secret"); 
    
    // Display KeyStore
    console.log(ks.toResultSet());
    
    // Iterate entries in KeyStore
    for (var row of ks.toResultSet()) {
        var alias = row.name;
        console.log("======================== " + alias + " ========================");
        console.log(row);
        console.log(ks.getEntryType(alias));
        if (ks.getEntryType(row.name) == "KeyPairEntry")
            console.log("   " + ks.getPublicKey(alias));
        if (ks.getEntryType(row.name) == "TrustCertEntry")
            console.log("   " + ks.getCertificate(alias));
    }
</script>
+------------+----+------+---------+---------+-------+-----------------+-------------+
|type        |lock|expiry|name     |algorithm|keysize|cerificate_expiry|last_modified|
+------------+----+------+---------+---------+-------+-----------------+-------------+
|KeyPairEntry|true|false |markjones|RSA      |  2,048|Oct 6, 2020      |             |
+------------+----+------+---------+---------+-------+-----------------+-------------+

======================== markjones ========================
{keysize=2048, cerificate_expiry=Tue Oct 06 14:51:31 IST 2020, name=markjones, lock=true, expiry=false, type=KeyPairEntry, last_modified=null, algorithm=RSA}
KeyPairEntry
   RSA Public Key [5b:cf:af:c9:59:2e:4a:4b:2c:bd:e4:13:e4:08:2a:f9:84:c7:6f:77]
            modulus: b6b894eb75c26ec930e1329c5ab7ac639ca1d8345d27bd02f53ea33da64ccce15abfde4d9704e2d2cbfb928f3aeec403d61079c35c2d1dcb24016e8fda92c6515cb5adbad292d41b2f4896cd363931810b2e842ab96f6dfe890cb74536094fa93ed4d984ae299ab5b70bfda8d8c2f0951bd5f4c5a5a6ad8bd7ec791266afce56bdd7e4e103aea2f99744d578ca1eff2de33c1a48c234b5cc4e1be31b51ee57331e985af5b833dc57d5c1a1604c2f5b4e57a13f72b9e162c14fd2743a61936c993c16f894da2d80ab559d04325977cf15ba22908020c075e500c7b1342a74c24c4d60f65d0bde72edc6073c3e80045a037a697f0be49b48067b67860c40bdaaf7
    public exponent: 10001

9.4 Sign a document with XAdES

Copy
<script>
    // Load a keystore from database
    var json = Ax.db.executeQuery("SELECT * FROM keystores WHERE ks_name = 'ceo_keys'").toOne();
    var ks = new Ax.ks.KeyStoreManager(json.ks_data, "secret"); 
	console.log(ks.toResultSet());

    // Load any document (text, file ...)
    // In our example, we use a simple text
    var src = "This is a memo text that must be signed to certifify it's author";
    
    // Sign the document using keystore private key alias "markjones" with password "secret"
    var tmp = new Ax.crypt.CAdES(src)
    .setTspServer("http://tsa.belgium.be/connect")
    .setSignaturePackaging(Ax.crypt.CAdES.SIGNATUREPACKAGING.DETACHED)
    .setSignatureLevel(Ax.crypt.CAdES.SIGNATURELEVEL.CAdES_BASELINE_T)
    .sign(ks, "markjones", "secret");
    
    // Look at the content of PKCS7 data
    console.log(tmp);
</script>
+------------+----+------+---------+---------+-------+-----------------------+-----------------------+------------+
|type        |lock|expiry|name     |algorithm|keysize|noBefore               |noAfter                |lastmodified|
+------------+----+------+---------+---------+-------+-----------------------+-----------------------+------------+
|KeyPairEntry|true|false |markjones|RSA      |  2,048|Aug 7, 2019, 3:27:39 PM|Oct 6, 2019, 3:27:39 PM|            |
+------------+----+------+---------+---------+-------+-----------------------+-----------------------+------------+

00000000 30 82 1B 3E 06 09 2A 86 48 86 F7 0D 01 07 02 A0 0..>..*.H.......
00000010 82 1B 2F 30 82 1B 2B 02 01 01 31 0F 30 0D 06 09 ../0..+...1.0...
00000020 60 86 48 01 65 03 04 02 01 05 00 30 0B 06 09 2A `.H.e......0...*
00000030 86 48 86 F7 0D 01 07 01 A0 82 03 5C 30 82 03 58 .H.........\0..X
00000040 30 82 02 40 A0 03 02 01 02 02 04 5D 4A A0 93 30 0..@.......]J..0
00000050 0D 06 09 2A 86 48 86 F7 0D 01 01 0B 05 00 30 6E ...*.H........0n
00000060 31 11 30 0F 06 09 2A 86 48 86 F7 0D 01 09 01 16 1.0...*.H.......
00000070 02 45 41 31 0B 30 09 06 03 55 04 06 13 02 55 53 .EA1.0...U....US
00000080 31 0B 30 09 06 03 55 04 08 0C 02 43 41 31 0B 30 1.0...U....CA1.0
00000090 09 06 03 55 04 07 0C 02 55 53 31 0C 30 0A 06 03 ...U....US1.0...
6828 byte(s) more

9.5 Sign a document with XMLDSig

Copy
<script>
	// Load a keystore from database
    var json = Ax.db.executeQuery("SELECT * FROM keystores WHERE ks_name = 'ceo_keys'").toOne();
    var ks = new Ax.ks.KeyStoreManager(json.ks_data, "secret"); 
	console.log(ks.toResultSet());
    
    // Load an XML document
    var src = new Ax.xml.DocumentBuilderFactory().parse(new Ax.net.URL('https://bitbucket.org/deister/axional-docs-resources/raw/master/XML/books.xml'));
    
    // Sign the document using keystore provate key alias "markjones" with password "secret"
    var dst = new Ax.crypt.XMLDSig(src).sign(ks, "markjones", "secret");
    
    // Show the returned XML document String
    console.log(dst);
</script>
+------------+----+------+---------+---------+-------+-----------------------+-----------------------+------------+
|type        |lock|expiry|name     |algorithm|keysize|noBefore               |noAfter                |lastmodified|
+------------+----+------+---------+---------+-------+-----------------------+-----------------------+------------+
|KeyPairEntry|true|false |markjones|RSA      |  2,048|Aug 7, 2019, 3:27:39 PM|Oct 6, 2019, 3:27:39 PM|            |
+------------+----+------+---------+---------+-------+-----------------------+-----------------------+------------+

<?xml version="1.0" encoding="UTF-8" standalone="no"?><catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
   <book id="bk103">
      <author>Corets, Eva</author>
      <title>Maeve Ascendant</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-11-17</publish_date>
      <description>After the collapse of a nanotechnology 
      society in England, the young survivors lay the 
      foundation for a new society.</description>
   </book>
   <book id="bk104">
      <author>Corets, Eva</author>
      <title>Oberon's Legacy</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2001-03-10</publish_date>
      <description>In post-apocalypse England, the mysterious 
      agent known only as Oberon helps to create a new life 
      for the inhabitants of London. Sequel to Maeve 
      Ascendant.</description>
   </book>
   <book id="bk105">
      <author>Corets, Eva</author>
      <title>The Sundered Grail</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2001-09-10</publish_date>
      <description>The two daughters of Maeve, half-sisters, 
      battle one another for control of England. Sequel to 
      Oberon's Legacy.</description>
   </book>
   <book id="bk106">
      <author>Randall, Cynthia</author>
      <title>Lover Birds</title>
      <genre>Romance</genre>
      <price>4.95</price>
      <publish_date>2000-09-02</publish_date>
      <description>When Carla meets Paul at an ornithology 
      conference, tempers fly as feathers get ruffled.</description>
   </book>
   <book id="bk107">
      <author>Thurman, Paula</author>
      <title>Splish Splash</title>
      <genre>Romance</genre>
      <price>4.95</price>
      <publish_date>2000-11-02</publish_date>
      <description>A deep sea diver finds true love twenty 
      thousand leagues beneath the sea.</description>
   </book>
   <book id="bk108">
      <author>Knorr, Stefan</author>
      <title>Creepy Crawlies</title>
      <genre>Horror</genre>
      <price>4.95</price>
      <publish_date>2000-12-06</publish_date>
      <description>An anthology of horror stories about roaches,
      centipedes, scorpions  and other insects.</description>
   </book>
   <book id="bk109">
      <author>Kress, Peter</author>
      <title>Paradox Lost</title>
      <genre>Science Fiction</genre>
      <price>6.95</price>
      <publish_date>2000-11-02</publish_date>
      <description>After an inadvertant trip through a Heisenberg
      Uncertainty Device, James Salway discovers the problems 
      of being quantum.</description>
   </book>
   <book id="bk110">
      <author>O'Brien, Tim</author>
      <title>Microsoft .NET: The Programming Bible</title>
      <genre>Computer</genre>
      <price>36.95</price>
      <publish_date>2000-12-09</publish_date>
      <description>Microsoft's .NET initiative is explored in 
      detail in this deep programmer's reference.</description>
   </book>
   <book id="bk111">
      <author>O'Brien, Tim</author>
      <title>MSXML3: A Comprehensive Guide</title>
      <genre>Computer</genre>
      <price>36.95</price>
      <publish_date>2000-12-01</publish_date>
      <description>The Microsoft MSXML3 parser is covered in 
      detail, with attention to XML DOM interfaces, XSLT processing, 
      SAX and more.</description>
   </book>
   <book id="bk112">
      <author>Galos, Mike</author>
      <title>Visual Studio 7: A Comprehensive Guide</title>
      <genre>Computer</genre>
      <price>49.95</price>
      <publish_date>2001-04-16</publish_date>
      <description>Microsoft Visual Studio 7 is explored in depth,
      looking at how Visual Basic, Visual C++, C#, and ASP+ are 
      integrated into a comprehensive development 
      environment.</description>
   </book>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><DigestValue>zolcPXUMCIref0InS0KhgpYS6u7J6SgrAEpj//MjClU=</DigestValue></Reference></SignedInfo><SignatureValue>r0Vxj3+17n1ny6RN+Vow84j1zdUoUdKSOiZsAZZPm2FnQyBGcG8gLvKsStHTwf3n3Taoy02in+l7&#13;
cNhoxN119VwZ04dLZbTEHD2G2fqgEGfiyFIEjuoF0fpsr0Tn6WBMLGWQprJxa/sU4CvWDkORDYLe&#13;
n+rDgLCJVjltq7yBARssSFe/myOyJYRVxJnnElzLWJBceHM3G5OfOuVXxG6p6psWnrUrOiAXYh/J&#13;
P80Sn3v3s8pqz0MWLdrI752kSf1V4jVpHeN0VOl0S8/1Xu3+2qky0/FkVSwRAz8XcO3rsYyhgQD/&#13;
Nc7RXGnGqhao2MTAu9rWVu57CLkeUNOuAcRRhg==</SignatureValue><KeyInfo><X509Data><X509SubjectName>CN=Mark Jones,OU=Tivoli,O=IBM,L=US,ST=CA,C=US,1.2.840.113549.1.9.1=#16024541</X509SubjectName><X509Certificate>MIIDWDCCAkCgAwIBAgIEXUqgkzANBgkqhkiG9w0BAQsFADBuMREwDwYJKoZIhvcNAQkBFgJFQTEL&#13;
MAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJVUzEMMAoGA1UECgwDSUJNMQ8wDQYD&#13;
VQQLDAZUaXZvbGkxEzARBgNVBAMMCk1hcmsgSm9uZXMwHhcNMTkwODA3MDk1NzM5WhcNMTkxMDA2&#13;
MDk1NzM5WjBuMREwDwYJKoZIhvcNAQkBFgJFQTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQsw&#13;
CQYDVQQHDAJVUzEMMAoGA1UECgwDSUJNMQ8wDQYDVQQLDAZUaXZvbGkxEzARBgNVBAMMCk1hcmsg&#13;
Sm9uZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/F2UyKlPYBd8HHpD4vm0LQvDv&#13;
rZ2AGmqB1Us0opZCkMha1sfjxQkzrY3drerIhNmlOTVm2xwYjSb6iJxsBzfwtKPl0F/JGsvldLpw&#13;
ItqIA12CY7suorfRZdh4C+EpV7VAhPA1Zhl7podVW0Hflb71ERt5/yFkLX4l5b4ENYZg06lJCJPB&#13;
cCIzsTu0EmXxXu2LrnWhJdhnSBytXbBpGTAxuRt+9xJv8OdcaJaO0UReG+RS1Lfz9SnREQU4F4gM&#13;
BsyJH8sob9zgUOBNGuC6cUancQEA3fUG/qpn8uA/dfz2yiNJgTwqbqlxniK8ydeububNnILObXmA&#13;
UZXEM/0hlaZdAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAKliMZZ9XDUiI7xxZuqrDvkXbcgEComi&#13;
oCbWwkSr1HdPEPTqOZQLZaV3YQAvGqwRUTn+UG1YcNLs7bSA/S1MLafE408JPESCQYK3Rn7+p9vl&#13;
9LFSJ8YnvUipFXDk29uWpqMoXuCejN3cbC5nmGlhySG8Eq3mp4L1XHKFX59BT9NrwHQG+hEAgbGW&#13;
FuJU5rqeMEhKD++UXd8QQiijgocP/HIndJCHbuwAVpeSERp/tzg3C8jzyNjWWkxofpQ65LdAzBfs&#13;
OvTo8zd+CA1p26WwBxxe7RWNgt56oMyYFD6jSZbGKBLKrXEBcJJT9NABhjWWGDKIYoaMZLd7U1RA&#13;
NeAtGSY=</X509Certificate></X509Data></KeyInfo></Signature></catalog>