Java security evolution and concepts, Part 5

J2SE 1.4 offers numerous improvements to Java security

Early on, Java security focused on resisting executable content threats — security risks caused by malicious or poorly designed code. From that beginning, Java security measures evolved to provide security based on where code came from and who signed it. More recently, Java security has improved further to provide user and pluggable authentication, as well as SSL (Secure Socket Layer) and other key management and cryptography support.

Java security evolution and concepts: Read the whole series!

  • Part 1: Learn computer security concepts and terms in this introductory overview
  • Part 2: Discover the ins and outs of Java security
  • Part 3: Tackle Java applet security with confidence
  • Part 4: Learn how optional packages extend and enhance Java security
  • Part 5: J2SE 1.4 offers numerous improvements to Java security

This article, the last of five in the Java security series, follows the examples introduced in Part 3 and briefly revisits the optional packages covered in Part 4. By revisiting the examples from earlier articles, we can reinforce concepts and understand what has changed in the interim.

After an overview of those security features that have changed between J2SE (Java 2 Platform, Standard Edition) 1.3 and the upcoming J2SE 1.4, this article digs deeper into the new packages included in 1.4. The first of the newer packages is the Java Certification Path (CertPath) API, which supports certificate chain manipulation. Second is the Java GSS-API (JGSS), which contains the Java bindings for the Generic Security Services Application Program Interface (GSS-API) for standardized access to a variety of security services and a framework for a single sign-on.

Overview of changes

First, let’s quickly look at the changes between J2SE 1.3 and 1.4.

Optional packages move into the 1.4 core

As the most obvious change between J2SE 1.3 security and 1.4, the optional packages (examined in Part 4) will move into 1.4’s core security structure:

  • Java Authentication and Authorization Service (JAAS): A framework for performing user-based authentication
  • Java Cryptography Extension (JCE): A framework for using strong ciphers on a global basis
  • Java Secure Socket Extension (JSSE): Support for SSL and TLS (Transport Layer Security)

Each of the aforementioned packages will be available on every J2SE 1.4 installation, obviating the need to install them explicitly.

New 1.4 packages

Besides moving the optional packages into the J2SE core, J2SE 1.4 will also feature two new security packages:

  • Java CertPath API: Classes, methods, and interfaces to build and validate certificate chains
  • JGSS API: Java bindings for the Generic Security Services API

The bulk of this article will be devoted to looking into these two packages.

Other changes

As a result of JAAS becoming an integral part of core security, access control is no longer solely based on code source (i.e., where the code is from and who signed it), but also on who is running the code. As a result, both the Policy files and the graphical Policy tool have been enhanced to accommodate the changes.

Next, strong cipher support is available via JCE and JSSE, albeit with some important control restrictions. In JCE, the cryptographic strengths are limited through the jurisdiction files by default. JSSE, for its part, now restricts the replacement of the default SSLSocketFactory and SSLServerSocketFactory classes.

Moreover, you’ll find support for dynamic policies. Prior to J2SE 1.4, the security policy was associated at the time of class loading. In 1.4, the security policy association is deferred until the security check becomes necessary.

In addition, J2SE 1.4 includes some changes to the functionality of the security classes. As an example, the javax.security.cert class is available only for backward compatibility, with its functionality carried forward by the java.security.cert class. Newer applications should use this class.

Finally, applet security as enforced by 1.4 is different, which we’ll look into in the next section.

Java Plug-in enhancements

You’ll see some changes in security between the J2SE 1.3 Java Plug-in and the 1.4 Java Plug-in (for more, see Sidebar 1: Java Plug-in Primer). Since we are interested in security, I explore the changes by revisiting the signed applets developed in Part 3.

Security in the J2SE 1.3 Java Plug-in

To illustrate how the J2SE 1.3 Plug-in handles applet security, let’s first look at the writeFile applet from Part 3 of this series. Execute the writeFile signed applet under the J2SE 1.3 Java Plug-in. Make sure that the policy files do not allow the temp file (/tmp/foo on Unix systems and c:tmpfoo on Windows) to be modified. If the clock on your system is set correctly, the signed applet’s signature should not validate because it has expired; therefore, the applet will not initialize. If you set your system’s clock back to a date between December 13, 2000 and December 21, 2001 (that is, to a time when the certificate is valid), the signature validates, and you should see a dialog box asking whether the applet should run or not.

As another example, run the signed applet discussed in “JDK 1.2 — Signed Applet Example” under the J2SE 1.3 Java Plug-in. The applet has been signed by a key — Duke — whose public key has been self-certified. That means the Certification Authority (CA) used to sign the certificate is not trusted by default in the environment. As a result, the signature validation fails again, and the dialog box again fails to pop up.

Security in the J2SE 1.4 Java Plug-in

Now, let’s run the same applet examples under the J2SE 1.4 Java Plug-in.

When executing the example from Part 3, the signed applet with the expired certificate, the user sees a dialog box clearly indicating that the certificate is expired, as shown in Figure 1. Here, the ultimate decision to execute the applet is left to the user’s discretion.

Figure 1. Signed applet with an expired certificate

Likewise, in the second example of the signed applet with the untrusted certificate, the user sees a dialog box, this time indicating that the CA cannot be trusted. The applet can still be executed if the user so chooses, as seen in Figure 2.

Figure 2. Signed applet with a certificate signed by an untrusted CA. (Source: Sun Microsystems Inc.)

To summarize the differences between security in the J2SE 1.3 and 1.4 Java Plug-ins: In 1.4, if the signature validates successfully, the dialog box pops up with a message indicating that the certificate is valid, as shown in Figure 3.

Figure 3. Signed applet with a valid certificate

Under the J2SE 1.4 Java Plug-in, if the signature does not validate, the dialog box still pops up under the cases we’ve seen above. The dialog box clearly warns against potential security holes but leaves the final decision of initializing the applet to the user. With the J2SE 1.3 Java Plug-in, the applet fails to initialize unless the user does something explicitly, such as setting the policies or adjusting the system clock.

Clearly, the J2SE 1.4 Java Plug-in offers the user greater flexibility. Moreover, in an intranet environment, you may no longer be required to sign applets with an external CA; a company-wide CA would suffice. The downside of this flexibility is that some responsibility for validating the signature now shifts to the user. That shift is probably all right, since technology can only so go far to validate a signature. The aspect of trusting a user based on the signature is an interpersonal issue and is left to the user anyway. Technology cannot address this important issue (and I hope it never will).

Now that we have covered some familiar ground, let’s move on to J2SE 1.4’s new packages. In the examples we looked at above, the Java Plug-in had to validate a certificate or a certificate chain. If, however, we had to build or validate a certificate chain in a program, we would use the Java CertPath API.

Java CertPath API

The Java CertPath API comprises classes and interfaces to manipulate an ordered list of certificates, referred to as certification paths (or certificate chains). Based on the validation results, you can associate a public key with a subject.

As we’ve seen, certificates serve as digital identities. As such, a certificate associates a public key with an identity. A CA vouches the digital identity by signing the certificate with the CA’s private key. To verify a certificate’s identity, the relying party should have a trusted copy of the CA’s public key. In the absence of such a trusted copy, a certificates chain, the certification path, is needed, with each certificate vouching for the previous one until a certificate the relying party implicitly trusts is found.

The example illustrated in Figure 4 includes a CA hierarchy. Let’s look at a case when bob tries to validate the public key of the subject, alice. Since bob does not trust alice’s public key directly, a certificates chain is needed to validate alice’s key until a public key that bob trusts can be found. This chain is based on alice’s key signed by a CA, CA3, which is then signed by CA1. Finally, a CA, referred to as the Root CA or the most-trusted CA, is found. The relying party, in this case bob, trusts this Root CA perched topmost in the certificate chain hierarchy.

Likewise, if alice were to validate bob’s key, the certificate path bob-CA4-CA2-Root CA would be required, assuming alice trusts the Root CA’s public key.

Figure 4. Hierarchy of CAs

To make such certificate-chain validation possible in programs, signatures must be verified, certification revocation and validity must be checked, and so on. Further, a certificate chain from the most-trusted CA to the subject may have to be found by other means, such as with access to LDAP (Lightweight Directory Access Protocol).

Building and validating certification paths is routinely carried out in security protocols such as SSL/TLS, S/MIME, IPSec, and so on. We saw how the Java Plug-in validated a certificate (or a chain). The Java CertPath API proves useful in all such cases.

I briefly examined X.509 in earlier articles of this series. The X.509 certificate standard in part provides confidence for doing business online. The Public-Key Infrastructure X.509 (PKIX) working group develops Internet standards needed to support X.509 PKI.

The Java CertPath API is based on the provider architecture introduced in the Java Connector Architecture (JCA). The provider architecture allows user programs to use the same API, but different providers can be plugged in via a Service Provider Interface (SPI). The Sun provider supports the PKIX standard.

Java CertPath API classes and interfaces

Now that we’ve seen Java CertPath’s function, let’s examine its classes for building and validating certification paths. Each class below exists in the java.security.cert package:

  • Core classes:
    • The abstract CertPath captures the functionality shared by all certification path objects. For example, its getCertificates() abstract method returns the certificates list in the path.
    • In J2SE 1.4 the CertificateFactory now supports certification path objects.
    • The interface CertPathParameters specifies parameters to the Certification Path algorithms. For example, the class PKIXParameters that implements the interface can set PKIX parameters such as time of validity, policy constraints, target certificate constraints, and user-defined checks, among others.
  • Validation classes:
    • CertPathValidator validates a certification path.
    • The CertPathValidatorResult interface captures the results from the CertPathValidator certification path validation.
  • Building classes:
    • The CertPathBuilder class, like CertPathValidator, builds certification paths.
    • CertPathBuilderResult captures the results of CertPathBuilder‘s path building.
  • Storage classes:
    • CertStore provides the functionality of a certificate and certificate revocation list (CRL) repository, such as LDAP. The methods getCertifcates() and getCRLs() retrieve certificates and CRLs, respectively.
    • CertStoreParameters specifies all CertStore parameters. In conjunction with the CertStore.getInstance()method, the CertStoreParameters class obtains a CertStore with the appropriate properties.
    • The CertSelector interface serves as an argument to the respective methods, allowing them to specify a set of criteria for the respective selection.
    • The CRLSelector interface also serves as an argument to the respective methods.

Having briefly looked at the classes and some methods, in the next section we see how to use them.

Java Certification Path programming model

Next, we see an example of validating a Certification Path of X.509 certificates. The following steps illustrate how to accomplish that task:

    // Fetch or build a certificate chain
    Certificate[] certArray = pks.getCertificateChain("rags");
    // Convert chain to a List
    List certList = Arrays.asList(certArray);
    // Instantiate a CertificateFactory for X.509 
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    // Extract the certification path from
    // the List of Certificates
     CertPath cp = cf.generateCertPath(certList);
    // Create CertPathValidator that implements the "PKIX" algorithm
    CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
     // Set the Trust anchor
    TrustAnchor anchor = new TrustAnchor((X509Certificate)tks.getCertificate("ca"), null);
    // Set the PKIX parameters
    PKIXParameters params = new PKIXParameters(Collections.singleton(anchor));
    params.setRevocationEnabled(false);
    // Validate and obtain results
    try {
        PKIXCertPathValidatorResult result =
            (PKIXCertPathValidatorResult) cpv.validate(cp, params);
     } catch (CertPathValidatorException cpve) {
        System.out.println("Validation failure, cert[" 
            + cpve.getIndex() + "] :" + cpve.getMessage());
     }

The code snippet above illustrates the validation of a certificate chain from the keystore using a trust anchor obtained from a truststore.

Java Certification Path example programs

For the purposes of the examples, we have disabled revocation checking to make the sample code easier to execute. The PKIX validation algorithm requires us to check the revocation status of each certificate in a chain. The user should be aware of the security risks associated with explicitly disabling certificate revocation checking.

To illustrate the programming model highlighted above, we validate a self-certified certificate chain using the same key as trust anchor. The example is not a useful real-life example, but nevertheless illustrates the API’s use:

Example 1, Step 1. Create a keystore with a key, which also self-certifies it.

C:rags>keytool -genkey -alias rags -keystore certpath.keystore
Enter keystore password:  changeit
What is your first and last name?
  [Unknown]:  Rags Srinivas
What is the name of your organizational unit?
  [Unknown]:  SDN
What is the name of your organization?
  [Unknown]:  Sun
What is the name of your City or Locality?
  [Unknown]:  Burlington
What is the name of your State or Province?
  [Unknown]:  MA
What is the two-letter country code for this unit?
  [Unknown]:  US
Is CN=Rags Srinivas, OU=SDN, O=Sun, L=Burlington, ST=MA, C=US correct?
  [no]:  yes
Enter key password for <rags>
        (RETURN if same as keystore password):

Example 1, Step 2. Verify whether the certificate chain has been properly generated. The certificate chain length should be 1 and the owner and issuer must be identical.

C:rags>keytool -list -v -alias rags -keystore certpath.keystore
Enter keystore password:  changeit
Alias name: rags
Creation date: Dec 10, 2001
Entry type: keyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Rags Srinivas, OU=SDN, O=Sun, L=Burlington, ST=MA, C=US
Issuer: CN=Rags Srinivas, OU=SDN, O=Sun, L=Burlington, ST=MA, C=US
Serial number: 3c148eca
Valid from: Mon Dec 10 05:30:34 EST 2001 until: Sun Mar 10 05:30:34 EST 2002
Certificate fingerprints:
         MD5:  97:40:C2:87:14:FD:54:1F:E3:EB:3E:27:C0:34:70:A8
         SHA1: B1:0E:0A:78:EA:10:D9:21:31:1F:DB:F2:2F:26:8B:97:77:5D:07:69

Example 1, Step 3. Compile and run the following program, which reads the self-certified chain from the keystore and validates it against the same certificate. The example program ignores some of the possible exceptions that could be generated.

/**
 * ValidateSelfCert : validates an X.509 certification path
 *      using a PKIX CertPathValidator
 *
 * Synopsis: java ValidateSelfCert keystore password alias
 *
 * The program validates the certificate chain in the keystore
 *  referred by the "alias".
 */
import java.security.*;
import java.security.cert.*;
import java.util.*;
import java.io.*;
class ValidateSelfCert
{
    public static void main(String args[])
    {
        // Instantiate a KeyStore with type JKS
        try {
            if (args.length != 3)
                throw new Exception("ValidateCert " + "keystore " + "password " + "alias");
           KeyStore ks = KeyStore.getInstance("JKS");
            // Load the contents of the KeyStore
            ks.load(new FileInputStream(args[0]),
                args[1].toCharArray());
             // Fetch certificate chain stored with alias "rags"
             java.security.cert.Certificate[] certArray = ks.getCertificateChain(args[2]);
             if (certArray == null)
                throw new Exception("Alias " + args[2] + " is not a certificate chain");
             // Convert chain to a List
             List certList = Arrays.asList(certArray);
             // Instantiate a CertificateFactory for X.509
             CertificateFactory cf = CertificateFactory.getInstance("X.509");
             // Extract the certification path from
             // the List of Certificates
             CertPath cp = cf.generateCertPath(certList);
             // Create CertPathValidator that implements the "PKIX" algorithm
             CertPathValidator cpv = null;
             cpv = CertPathValidator.getInstance("PKIX");
             // Set the Trust anchor
             TrustAnchor anchor = new TrustAnchor((X509Certificate)ks.getCertificate(args[2]), null);
             // Set the PKIX parameters
             PKIXParameters params = new PKIXParameters(Collections.singleton(anchor));
             params.setRevocationEnabled(false);
             // Validate and obtain results
             try {
                 PKIXCertPathValidatorResult result =
                     (PKIXCertPathValidatorResult) cpv.validate(cp, params);
                 PolicyNode policyTree = result.getPolicyTree();
                 PublicKey subjectPublicKey = result.getPublicKey();
                 System.out.println("Certificate validated");
                 System.out.println("Policy Tree:n" + policyTree);
                 System.out.println("Subject Public key:n" +subjectPublicKey);
             } catch (CertPathValidatorException cpve) {
                 System.out.println("Validation failure, cert[" 
                     + cpve.getIndex() + "] :" + cpve.getMessage());
             }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

You should see output resembling:

C:rags>java ValidateSelfCert certpath.keystore changeit rags
Certificate validated
Policy Tree:
null
Subject Public key:
Sun DSA Public Key
    Parameters:DSA
        p:     fd7f5381 1d751229 52df4a9c 2eece4e7 f611b752 3cef4400 c31e3f80 b6512669
    455d4022 51fb593d 8d58fabf c5f5ba30 f6cb9b55 6cd7813b 801d346f f26660b7
    6b9950a5 a49f9fe8 047b1022 c24fbba9 d7feb7c6 1bf83b57 e7c6a8a6 150f04fb
    83f6d3c5 1ec30235 54135a16 9132f675 f3ae2b61 d72aeff2 2203199d d14801c7
        q:     9760508f 15230bcc b292b982 a2eb840b f0581cf5
        g:     f7e1a085 d69b3dde cbbcab5c 36b857b9 7994afbb fa3aea82 f9574c0b 3d078267
    5159578e bad4594f e6710710 8180b449 167123e8 4c281613 b7cf0932 8cc8a6e1
    3c167a8b 547c8d28 e0a3ae1e 2bb3a675 916ea37f 0bfa2135 62f1fb62 7a01243b
    cca4f1be a8519089 a883dfe1 5ae59f06 928b665e 807b5525 64014c3b fecf492a
  y:
    5834e353 dbc0be85 fce9c28d 1679066c b2a93d23 651f731b 40c96e2f 445db11b
    82209777 2cce98a8 65aa5545 5a0d4e3a 45b52fe3 24276c7b 7f8f5189 162626cc
    bf98703f 9350b49f 7ae22330 dfe11f89 928f3acc 69e69419 d73ca568 a0f459c1
    743028b3 b59977a3 66b0383c aaf01645 efa7091d 493e6b8c 15f06391 c780f6e2

The example above illustrates a certification path validation. However, the example seems unrealistic since the validation concerns a self-certified certificate.

In a real-life scenario, certification paths will validate against standard CAs, using CRLs. You’ll find a more realistic scenario in Example 2.

Example 2, Step 1. Obtain a certificate chain beginning or ending with a standard CA. The following certificate serves as an example. You may want to obtain your own certificate chain by validating your certificate request from a CA.

C:rags>type verisign.cer
-----BEGIN CERTIFICATE-----
MIAGCSqGSIb3DQEHAqCAMIACAQExADALBgkqhkiG9w0BBwGggDCCB3AwggbZoAMC
AQICEHFplLgCsdyOEiRuw5RKX1wwDQYJKoZIhvcNAQEEBQAwgcgxFzAVBgNVBAoT
DlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3Jr
MUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvUlBBIEluY29y
cC4gYnkgUmVmLixMSUFCLkxURChjKTk4MUQwQgYDVQQDEztWZXJpU2lnbiBDbGFz
cyAzIENBIC0gQ29tbWVyY2lhbCBDb250ZW50L1NvZnR3YXJlIFB1Ymxpc2hlcjAe
Fw0wMTAzMjkwMDAwMDBaFw0wMjAzMjkyMzU5NTlaMIIBDjEXMBUGA1UEChMOVmVy
aVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxRjBE
BgNVBAsTPXd3dy52ZXJpc2lnbi5jb20vcmVwb3NpdG9yeS9SUEEgSW5jb3JwLiBi
eSBSZWYuLExJQUIuTFREKGMpOTkxMTAvBgNVBAsTKERpZ2l0YWwgSUQgQ2xhc3Mg
MyAtIEphdmEgT2JqZWN0IFNpZ25pbmcxGTAXBgNVBAMUEFN1biBNaWNyb3N5c3Rl
bXMxDTALBgNVBAsUBE1ERFIxEzARBgNVBAcTCkJ1cmxpbmd0b24xCzAJBgNVBAgT
Ak1BMQswCQYDVQQGEwJVUzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAz4XG
ut3Y9h5ihAwYvp2BklMbUFml/mSjoOA328yuc+UoJ9McsRcEMmx1nTWtIzL2Q/bU
RKH8OnGx845vwVnbxy3HgG+9hC+BT8jtcJeriFYS+j7LQ+jJkYJa1++WXxTQyMNu
yxzcOrxpRaxQvr49Nn+uYn0gkCswjM1JY04I24MCAwEAAaOCBBAwggQMMAkGA1Ud
EwQCMAAwCwYDVR0PBAQDAgWgMBEGCWCGSAGG+EIBAQQEAwIEEDA2BglghkgBhvhC
AQgEKRYnaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvQ1BTMIID
jQYJYIZIAYb4QgENBIIDfhaCA3pUaGlzIGNlcnRpZmljYXRlIGluY29ycG9yYXRl
cyBieSByZWZlcmVuY2UsIGFuZCAKaXRzIHVzZSBpcyBzdHJpY3RseSBzdWJqZWN0
IHRvLCB0aGUgVmVyaVNpZ24gCkNlcnRpZmljYXRpb24gUHJhY3RpY2UgU3RhdGVt
ZW50IChDUFMpLCBhdmFpbGFibGUKaW4gdGhlIFZlcmlTaWduIHJlcG9zaXRvcnkg
YXQ6IApodHRwczovL3d3dy52ZXJpc2lnbi5jb207IGJ5IEUtbWFpbCBhdApDUFMt
cmVxdWVzdHNAdmVyaXNpZ24uY29tOyBvciBieSBtYWlsIGF0IFZlcmlTaWduLApJ
bmMuLCAyNTkzIENvYXN0IEF2ZS4sIE1vdW50YWluIFZpZXcsIENBIDk0MDQzIFVT
QQoKQ29weXJpZ2h0IChjKTE5OTYgVmVyaVNpZ24sIEluYy4gIEFsbCBSaWdodHMg
ClJlc2VydmVkLiAKCldBUk5JTkc6IFRIRSBVU0UgT0YgVEhJUyBDRVJUSUZJQ0FU
RSBJUyBTVFJJQ1RMWQpTVUJKRUNUIFRPIFRIRSBWRVJJU0lHTiBDRVJUSUZJQ0FU
SU9OIFBSQUNUSUNFClNUQVRFTUVOVC4gIFRIRSBJU1NVSU5HIEFVVEhPUklUWSBE
SVNDTEFJTVMgQ0VSVEFJTgpJTVBMSUVEIEFORCBFWFBSRVNTIFdBUlJBTlRJRVMs
IElOQ0xVRElORyBXQVJSQU5USUVTCk9GIE1FUkNIQU5UQUJJTElUWSBPUiBGSVRO
RVNTIEZPUiBBIFBBUlRJQ1VMQVIKUFVSUE9TRSwgQU5EIFdJTEwgTk9UIEJFIExJ
QUJMRSBGT1IgQ09OU0VRVUVOVElBTCwKUFVOSVRJVkUsIEFORCBDRVJUQUlOIE9U
SEVSIERBTUFHRVMuIFNFRSBUSEUgQ1BTCkZPUiBERVRBSUxTLgoKQ29udGVudHMg
b2YgdGhlIFZlcmlTaWduIHJlZ2lzdGVyZWQKbm9udmVyaWZpZWRTdWJqZWN0QXR0
cmlidXRlcyBleHRlbnNpb24gdmFsdWUgc2hhbGwgCm5vdCBiZSBjb25zaWRlcmVk
IGFzIGFjY3VyYXRlIGluZm9ybWF0aW9uIHZhbGlkYXRlZCAKYnkgdGhlIElBLjAW
BgorBgEEAYI3AgEbBAgwBgEBAAEB/zANBgkqhkiG9w0BAQQFAAOBgQDJn6qbpwJs
o5Tysnbj8tIaX4i5P3kY65Coofi5JHFF2qG7wIH4LLvNBkUr+mEbPRD+jpUdaCM4
nf2gHyhB1uTcFrQtV8Zqx7gUjC0Ndqs8jpmPneJo8jGQ8U5eCgKHGgxVjP1QViaB
8m/NMZP2v1EL5n3+zsKF4xqyVkuMmtURkDCCA4gwggLxoAMCAQICEQDL4hP+j/J6
JPdDkHw35sUaMA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQK
Ew5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFy
eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05ODEyMzEwMDAwMDBaFw0wNDAx
MDYyMzU5NTlaMIHIMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMW
VmVyaVNpZ24gVHJ1c3QgTmV0d29yazFGMEQGA1UECxM9d3d3LnZlcmlzaWduLmNv
bS9yZXBvc2l0b3J5L1JQQSBJbmNvcnAuIGJ5IFJlZi4sTElBQi5MVEQoYyk5ODFE
MEIGA1UEAxM7VmVyaVNpZ24gQ2xhc3MgMyBDQSAtIENvbW1lcmNpYWwgQ29udGVu
dC9Tb2Z0d2FyZSBQdWJsaXNoZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
AMwDv0OpVc4RkrY16GDdlPVCVnDUNt1kF4iXjE36csP4vR1frVAxyOPRWkLO2YmX
tjWkmM8aKrNS8YoxrIynXjcGeANLqu0Sfmr64jbRx/VHL1VNftzN4ECyIFxSOpHW
WtzWlTZto4XA/ybUItwv+ReVQlhRjRLELziznveIqoJ1AgMBAAGjgdkwgdYwIwYD
VR0RBBwwGqQYMBYxFDASBgNVBAMTC0NsYXNzM0NBMS0zMEcGA1UdIARAMD4wPAYL
YIZIAYb4RQEHAQEwLTArBggrBgEFBQcCARYfd3d3LnZlcmlzaWduLmNvbS9yZXBv
c2l0b3J5L1JQQTAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjA1BgNVHR8E
LjAsMCqgKKAmhiRodHRwOi8vY3JsLnZlcmlzaWduLmNvbS9wY2EzLjEuMS5jcmww
EQYJYIZIAYb4QgEBBAQDAgABMA0GCSqGSIb3DQEBAgUAA4GBAEX3+xIpzyHQlCu1
ulIBa1kfTTCMQAdHRdE+ZSZjy6jLZsI6YJOt3HaC3D6/+IOQ4fVOBrWmy4yfr7yA
4n+qqqNc4gt1RUKgXVDHmZKJ9nandj27TshjUmtBrmUn/FGP3W12t3cAJoW9SRIu
EBH+Lx97yU48SQNlOoMnc7kxeJ+4AAAxAAAAAAAAAA==
-----END CERTIFICATE-----

Example 2, Step 2. Verify whether the certificate chain has been properly generated. The certificate chain length should be greater than 1 and signed by a standard CA.

C:rags>keytool -printcert -file verisign.cer
Certificate[1]:
Owner: C=US, ST=MA, L=Burlington, OU=MDDR, CN=Sun Microsystems, OU=Digital ID Class 3 - Java Object Signing, OU="www.verisign.com/repository/RPA Incorp. by Ref.,LIAB.LTD(c)99", OU=VeriSign Trust Network, O="VeriSign, Inc."
Issuer: CN=VeriSign Class 3 CA - Commercial Content/Software Publisher, OU="www.verisign.com/repository/RPA Incorp. by Ref.,LIAB.LTD(c)98", OU=VeriSign Trust Network, O="VeriSign, Inc."
Serial number: 716994b802b1dc8e12246ec3944a5f5c
Valid from: Wed Mar 28 19:00:00 EST 2001 until: Fri Mar 29 18:59:59 EST 2002
Certificate fingerprints:
         MD5:  8C:DA:A6:0B:38:7C:09:B2:2E:51:94:02:FA:18:EC:76
         SHA1: 68:49:64:A3:15:0C:C7:68:82:69:05:85:AE:05:0E:41:1E:C2:D9:F3
Certificate[2]:
Owner: CN=VeriSign Class 3 CA - Commercial Content/Software Publisher, OU="www.verisign.com/repository/RPA Incorp. by Re
f.,LIAB.LTD(c)98", OU=VeriSign Trust Network, O="VeriSign, Inc."
Issuer: OU=Class 3 Public Primary Certification Authority, O="VeriSign, Inc.", C=US
Serial number: cbe213fe8ff27a24f743907c37e6c51a
Valid from: Wed Dec 30 19:00:00 EST 1998 until: Tue Jan 06 18:59:59 EST 2004
Certificate fingerprints:
         MD5:  3D:65:D5:67:C2:75:90:3D:3A:9E:20:82:FE:A0:C5:9C
         SHA1: 48:8D:67:77:D8:6F:E4:BA:FF:E8:A2:BC:A3:E6:29:95:81:D5:2E:04

Example 2, Step 3. Obtain the certificate corresponding to the trusted anchor (Verisign Class 3 CA, in this example). In this case, we obtain the trusted anchor’s certificate from the cacerts file, which contains some standard CAs’ certificates.

C:rags>keytool -export -alias verisignclass3ca -keystore c:jdk1.4jrelibsecuritycacerts -file verisignclass3ca.cer
Enter keystore password:  changeit
Certificate stored in file <verisignclass3ca.cer>

Example 2, Step 4. Now run the following program, which validates the certificate chain shown in Step 2, with the standard CA used in Step 3.

/**
 * ValidateCertPath : validates an X.509 certification path
 *      using a PKIX CertPathValidator
 *
 * Synopsis: java ValidateCertPath trustAnchor certPath
 *      or
 *           java ValidateCertPath trustAnchor targetCert intermediateCACert ...
 *
 *      The "trustAnchor" parameter is the name of a file containing
 *      an encoded X.509 trusted CA cert in DER or Base64 format. The"certPath"
 *      parameter is the name of a file containing a PKCS7 or base64 encoded
 *      X.509 cert chain. The "targetCert" and "intermediateCACert" parameters
 *      are the names of a sequence of files representing a chain of certificates.
 *      These files must contain certificates in the same format as "trustAnchor".
 * Author: Sean Mullan
 */
import java.io.*;
import java.security.cert.*;
import java.util.*;
public class ValidateCertPath {
    public static void main(String[] args) throws Exception {
    if (args.length == 0)
        throw new Exception("must specify at least trustAnchor");
    PKIXParameters params = createParams(args[0]);
    CertPath cp = null;
    if (args.length == 2 && (args[1].endsWith("pkcs7") || args[1].endsWith("cer"))) {
        cp = createPath(args[1]);
    } else {
        cp = createPath(args);
    }
    System.out.println("path: " + cp);
    CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
    CertPathValidatorResult cpvr = cpv.validate(cp, params);
    System.out.println(cpvr);
    }
    public static PKIXParameters createParams(String anchorFile) throws Exception {
        TrustAnchor anchor = new TrustAnchor(getCertFromFile(anchorFile), null);
        Set anchors = Collections.singleton(anchor);
        PKIXParameters params = new PKIXParameters(anchors);
        params.setRevocationEnabled(false);
        return params;
    }
    public static CertPath createPath(String certPath) throws Exception {
        File certPathFile = new File(certPath);
        FileInputStream certPathInputStream = new FileInputStream(certPathFile);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
    try {
            return cf.generateCertPath(certPathInputStream, "PKCS7");
    } catch (CertificateException ce) {
        // try generateCertificates
                      Collection c = cf.generateCertificates(certPathInputStream);
        return cf.generateCertPath(new ArrayList(c));
    }
    }
    public static CertPath createPath(String[] certs) throws Exception {
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
        List list = new ArrayList();
        for (int i = 1; i < certs.length; i++) {
            list.add(getCertFromFile(certs[i]));
        }
    CertPath cp = cf.generateCertPath(list);
    return cp;
    }
    /**
     * Get a DER or BASE64-encoded X.509 certificate from a file.
     *
     * @param certFilePath path to file containing DER or BASE64-encoded certificate
     * @return X509Certificate
     * @throws Exception on error
     */
    public static X509Certificate getCertFromFile(String certFilePath)
        throws Exception {
        X509Certificate cert = null;
        File certFile = new File(certFilePath);
        FileInputStream certFileInputStream = new FileInputStream(certFile);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        cert = (X509Certificate) cf.generateCertificate(certFileInputStream);
        return cert;
    }
}

You should see output resembling:

C:rags>java ValidateCertPath verisignclass3ca.cer verisign.cer
path:
X.509 Cert Path: length = 2.
[
=========================================================Certificate 1 start.
[
[
  Version: V3
  Subject: C=US, ST=MA, L=Burlington, OU=MDDR, CN=Sun Microsystems, OU=Digital ID Class 3 - Java Object Signing, OU="ww
.verisign.com/repository/RPA Incorp. by Ref.,LIAB.LTD(c)99", OU=VeriSign Trust Network, O="VeriSign, Inc."
  Signature Algorithm: MD5withRSA, OID = 1.2.840.113549.1.1.4
  Key:  com.sun.net.ssl.internal.ssl.JSA_RSAPublicKey@c2a132
  Validity: [From: Wed Mar 28 19:00:00 EST 2001,
               To: Fri Mar 29 18:59:59 EST 2002]
  Issuer: CN=VeriSign Class 3 CA - Commercial Content/Software Publisher, OU="www.verisign.com/repository/RPA Incorp. b
 Ref.,LIAB.LTD(c)98", OU=VeriSign Trust Network, O="VeriSign, Inc."
  SerialNumber: [    716994b8 02b1dc8e 12246ec3 944a5f5c ]
Certificate Extensions: 6
[1]: ObjectId: 2.16.840.1.113730.1.13 Criticality=false
Extension unknown: DER encoded OCTET string =
0000: 04 82 03 7E 16 82 03 7A   54 68 69 73 20 63 65 72  .......zThis cer
0010: 74 69 66 69 63 61 74 65   20 69 6E 63 6F 72 70 6F  tificate incorpo
0020: 72 61 74 65 73 20 62 79   20 72 65 66 65 72 65 6E  rates by referen
0030: 63 65 2C 20 61 6E 64 20   0A 69 74 73 20 75 73 65  ce, and .its use
0040: 20 69 73 20 73 74 72 69   63 74 6C 79 20 73 75 62   is strictly sub
0050: 6A 65 63 74 20 74 6F 2C   20 74 68 65 20 56 65 72  ject to, the Ver
0060: 69 53 69 67 6E 20 0A 43   65 72 74 69 66 69 63 61  iSign .Certifica
0070: 74 69 6F 6E 20 50 72 61   63 74 69 63 65 20 53 74  tion Practice St
0080: 61 74 65 6D 65 6E 74 20   28 43 50 53 29 2C 20 61  atement (CPS), a
0090: 76 61 69 6C 61 62 6C 65   0A 69 6E 20 74 68 65 20  vailable.in the
00A0: 56 65 72 69 53 69 67 6E   20 72 65 70 6F 73 69 74  VeriSign reposit
00B0: 6F 72 79 20 61 74 3A 20   0A 68 74 74 70 73 3A 2F  ory at: .https:/
00C0: 2F 77 77 77 2E 76 65 72   69 73 69 67 6E 2E 63 6F  /www.verisign.co
00D0: 6D 3B 20 62 79 20 45 2D   6D 61 69 6C 20 61 74 0A  m; by E-mail at.
00E0: 43 50 53 2D 72 65 71 75   65 73 74 73 40 76 65 72  CPS-requests@ver
00F0: 69 73 69 67 6E 2E 63 6F   6D 3B 20 6F 72 20 62 79  isign.com; or by
0100: 20 6D 61 69 6C 20 61 74   20 56 65 72 69 53 69 67   mail at VeriSig
0110: 6E 2C 0A 49 6E 63 2E 2C   20 32 35 39 33 20 43 6F  n,.Inc., 2593 Co
0120: 61 73 74 20 41 76 65 2E   2C 20 4D 6F 75 6E 74 61  ast Ave., Mounta
0130: 69 6E 20 56 69 65 77 2C   20 43 41 20 39 34 30 34  in View, CA 9404
0140: 33 20 55 53 41 0A 0A 43   6F 70 79 72 69 67 68 74  3 USA..Copyright
0150: 20 28 63 29 31 39 39 36   20 56 65 72 69 53 69 67   (c)1996 VeriSig
0160: 6E 2C 20 49 6E 63 2E 20   20 41 6C 6C 20 52 69 67  n, Inc.  All Rig
0170: 68 74 73 20 0A 52 65 73   65 72 76 65 64 2E 20 0A  hts .Reserved. .
0180: 0A 57 41 52 4E 49 4E 47   3A 20 54 48 45 20 55 53  .WARNING: THE US
0190: 45 20 4F 46 20 54 48 49   53 20 43 45 52 54 49 46  E OF THIS CERTIF
01A0: 49 43 41 54 45 20 49 53   20 53 54 52 49 43 54 4C  ICATE IS STRICTL
01B0: 59 0A 53 55 42 4A 45 43   54 20 54 4F 20 54 48 45  Y.SUBJECT TO THE
01C0: 20 56 45 52 49 53 49 47   4E 20 43 45 52 54 49 46   VERISIGN CERTIF
01D0: 49 43 41 54 49 4F 4E 20   50 52 41 43 54 49 43 45  ICATION PRACTICE
01E0: 0A 53 54 41 54 45 4D 45   4E 54 2E 20 20 54 48 45  .STATEMENT.  THE
01F0: 20 49 53 53 55 49 4E 47   20 41 55 54 48 4F 52 49   ISSUING AUTHORI
0200: 54 59 20 44 49 53 43 4C   41 49 4D 53 20 43 45 52  TY DISCLAIMS CER
0210: 54 41 49 4E 0A 49 4D 50   4C 49 45 44 20 41 4E 44  TAIN.IMPLIED AND
0220: 20 45 58 50 52 45 53 53   20 57 41 52 52 41 4E 54   EXPRESS WARRANT
0230: 49 45 53 2C 20 49 4E 43   4C 55 44 49 4E 47 20 57  IES, INCLUDING W
0240: 41 52 52 41 4E 54 49 45   53 0A 4F 46 20 4D 45 52  ARRANTIES.OF MER
0250: 43 48 41 4E 54 41 42 49   4C 49 54 59 20 4F 52 20  CHANTABILITY OR
0260: 46 49 54 4E 45 53 53 20   46 4F 52 20 41 20 50 41  FITNESS FOR A PA
0270: 52 54 49 43 55 4C 41 52   0A 50 55 52 50 4F 53 45  RTICULAR.PURPOSE
0280: 2C 20 41 4E 44 20 57 49   4C 4C 20 4E 4F 54 20 42  , AND WILL NOT B
0290: 45 20 4C 49 41 42 4C 45   20 46 4F 52 20 43 4F 4E  E LIABLE FOR CON
02A0: 53 45 51 55 45 4E 54 49   41 4C 2C 0A 50 55 4E 49  SEQUENTIAL,.PUNI
02B0: 54 49 56 45 2C 20 41 4E   44 20 43 45 52 54 41 49  TIVE, AND CERTAI
02C0: 4E 20 4F 54 48 45 52 20   44 41 4D 41 47 45 53 2E  N OTHER DAMAGES.
02D0: 20 53 45 45 20 54 48 45   20 43 50 53 0A 46 4F 52   SEE THE CPS.FOR
02E0: 20 44 45 54 41 49 4C 53   2E 0A 0A 43 6F 6E 74 65   DETAILS...Conte
02F0: 6E 74 73 20 6F 66 20 74   68 65 20 56 65 72 69 53  nts of the VeriS
0300: 69 67 6E 20 72 65 67 69   73 74 65 72 65 64 0A 6E  ign registered.n
0310: 6F 6E 76 65 72 69 66 69   65 64 53 75 62 6A 65 63  onverifiedSubjec
0320: 74 41 74 74 72 69 62 75   74 65 73 20 65 78 74 65  tAttributes exte
0330: 6E 73 69 6F 6E 20 76 61   6C 75 65 20 73 68 61 6C  nsion value shal
0340: 6C 20 0A 6E 6F 74 20 62   65 20 63 6F 6E 73 69 64  l .not be consid
0350: 65 72 65 64 20 61 73 20   61 63 63 75 72 61 74 65  ered as accurate
0360: 20 69 6E 66 6F 72 6D 61   74 69 6F 6E 20 76 61 6C   information val
0370: 69 64 61 74 65 64 20 0A   62 79 20 74 68 65 20 49  idated .by the I
0380: 41 2E                                              A.
[2]: ObjectId: 2.16.840.1.113730.1.1 Criticality=false
NetscapeCertType [
   Object Signing
]
[3]: ObjectId: 1.3.6.1.4.1.311.2.1.27 Criticality=false
Extension unknown: DER encoded OCTET string =
0000: 04 08 30 06 01 01 00 01   01 FF                    ..0.......
[4]: ObjectId: 2.16.840.1.113730.1.8 Criticality=false
Extension unknown: DER encoded OCTET string =
0000: 04 29 16 27 68 74 74 70   73 3A 2F 2F 77 77 77 2E  .).' 76 65 72 69 73 69 67 6E   2E 63 6F 6D 2F 72 65 70  verisign.com/rep
0020: 6F 73 69 74 6F 72 79 2F   43 50 53                 ository/CPS
[5]: ObjectId: 2.5.29.15 Criticality=false
KeyUsage [
  DigitalSignature
  Key_Encipherment
]
[6]: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:false
PathLen: undefined
]
]
  Algorithm: [MD5withRSA]
  Signature:
0000: C9 9F AA 9B A7 02 6C A3   94 F2 B2 76 E3 F2 D2 1A  ......l....v....
0010: 5F 88 B9 3F 79 18 EB 90   A8 A1 F8 B9 24 71 45 DA  _..?y.......$qE.
0020: A1 BB C0 81 F8 2C BB CD   06 45 2B FA 61 1B 3D 10  .....,...E+.a.=.
0030: FE 8E 95 1D 68 23 38 9D   FD A0 1F 28 41 D6 E4 DC  ....h#8....(A...
0040: 16 B4 2D 57 C6 6A C7 B8   14 8C 2D 0D 76 AB 3C 8E  ..-W.j....-.v.<.
0050: 99 8F 9D E2 68 F2 31 90   F1 4E 5E 0A 02 87 1A 0C  ....h.1..N^.....
0060: 55 8C FD 50 56 26 81 F2   6F CD 31 93 F6 BF 51 0B  U..PV&..o.1...Q.
0070: E6 7D FE CE C2 85 E3 1A   B2 56 4B 8C 9A D5 11 90  .........VK.....
]
=========================================================Certificate 1 end.
=========================================================Certificate 2 start.
[
[
  Version: V3
  Subject: CN=VeriSign Class 3 CA - Commercial Content/Software Publisher, OU="www.verisign.com/repository/RPA Incorp.
y Ref.,LIAB.LTD(c)98", OU=VeriSign Trust Network, O="VeriSign, Inc."
  Signature Algorithm: MD2withRSA, OID = 1.2.840.113549.1.1.2
  Key:  com.sun.net.ssl.internal.ssl.JSA_RSAPublicKey@2a54f9
  Validity: [From: Wed Dec 30 19:00:00 EST 1998,
               To: Tue Jan 06 18:59:59 EST 2004]
  Issuer: OU=Class 3 Public Primary Certification Authority, O="VeriSign, Inc.", C=US
  SerialNumber: [    cbe213fe 8ff27a24 f743907c 37e6c51a ]
Certificate Extensions: 6
[1]: ObjectId: 2.16.840.1.113730.1.1 Criticality=false
NetscapeCertType [
   Object Signing CA]
[2]: ObjectId: 2.5.29.31 Criticality=false
Extension unknown: DER encoded OCTET string =
0000: 04 2E 30 2C 30 2A A0 28   A0 26 86 24 68 74 74 70  ..0,0*.(.&.$http
0010: 3A 2F 2F 63 72 6C 2E 76   65 72 69 73 69 67 6E 2E  ://crl.verisign.
0020: 63 6F 6D 2F 70 63 61 33   2E 31 2E 31 2E 63 72 6C  com/pca3.1.1.crl
[3]: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
[CN=Class3CA1-3]]
[4]: ObjectId: 2.5.29.15 Criticality=false
KeyUsage [
  Key_CertSign
  Crl_Sign
]
[5]: ObjectId: 2.5.29.32 Criticality=false
CertificatePolicies [
  [CertificatePolicyId: [2.16.840.1.113733.1.7.1.1]
[PolicyQualifierInfo: [
  qualifierID: 1.3.6.1.5.5.7.2.1
  qualifier: 0000: 16 1F 77 77 77 2E 76 65   72 69 73 69 67 6E 2E 63  ..www.verisign.c
0010: 6F 6D 2F 72 65 70 6F 73   69 74 6F 72 79 2F 52 50  om/repository/RP
0020: 41                                                 A
]]  ]
]
[6]: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:true
PathLen:0
]
]
  Algorithm: [MD2withRSA]
  Signature:
0000: 45 F7 FB 12 29 CF 21 D0   94 2B B5 BA 52 01 6B 59  E...).!..+..R.kY
0010: 1F 4D 30 8C 40 07 47 45   D1 3E 65 26 63 CB A8 CB  [email protected].>e&c...
0020: 66 C2 3A 60 93 AD DC 76   82 DC 3E BF F8 83 90 E1  f.:`...v..<.....
0030: F5 4E 06 B5 A6 CB 8C 9F   AF BC 80 E2 7F AA AA A3  .N..............
0040: 5C E2 0B 75 45 42 A0 5D   50 C7 99 92 89 F6 76 A7  ..uEB.]P.....v.
0050: 76 3D BB 4E C8 63 52 6B   41 AE 65 27 FC 51 8F DD  v=.N.cRkA.e'.Q..
0060: 6D 76 B7 77 00 26 85 BD   49 12 2E 10 11 FE 2F 1F  mv.w.&..I...../.
0070: 7B C9 4E 3C 49 03 65 3A   83 27 73 B9 31 78 9F B8  ..N<I.e:.'s.1x..
]
=========================================================Certificate 2 end.
]
PKIXCertPathValidatorResult: [
  Trust Anchor: [
  Trusted CA cert: [
[
  Version: V1
  Subject: OU=Class 3 Public Primary Certification Authority, O="VeriSign, Inc.", C=US
  Signature Algorithm: MD2withRSA, OID = 1.2.840.113549.1.1.2
  Key:  com.sun.net.ssl.internal.ssl.JSA_RSAPublicKey@b1b4c3
  Validity: [From: Sun Jan 28 19:00:00 EST 1996,
               To: Wed Jan 07 18:59:59 EST 2004]
  Issuer: OU=Class 3 Public Primary Certification Authority, O="VeriSign, Inc.", C=US
  SerialNumber: [    e49efdf3 3ae80ecf a5113e19 a4240232 ]
]
  Algorithm: [MD2withRSA]
  Signature:
0000: 61 70 EC 2F 3F 9E FD 2B   E6 68 54 21 B0 67 79 08  ap./?..+.hT!.gy.
0010: 0C 20 96 31 8A 0D 7A BE   B6 26 DF 79 2C 22 69 49  . .1..z..&.y,"iI
0020: 36 E3 97 77 62 61 A2 32   D7 7A 54 21 36 BA 02 C9  6..wba.2.zT!6...
0030: 34 E7 25 DA 44 35 B0 D2   5C 80 5D B3 94 F8 F9 AC  4.%.D5...].....
0040: EE A4 60 75 2A 1F 95 49   23 B1 4A 7C F4 B3 47 72  ..`u*..I#.J...Gr
0050: 21 5B 7E 97 AB 54 AC 62   E7 5D EC AE 9B D2 C9 B2  ![...T.b.]......
0060: 24 FB 82 AD E9 67 15 4B   BA AA A6 F0 97 A0 F6 B0  $....g.K........
0070: 97 57 00 C8 0C 3C 09 A0   82 04 BA 41 DA F7 99 A4  .W...&tl;.....A....
]
  Policy Tree: null
  Subject Public Key: com.sun.net.ssl.internal.ssl.JSA_RSAPublicKey@c2a132
]

The examples above demonstrate how to validate certification paths. I haven’t covered building certification paths, but the process is similar.

Having looked at the Java CertPath API in some detail, let’s turn our attention to the JGSS API.

JGSS API

The JGSS API provides Java bindings for the Generic Security Services API — a uniform API for authentication and secure communication regardless of the underlying technology, as illustrated in Figure 5.

Figure 5. A multimechanism GSS implementation. (Source: Sun Microsystems.)

Figure 5 shows the two main standards used for network authentication: Kerberos version 5 and the Simple Public Key Mechanism (SPKM), each accessible using a common API. (For more on Kerberos, see “Sidebar 2: Kerberos Made Easy.”)

Presently, the Sun implementation only makes Kerberos version 5 available. Since JAAS performs authentication as well, developers typically use JAAS in conjunction with JGSS to accomplish complete authentication.

JGSS API classes and interfaces

The org.ietf.jgss package supports the following classes and interfaces:

  • GSSManager (class): Serves as a factory for other important JGSS API classes and creates instances of classes implementing the JGSS API interfaces mentioned next
  • GSSContext (interface): Manipulates the JGSS API security context and the security services available over the context
  • GSSCredntial (interface): Manipulates the JGSS API credentials for an entity
  • GSSName (interface): Encapsulates a single GSS API principal

In addition to these classes, several JAAS classes are used as well.

JGSS API programming model

The following four steps illustrate the use of the JGSS API:

  • The application acquires a set of credentials with which it may prove its identity to other applications
  • The communicating applications establish a joint security context using their credentials
  • Per-message services are invoked on a GSSContext object
  • The application(s) use one of the GSSContext‘s methods to invalidate the security context and release any resources held

Here’s the client’s outline:

    // get an instance of the default GSSManager
    GSSManager manager = GSSManager.getInstance();
    // Server name to connect 
    GSSName serverName = manager.createName(server, null);
    // Create the context
    GSSContext context = 
        manager.createContext(serverName,
                                                   krb5Oid,
                                                   null,
                                                   GSSContext.DEFAULT_LIFETIME);
    // Establish the context
    token = context.initSecContext(token, 0, token.length);
    // Send a token to the server if one was generated by
    // initSecContext
    if (token != null) {
        System.out.println("Will send token of size "
                                           + token.length + " from initSecContext.");
         outStream.writeInt(token.length);
         outStream.write(token);
         outStream.flush();
    }
    // More tokens ...
    if (context.getMutualAuthState())
        System.out.println("Mutual authentication took place!");
    // Encrypt message and send
    /*
     * The first MessageProp argument is 0 to request
     * the default Quality-of-Protection.
     * The second argument is true to request
     * privacy (encryption of the message).
     */
    MessageProp prop =  new MessageProp(0, true);
     /*
      * Encrypt the data and send it across. Integrity protection
      * is always applied, irrespective of encryption.
      */
     token = context.wrap(messageBytes, 0, messageBytes.length, 
        prop);
     System.out.println("Will send wrap token of size " 
         + token.length);
      outStream.writeInt(token.length);
      outStream.write(token);
      outStream.flush();

Next, here’s the server’s outline:

    // get an instance of the default GSSManager
    GSSManager manager = GSSManager.getInstance();
    // Server name to connect 
    GSSName serverName = manager.createName(server, null);
    // Create the context using default credentials
    GSSContext context = manager.createContext((GSSCredential)null);
    // Establish the context
    while (!context.isEstablished()) {
        token = new byte[inStream.readInt()];
        System.out.println("Will read input token of size "
            + token.length
            + " for processing by acceptSecContext");
         inStream.readFully(token);
                             
         token = context.acceptSecContext(token, 0, token.length);
    
         // Send a token to the peer if one was generated by
         // acceptSecContext
         if (token != null) {
             System.out.println("Will send token of size "
                 + token.length
                 + " from acceptSecContext.");
              outStream.writeInt(token.length);
              outStream.write(token);
              outStream.flush();
        }
    }
   System.out.print("Context Established! "); 
    
    if (context.getMutualAuthState())
        System.out.println("Mutual authentication took place!");
    // receive and decrypt message
    /*
     * Create a MessageProp which unwrap will use to return 
     * information such as the Quality-of-Protection that was 
     * applied to the wrapped token, whether or not it was 
     * encrypted, etc. Since the initial MessageProp values
     * are ignored, it doesn't matter what they are set to.
     */
     
    MessageProp prop = new MessageProp(0, false);
     /* 
      * Read the token. This uses the same token byte array 
      * as that used during context establishment.
      */
    token = new byte[inStream.readInt()];
        System.out.println("Will read token of size " 
             + token.length);
        inStream.readFully(token);
        byte[] bytes = context.unwrap(token, 0, token.length, prop);
        String str = new String(bytes);
        System.out.println("Received data ""
            + str + "" of length " + str.length());
        System.out.println("Encryption applied: "
            + prop.getPrivacy());

JGSS API example programs

The JGSS installation includes sample programs. This section demonstrates how to run the client and server programs using JGSS for secure message exchange.

Before running the programs, you should have access to a Kerberos environment. However, installing and configuring Kerberos is not something for the fainthearted, so get some help if you need it.

Start kdc on the network. Start the server program. The server waits in a loop for connections. The following output illustrates the remaining steps through the program:

C:rags>java -Djava.security.krb5.realm=JILEBI.SUN.COM -Djava.security.krb5.kdc=jujub -Djavax.security.auth.useSubjectCredsOnly=false -Djava.security.auth.login.config=bcsLogin.conf  SampleServer 9696
Waiting for incoming connection...
Got connection from client /24.128.136.197
Will read input token of size 490 for processing by acceptSecContext
Kerberos username [rags]: raghavan
Kerberos password for raghavan:
Will send token of size 106 from acceptSecContext.
Context Established! Client is [email protected]
Server is [email protected]
Mutual authentication took place!
Will read token of size 61
Received data "Hello There! " of length 13
Confidentiality applied: true
Will send MIC token of size 37
Closing connection with client /24.128.136.197
Waiting for incoming connection...

Now run the client program. The output below illustrates the steps through the program:

C:rags>java -Djava.security.krb5.realm=JILEBI.SUN.COM -Djava.security.krb5.kdc=jujub -Djavax.security.auth.useSubjectCredsOnly=false -Djava.security.auth.login.config=bcsLogin.conf  SampleClient raghavan anvil 9696
Connected to server anvil/24.128.136.197
Kerberos username [rags]: raghavan
Kerberos password for raghavan:
Will send token of size 490 from initSecContext.
Will read input token of size 106 for processing by initSecContext
Context Established!
Client is [email protected]
Server is raghavan
Mutual authentication took place!
Will send wrap token of size 61
Will read token of size 37
Verified received MIC for message.
Exiting...

The client and server programs establish a connection, mutually authenticate, and exchange a message with confidentiality assured.

JGSS and JSSE

You may wonder how the JGSS approach differs from the JSSE approach, which can also mutually authenticate the client and server and securely exchange messages. A cursory examination of the commands used to run the example programs show that the JGSS sample programs don’t use the truststore. Instead, the mutual authentication proceeds with Kerberos. The other differences between the two are documented in the JGSS documentation and summarized in the table below.

Comparison of JGSS and JSSE. (Condensed from Sun Microsystems’s “When to Use Java GSS-API vs. JSSE.”)

Aspect JGSS JSSE
Protocol requirements Kerberos version 5 SSL/TLS
Kerberos single sign-on support Available using a separate Kerberos installation No support in SSL/TLS
Communications API Token based — dependent on applications such as TCP, UDP, etc. Socket based
Credential delegation Possible; suitable for intermediaries Not possible using the API
Selective encryption Possible; suitable for this requirement Unsuitable for this requirement

Security is everyone’s business

In this article, we looked primarily at the new features of J2SE 1.4 security. Java security has continually evolved by enhancing the flexibility of a secure environment. The movement of the optional packages into the core and the two new packages I discussed make it easier to incorporate a variety of security solutions in a portable fashion.

Throughout this series I’ve strived to offer simple examples to drive home the concepts. I leave it as an exercise to you to build more complex and realistic solutions. I hope those who wish to build more complex solutions will benefit from a knowledge of these simple examples and concepts.

Raghavan N. Srinivas is a
Java technology evangelist at Sun Microsystems who specializes in
Java and distributed systems. He is a proponent of Java technology
and teaches graduate and undergraduate classes in the evening.
Srinivas holds a master’s degree in computer science from the
Center of Advanced Computer Studies at the University of
Southwestern Louisiana. He likes hiking, running, and traveling,
but most of all loves to eat, especially spicy food.

Source: www.infoworld.com