The PKIF Java Interface (JPKIF)

PKIF implements a complete java interface (JPKIF), provided in the "com.orionsec.jpkif" package. This interface is implemented through a set of Java classes which access the PKIF library via JNI.

Supported JRE Versions

JPKIF has been fully tested on Microsoft Windows XP (32 and 64 bit versions), Solaris 10, and multiple Linux distributions (2.6 kernel) using Sun Microsystems 1.4 and 1.5 JDK. There are currently no known operating issues when JPKIF is properly installed.

Installing and using JPKIF

JPKIF is included in the PKIF installation. The java wrapper classes are packaged in the JPKIF.jar file. Java programs which intend to utilize JPKIF must include the JPKIF.jar file in the java classpath. Additionally, all native PKIF libary files must be accessible to the java runtime environment (JRE). This includes the PKIF library itself, and all of it's dependencies (boost, log4cxx, etc). Missing native library files will generate a runtime error condition in the JRE. The recommended way to make PKIF native libraries accessible is to include the libraries in the system path. Alternatively, most JRE implementations allows users to specify library file locations via the "java.library.path" environment variable. Consult your JRE's documentation for more information.

Since JPKIF depends on natively compiled PKIF libraries, it is necessary to explicitly tell the JRE which native library to load in order to use PKIF. Typically, this is done using either the "java.lang.System.load" method, or the "java.lang.System.loadLibrary" method. The default JPKIF dll name is "jpkif_module". Here is an example of loading the native library from within a static block of java code.

    static 
    {
      // load PKIF before attempting to use the library!
      System.loadLibrary("jpkif_module");
    }

    
Refer to the Additional References for links to Sun Microsystems official documentation for the java.lang.System class.

JPKIF API Documentation

JPKIF is implemented as a set of thin java wrappers that access PKIF via JNI. With the exception of language specific types (numeric types, character types, etc), every effort has been made to maintain full API compatibility between PKIF and the JPKIF wrapper classes. As a result, the current PKIF documentation is applicable to the JPKIF interface. Refer to the section "Notes on Java Language Types" for additional information.

Notes on Java Language Types

The java language is strongly typed, and there are notable differences between the range and handling of java types compared to the native C/C++ types used in the underlying PKIF library.

Numeric Types

All java primitive numeric types are signed. In some situations, attempting to use unsigned data may result in compilation errors. For example, say the following code is used within a C/C++ program utilizing PKIF:
      
      const unsigned char data[] = {236, 233, 216, ...};
    
Copying and pasting this code into a JPKIF java program, and changing the "unsigned char[]" type declaration to "byte[]" will result in compilation errors. This occurs because the java "byte" type is signed, it's valid data ranges are from [-2^7, 2^7-1] In this scenario, the preferred method is to change the c/c++ numeric type into a java numeric type whose signed values can accomodate the possible range of the c/c++ unsigned values. A set of JPKIF helper functions can then be used to navigate between types, if necessary. For example:

      // C/C++ code
      const unsigned char data[] = {236, 233, 216, ...};
    
Copying and pasting this code, then modifying it to compile as java code would look like this:

      // Equivalent java code
      int data[] = {236, 233, 216, ...};
      byte b[] = null;
      try {
        b = pkif_module.toByteArray (buf);
        // throws an Exception if data loss will 
        // occur when going from int to byte values.
      } catch (IllegalArgumentException ie) {
        // handle the exception
      } 
    

Character Types

Unless otherwise noted, C/C++ character data types, including char*, are represented as java.lang.String objects within the JPKIF API. For example, in the native PKIF library, the prototype of the "dnsName" function of the CPKIFGeneralName class is as follows:

      const char* CPKIFGeneralName::dnsName() const
    
The prototype of the JPKIF version of this function is:
    
      public class CPKIFGeneralName {
        ...
          public String dnsName();
        ...
      }
    

JPKIF Exception Handling

C++ exceptions thrown by the underlying native PKIF library are propogated through JPKIF as instances of the java.lang.Exception class. Details of the exception generating condition(s) can be obtained via the "getMessage" method.

A JPKIF Code Example

  import com.orionsec.jpkif.*;

  public class JPKIFSample
  {
    static 
    {
      // Make a request to the JRE to load the PKIF native library
      System.loadLibrary("jpkif_module");

      // alternatively, the "System.load" method can be invoked:
      // System.load(<complete path to library file>);
    }

    public static void main(String[] args)
    {
      CPKIFPathSettingsPtr g_defaultSettings = pkif_module.make_CPKIFPathSettingsPtr();
      g_defaultSettings.SetRequireFreshRevocationData(true);  

      IPKIFMediator mediator = pkif_module.MakeDefaultMediator();
      IPKIFPathBuild pb = pkif_module.Get_IPKIFPathBuild(mediator);
      IPKIFPathValidate pv = pkif_module.Get_IPKIFPathValidate(mediator);
      IPKIFPathBuildAndValidate pbav = pkif_module.Get_IPKIFPathBuildAndValidate(mediator);

      CPKIFLDAPRepository ldap = new CPKIFLDAPRepository();
      ldap.SetHost("localhost");

      CPKIFCacheMediator2 cm = pkif_module.Get_CacheMediator(mediator);
      cm.AddColleague(pkif_module.Get_LDAPAsColleague(ldap));

      CPKIFCertificatePtr cert = pkif_module.DecodeCertFromFile ("/etc/certs/cert1.crt");

      CPKIFCertificatePath path = new CPKIFCertificatePath();
      path.SetTarget(cert);
      path.SetPathSettings(g_defaultSettings);
      
      CPKIFPathValidationResults results = new CPKIFPathValidationResults();
      pbav.BuildAndValidatePath(path, results);

      if (results.PathSuccessfullyValidated())
      {
        // do something
      }
    }
  }
    

Additional References