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:
CertificateManagerprovides methods for certificate management.Certificaterepresents CA and own certificates.CertificateEventprovides a set of events that are specific to the Certificate Repository.CertificateListenerprovides 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.CertificateManagerinterface. 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 acom.prosyst.mprm.data.Enumeratorobject of certificate unique names contained in certain certificate group. It requires a certificate domain and group names passed as arguments.getOwnCertificates- Returns ancom.prosyst.mprm.data.Enumeratorof 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 ancom.prosyst.mprm.data.Enumeratorof 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 ajava.util.Dateobject 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 |
| Returns the certificate unique name within the Certificate Repository. |
Serial number |
| Returns a |
Subject |
| Returns a |
Certificate signature algorithm |
| Returns the algorithms used to sign the certificates. For example, sha1WithRSA. |
Issuer |
| 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:
|
Certificate Domains |
| Returns a |
Certificate Group |
| Returns a String containing the group the certificate belongs to. |
Start of validity |
| Returns a |
End of validity |
| Returns a |
Certificate Properties |
| Returns a |
Revocation list URL |
| Returns a |
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.InputStreamobject of the key store to be imported. - A
Stringname of the certificate group where the certificates held by the key store will be imported. - A
Stringarray of certificate domain names where the certificates will be applicable to. - A
Stringcontaining the key store password. - A
Stringcontaining the password to encrypt the keys held by the kay store. - A
Stringspecifying the key store provider. The supported providers are SunJSSE and SUN. - A
Stringspecifying 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
Stringarray of certificate unique names of certificates to be included in the key store. - A
booleanindicating whether to include the key pairs of the certificates. - A
Stringcontaining the key store password. - A
Stringcontaining the password for encrypting the keys, which will be included in the key store. - A
Stringspecifying the key store provider. - A
Stringspecifying 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.Dictionarycontaining 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.Stringpassword for the created key store.A
java.lang.Stringprovider for the created key store.A
java.lang.Stringtype of the key store.A
java.util.Propertiesto provide the registration properties for theKeyStoreHolder.A
java.util.Propertiesto provide the registration properties for theX509KeyManager.A
java.util.Propertiesto provide the registration properties for theX509TrustManager.
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 acom.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- Returnscom.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.