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.
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.
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 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.
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.
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
}
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();
...
}
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.
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
}
}
}