Describes the RM API relevant to certificate management, which can be used on the RM framework or from external applications.

Certificate Management API Overview

The RM Certificate Management API is held by the com.prosyst.mprm.admin.certificate package. It provides interfaces through which applications may perform essential certificate management operations. The Certificate Management API is accessible both from external applications through a Remote Access Client, and as OSGi services on backbend server hosts.

The Certificate Management API provides the following interfaces:

  • CertificateManager provides methods for certificate management.
  • Certificate represents CA and own certificates.
  • CertificateEvent provides a set of events that are specific to the Certificate Repository.
  • CertificateListener provides means to interested applications to receive events specific to the Certificate Repository.

The principles of certificate management are described in the Certificate Management conceptual guide. Managing certificates through the RM Console is described in the Certificate Management user's guide.

Accessing the Certificate Management API

The Certificate Management API is part of the frontend APIs. It is accessed in two ways:

  • On the RM backend server hosts - Certificate Manager is available as a service registered under the com.prosyst.mprm.admin.certificate.CertificateManager interface. You can call the service using the conventional techniques defined by the OSGi Framework Specification.

  • On remote external applications - External applications can access Certificate Manager in the standard way for accessing RM services through the Remote Access Client (RAC) utility. In this case, you must have the lib/rac/system-rac.jar and lib/rac/foundation-rac.jar in the classpath. Working with it is described in the System package documentation, section "Programmer's Guide" -> "Backend Communication" -> Remote Access to RM.

Developers can use the lib/api/foundation-api.jar archive for development and compilation of applications using Certificate Manager

Using the Certificate Management API

Using the Certificate Management API you can perform the following tasks:

  • Perform basic management operations on stored certificates, such as: add, get and delete certificate from the Certificate Repository.
  • Open certificates and retrieve information about them.
  • Track changes that occur into the Certificate Repository.
  • Create own certificates.
  • Create secure context bundles to export own and trusted certificates.
  • Import key stores into RM as well as export such from it.

Opening a Certificate

To open a certificate, use the method openCertificate of the Certificate Manager. This method takes as a single argument a byte array, representing certificate data, parses it and returns a Certificate object. This method is commonly used to view a certificate which is not in the database yet.

The code snipped below contains an application, which gets a certificate from a file and represents it as a byte array. Then calls the openCertificate method of the Certificate Manager.

Opening a Certificate:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import com.prosyst.mprm.admin.certificate.Certificate;
import com.prosyst.mprm.admin.certificate.CertificateManager;
import com.prosyst.mprm.common.ManagementException;
 
public class OpenCertificate implements BundleActivator {
 
private ServiceReference certMngrRef;
CertificateManager certMngr;
Certificate certificate;
 
private FileInputStream fileStream;
private File certificateFile;
private int length;
 
//location of the certificate file on the local disk
private static final String certificateFilePath =
"D:\\certificates\\CertPlusClass1PrimaryCA.cer";
private byte[] certificateFileBytes;
//method for getting certificate bytes from a file
public byte[] getCertificateBytes(String filePath)throws IOException{
try{
certificateFile = new File(certificateFilePath);
length = (int) certificateFile.length();
fileStream = new FileInputStream(certificateFile);
certificateFileBytes = new byte[length];
for(int read, offset = 0; length > 0; offset += read, length -= read) {
read = fileStream.read(certificateFileBytes, offset, length);
}
 
return certificateFileBytes;
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void start(BundleContext bc) throws Exception {
certMngrRef = bc.getServiceReference(CertificateManager.class.getName());
certMngr = (CertificateManager) bc.getService(certMngrRef);
try{
certificateFileBytes = getCertificateBytes(certificateFilePath);
/*call the openCertificate method to create
Certificate object from the read bytes*/
certificate = certMngr.openCertificate(certificateFileBytes);
}catch (ManagementException e){
e.printStackTrace();
}
}
 
public void stop(BundleContext bc) throws Exception {
bc.ungetService(certMngrRef);
certMngrRef = null;
}
}

Adding Certificates

Certificate Manager service defines the addCertificate method as a mean to add certificates to the Certificate Repository. It takes as an argument a byte array containing the certificate to be added and returns the certificate unique name String.

The code excerpt that follows calls the getCertificateBytes method (see the above listing "Opening a Certificate"), to get a certificate's bytes, then calls the addCertificate method of the Certificate Manager to add the certificate to the Certificate Repository. Finally, it calls the addToDomain method to add the new certificate to the mPRM TLS Server domain.

Adding a Certificate:

... //obtaining a CertificateManager service
...
try{
//get certificate bytes from a file (see Listing 1)
certificateFileBytes = getCertificateBytes(certificateFilePath);
certMngr.addCertificate(certificate);
certificate.addToDomain("mPRM TLS Server");
}catch (ManagementException e){
e.printStackTrace();
}


               

Adding Certificate Domains

You can add new certificate domains to the Certificate Repository using the addDomain method of the Certificate Manager. It requires a String name of the new domain passed as an argument.

You must not use certificate domain names reserved by RM.

For further information on the certificate domains, refer to the Certificate Management conceptual guide.

Getting Certificates

Certificate Management API provides the following methods for obtaining certificates from the Certificate Repository:

  • getCertificate - Gets a certificate from the Certificate Repository. It requires the certificate unique name within the Certificate Repository passed as an argument.
  • getCertificates - Returns a com.prosyst.mprm.data.Enumerator object of certificate unique names contained in certain certificate group. It requires a certificate domain and group names passed as arguments.
  • getOwnCertificates - Returns an com.prosyst.mprm.data.Enumerator of unique names of the available own certificates. Requires a certificate domain and group names passed as arguments. If you pass null as arguments, all the available own certificate unique names will be returned. You can pass only a group or domain name to retrieve the unique names of the own certificates that belong to certain group or domain. If you pass both the arguments, the method will return the unique names of the own certificates that belong to certain group and are applicable to certain domain.
  • getTrustedCertificates - Returns an com.prosyst.mprm.data.Enumerator of certificate unique names contained in certain group that are issued from trusted CA. Requires a certificate domain and group names passed as arguments. You can use this method in the same way as the getOwnCertificates method.

Setting Certificate Properties

The Certificate interface allows you to bound custom properties to a certificate in order to provide additional functionality. These properties can be certificate ID, user friendly name, description etc. The method for setting custom properties to a certificate is setProperties which requires a Dictionary object containing the properties passed as an argument.

Setting certificate properties:

... //obtaining a CertificateManager
service
...
//get the certificate from the
Certificate Repository
Certificate certificate = certMngr.getCertificate(certificateUN);
 
Hashtable certificateProps = new Hashtable(); certificateProps.put("Certificate ID", "01"); certificateProps.put("Certificate Name", "MyCertificate"); certificate.setProperties(certificateProps);
...

            

Deleting Certificates

Certificate Manager defines two methods for deleting a certificates from the Certificate Repository:

  • removeCertificate - Removes a single certificate from the Certificate Repository. It takes the certificate unique name as an argument.
  • removeExpiredCertificates - Removes all certificates that will expire on certain date. It takes a java.util.Date object as an argument.

Obtaining Certificate Information

Through the methods of the Certificate interface you can retrieve information about a certificate.

Certificate Property

Method

Description

Unique Name

getUniqueName

Returns the certificate unique name within the Certificate Repository.

Serial number

getSerialNumber

Returns a String that contains the certification serial number as a hexadecimal. For example, 26e3fdc7.

Subject

getSubject

Returns a String that contains a list of values. The values contain information about the subject of the certificate. The subject of the certificate is an entity identifying the certificate holder.

Certificate signature algorithm

getSignatureAlgorithm

Returns the algorithms used to sign the certificates. For example, sha1WithRSA.

Issuer

getIssuer

Returns a String that consisting of a list of values containing information about the issuer of the certificate. The list of values both for the certification authority and the issuer consists of:

  • countryName
  • stateOrProvinceName
  • localityName
  • organizationName
  • organizationUnitName
  • commonName
  • emailAddress
    If any of these values are not set, they are not included in the String.

Certificate Domains

getDomains

Returns a String containing the domains the certificate is applicable to.

Certificate Group

getGroup

Returns a String containing the group the certificate belongs to.

Start of validity

getValidNotBefore

Returns a java.util.Date object specifying when the certificate becomes valid.

End of validity

getValidNotAfter

Returns a java.util.Date object specifying when the certificate will expire.

Certificate Properties

getProperties

Returns a String containing the properties associated with the certificate.

Revocation list URL

getRevocationListURL

Returns a String of the certificate revocation URL value for this certificate. If the certificate is from a JDBC database, but its revocation URL is unavailable, the method returns null.

Creating Own Certificates

You can create and register own certificates in the Certificate Repository by calling the createCA method of the Certificate Manager. It requires a key pair properties passed as an argument and returns the generated certificate unique name within the Certificate Repository.

The following code example creates a certificate and adds it in the Certificate Repository.

Retrieving Certificate Info:

import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import com.prosyst.mprm.admin.certificate.CertificateManager;
import com.prosyst.mprm.common.ManagementException;
 
public class OwnCertificateExample implements BundleActivator {
 
CertificateManager certMngr;
ServiceReference ref;
String certificate;
Hashtable certificateProps;
 
//set the certificate's validation date to be the date of its creation
static final String VALIDATION_DATE = String.valueOf(System.currentTimeMillis());
//set the certificate's expiration date to one year after it has been validated
static final String EXPIRATION_DATE =
String.valueOf(System.currentTimeMillis() + 365 * 24 * 3600 * 1000L);
public void start(BundleContext bc) throws Exception {
ref = bc.getServiceReference(CertificateManager.class.getName());
certMngr = (CertificateManager) bc.getService(ref);
//provide the certificate properties
certificateProps = new Hashtable();
certificateProps.put(CertificateManager.COMMON_NAME, "ACME Certificate");
certificateProps.put(CertificateManager.LOCALITY_NAME, "US");
certificateProps.put(CertificateManager.ORGANIZATION_NAME,"AMCE Corporation");
certificateProps.put(CertificateManager.BIT_LENGTH, "512");
certificateProps.put(CertificateManager.PK_ALGORITHM, CertificateManager.RSA);
certificateProps.put(CertificateManager.VALID_NOT_BEFORE, VALIDATION_DATE);
certificateProps.put(CertificateManager.VALID_NOT_AFTER, EXPIRATION_DATE);
try {
//create the certificate
certificate = certMngr.createCertificate(keyPairPops);
} catch (ManagementException e) {
e.printStackTrace();
}
}
public void stop(BundleContext bc) throws Exception {
bc.ungetService(ref);
ref = null;
}
}


Importing and Exporting a Key Store

Using the Certificate Manager API, you can import key stores into RM and export ones from it.

The method for importing a key store into RM is importKeyStore. It requires the following arguments:

  • A java.io.InputStream object of the key store to be imported.
  • A String name of the certificate group where the certificates held by the key store will be imported.
  • A String array of certificate domain names where the certificates will be applicable to.
  • A String containing the key store password.
  • A String containing the password to encrypt the keys held by the kay store.
  • A String specifying the key store provider. The supported providers are SunJSSE and SUN.
  • A String specifying the key store type. The supported types are PKCS12 and JKS.

The code example that follows, imports a key store into RM.

Importing a key store:

import java.io.File;
import java.io.FileInputStream;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import com.prosyst.mprm.admin.certificate.CertificateManager;
import com.prosyst.mprm.common.ManagementException;
 
public class ImportingKeyStore implements BundleActivator {
 
FileInputStream certIS;
File certificateFile;
String certificateFilePath = "D:\\keysotres\\ExampleKeyStore.keystore";
CertificateManager certMngr;
ServiceReference ref;
static final String[] DOMAINS = new String[]{"mPRM TLS Server"};
static final String CERT_GROUP = "General";
static final String STORE_PASS = "567890";
static final String KEY_PASS = "123456";
static final String PROVIDER = "SUN";
static final String STORE_TYPE = "JKS";
public void start(BundleContext bc) throws Exception {
ref = bc.getServiceReference(CertificateManager.class.getName());
certMngr = (CertificateManager) bc.getService(ref);
certificateFile = new File(certificateFilePath);
certIS = new FileInputStream(certificateFile);
try{
certMngr.importKeyStore
(certIS, CERT_GROUP, DOMAINS, STORE_PASS, KEY_PASS,PROVIDER, STORE_TYPE);
}catch (ManagementException e){
e.printStackTrace();
}
 
public void stop(BundleContext bc) throws Exception {
certIS.close();
bc.ungetService(ref);
ref = null;
 
}
 
}

The method for exporting a key store from RM is exportKeyStore. It takes the following arguments:

  • A String array of certificate unique names of certificates to be included in the key store.
  • A boolean indicating whether to include the key pairs of the certificates.
  • A String containing the key store password.
  • A String containing the password for encrypting the keys, which will be included in the key store.
  • A String specifying the key store provider.
  • A String specifying the key store type.

The following listing contains an application that exports all certificates contained in the General group and trusted by the mPRM TLS Server into a key store.

Exporting a key store:

import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import com.prosyst.mprm.admin.certificate.CertificateManager;
import com.prosyst.mprm.common.ManagementException;
import com.prosyst.mprm.data.Enumerator;
 
public class ExportingKeyStore implements BundleActivator {
 
static final String DOMAIN = "mPRM TLS Server";
static final String CERT_GROUP = "General";
static final String STORE_PASS = "567890";
static final String KEY_PASS = "123456";
static final String PROVIDER = "SunJSSE";
static final String STORE_TYPE = "PKCS12";
 
static final String[] CERTIFICATES;
static final String FILE_PATH = "D:\\keystores\\tls_server.pfx";
FileOutputStream keyStoreFile;
InputStream keyStoreStream;
public void start(BundleContext bc) throws Exception {
ref = bc.getServiceReference(CertificateManager.class.getName());
certMngr = (CertificateManager) bc.getService(ref);
//get the unique names of certificates trusted by the mPRM TLS Server
Enumerator certsUN = certMngr.getCertificates(DOMAIN, CERT_GROUP);
List certList = new ArrayList();
try{
while (certsUN.hasMoreElements()){
certList.add(certsUN.nextElement());
}
CERTIFICATES = (String[]) certList.toArray(new String[certList.size()]);
} catch (Exception e) {
e.printStackTrace();
}
byte[] buffer = new byte[4096];
keyStoreFile = new FileOutputStream(FILE_PATH);
try {
//export the key store
keyStoreStream = certMngr.exportKeyStore
(CERTIFICATES, true, STORE_PASS, KEY_PASS, PROVIDER, STORE_TYPE);
//create the key store file
for (int read = 0; (read = keyStoreStream.read(buffer)) != -1;
keyStoreFile.write(buffer, 0, read));
keyStoreFile.flush();
keyStoreFile.close();
 
}catch (ManagementException e){
e.printStackTrace();
}
}
 
public void stop(BundleContext bc) throws Exception {
bc.ungetService(ref);
ref = null;
 
}
}

Creating a Security Context Bundle

A Security Context bundle can export trusted and own certificates along with the related cryptographic functionality. In case of exporting trusted certificates, the Security Context bundle registers as an OSGi service a javax.net.ssl.X509Trust manager and when exporting own certificates, it registers as an OSGi service a javax.net.ssl.X509KeyManager. It also registers a com.prosyst.mprm.util.keystore.osgi.KeyStoreHolder to keep the related key and trusted certificate entries.

The Security Context bundle can be used by the TLS, the RM Secure Transport, the Login Service to ensure certificate-based logins or by any other interested security entity.

The Certificate Manager service provides the createSecureCtx method, which returns a JAR file containing the corresponding key pairs and trusted certificates. The method takes the following arguments:

  • A java.util.Dictionary containing properties for creation of own certificate and its private key. Here you can specify the unique name within the Certificate Repository of an issuer certificate. If no issuer certificate is specified, the generated own certificate will be self-signed.

  • A java.lang.String[] containing the unique names of certificates whose authenticity will be ensured by the X509TrustManager.

  • A java.lang.String password for the created key store.

  • A java.lang.String provider for the created key store.

  • A java.lang.String type of the key store.

  • A java.util.Properties to provide the registration properties for the KeyStoreHolder.

  • A java.util.Properties to provide the registration properties for the X509KeyManager.

  • A java.util.Properties to provide the registration properties for the X509TrustManager.

Creating a secure context bundle:

import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Properties;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import com.prosyst.mprm.admin.certificate.CertificateManager;
import com.prosyst.mprm.common.ManagementException;
import com.prosyst.mprm.data.Enumerator;
 
public class SecureCtxt implements BundleActivator {
 
CertificateManager certMngr;
ServiceReference ref;
FileOutputStream secureCtxtFile;
InputStream secureCtxtStream;
String FILE_PATH = "D:\\secureCtxt1.jar";
Hashtable keyProps;
Properties kshRegProps;
Properties keyMnrgRegProps;
Properties trustMnrgRegProps;
String[] TRUSTED_CERTIFICATES;
final static String VALIDATION_DATE = String.valueOf(System.currentTimeMillis());
final static String EXPIRATION_DATE = String.valueOf(System.currentTimeMillis() + 365 * 24 * 3600 * 1000L);
final static String KEY_STORE_PASS= "123456";
final static String KEY_STORE_PROVIDER = "ProsystKSProvider";
final static String KEY_STORE_TYPE = "PKS";
public void start(BundleContext bc) throws Exception {
ref = bc.getServiceReference(CertificateManager.class.getName());
certMngr = (CertificateManager) bc.getService(ref);
keyProps = new Hashtable();
//Set the own certificate properties
keyProps.put(CertificateManager.COMMON_NAME, "ACME Certificate");
keyProps.put(CertificateManager.LOCALITY_NAME, "US");
keyProps.put(CertificateManager.ORGANIZATION_NAME,"AMCE Corporation");
keyProps.put(CertificateManager.BIT_LENGTH, "512");
keyProps.put(CertificateManager.PK_ALGORITHM, CertificateManager.RSA);
keyProps.put(CertificateManager.PASSWORD_FOR_KPH, "123456");
keyProps.put(CertificateManager.VALID_NOT_BEFORE, VALIDATION_DATE);
keyProps.put(CertificateManager.VALID_NOT_AFTER, EXPIRATION_DATE);
//Set the Key Store registration properties
kshRegProps = new Properties();
kshRegProps.setProperty("MyKSH", "KSH");
//Set the X.509 Key Manager registration properties
keyMnrgRegProps = new Properties();
keyMnrgRegProps.setProperty("mPRM TLS Server", "KPH");
//Set the X.509 Trust Manager registration properties
trustMnrgRegProps = new Properties();
trustMnrgRegProps .setProperty("mPRM TLS Server", "CV");
secureCtxtFile = new FileOutputStream(FILE_PATH);
Enumerator certsUN = certMngr.getCertificates("mPRM RAS", "General");
List certList = new ArrayList();
//Get the certificates that belong to the mPRM RAS domain and are part of the General group
try{
while (certsUN.hasMoreElements()){
certList.add(certsUN.nextElement());
}
TRUSTED_CERTIFICATES = (String[]) certList.toArray(new String[certList.size()]);
} catch (Exception e) {
e.printStackTrace();
}
byte[] buffer = new byte[4096];
try {
//Create the Security Context bundle
secureCtxtStream = certMngr.createSecurityCtx(keyProps, TRUSTED_CERTIFICATES, KEY_STORE_PASS,
KEY_STORE_PROVIDER, KEY_STORE_TYPE, kshRegProps,
keyMnrgRegProps, trustMnrgRegProps, false);
for (int read = 0; (read = secureCtxtStream.read(buffer)) != -1; secureCtxtFile.write(buffer, 0, read));
 
}catch (ManagementException e){
e.printStackTrace();
}
}
 
public void stop(BundleContext bc) throws Exception {
 
secureCtxtFile.close();
secureCtxtStream.close();
bc.ungetService(ref);
ref = null;
}
 
}

Checking and Setting Subject Certificate Revocation

Revoked certificates are subject certificates signed by an issuer certificate and later declared untrusted for the remaining period of their current validity. The RM database keeps only trusted issuer certificates and the serial numbers of their revoked subject certificates, not their byte arrays.

The Certificate interface defines two methods for obtaining the serial numbers of revoked certificates:

  • getAdminRevokedCertificates - Returns a com.prosyst.mprm.data.Enumerator, containing the serial numbers of certificates, signed by the issuer certificate, which were revoked by the administrator of the RM.

  • getCRLRevokedCertificates - Returns com.prosyst.mprm.data.Enumerator, containing the serial numbers of certificates, signed by the issuer certificate, which were revoked by CRL.

To check if a definite subject certificate is revoked, use the isRevoked method defined by the Certificate interface (representing an instance of the issuer certificate for the subject one). The method takes the serial number of the subject certificate as a string parameter - String serialNumber. It returns a boolean with value true if the certificate is marked as revoked, or false - if it is not revoked in the RM system.

The following code excerpt illustrates the use of the methods for retrieval of subject certificates and change of their revocation.

Certificate Revocation Methods:

... //obtaining a CertificateManager service
...
//get a certificate's bytes from a file (see Listing 1)
certificateFileBytes = getCertificateBytes(certificateFilePath);
String certificateUN = certMngr.getCertificateUniqueName(certificateFileBytes);
certificate = certMngr.getCertificate(certificateUN);
//get the serial numbers of admin revoked certificates
Enumerator adminRevokedCert = certificate.getAdminRevokedCertificates();
while (adminRevokedCert.hasMoreElements()){
System.out.println(adminRevokedCert.nextElement());
}
...
 
//get the serial numbers of CRL revoked certificates
Enumerator crlRevokedCert = certificate.getCRLRevokedCertificates();
while (crlRevokedCert.hasMoreElements()){
System.out.println(crlRevokedCert.nextElement());
}
...
 
String subjectSerialNumber = "86FE1D5FC381F847D7332C7394757B37";
boolean isRevoked = certificate.isRevoked(certificateUN);
if (isRevoked != true) {
certificate.revokeCertificate(subjectSerialNumber);
System.out.println("Certificate revoked!");
}
...

To change the revocation list URL of a certificate, use the setRevocationListURL method, defined by the Certificate interface. It takes a string argument containing the certificate revocation list URL. The method sets a new certificate revocation list URL for this certificate.