Skip to main content

IBM WebSphere Developer Technical Journal: GT3 and WebSphere compatibility

Enabling the Globus security infrastructure on Web applications using WebSphere Application Server V4 and V5

Vladimir Silva, Software Engineer, Internet Technology, IBM
Vladimir Silva was born in Quito, Ecuador. He received a System's Analyst degree from the Polytechnic Institute of the Army in 1994. In the same year, he came to the United States as an exchange student pursuing a career in Computer Science at Middle Tennessee State University. After graduation, he joined the IBM "Web-Ahead" technology think tank. His interests include Grid computing, Neural Nets, and artificial intelligence. He also holds numerous IT certifications including OCP, MCSD, and MCP. To contact Vladimir, or to obtain the modified versions of puretls.jar and cryptix32.jar described in this article.

Summary:  This article addresses compatibility issues that arise when writing Web-enabled grid applications using IBM's WebSphere Application Server.

Date:  14 Oct 2003
Level:  Introductory
Activity:  270 views

Introduction

Security is at the core of the Globus ToolkitTM. Grid security infrastructure (GSI) enables secure authentication and communication over computer networks. It provides services such as mutual authentication and single sign-on, and is based on proven standards such as public key encryption, X.509 certificates, and the Secure Sockets Layer (SSL).

The purpose of this article is to address compatibility issues that arise when writing Web-enabled grid applications using IBM's WebSphere® Application Server. These issues are related specifically to the Grid security infrastructure JavaTM crypto extensions used by GSI to implement a variety of security services.


Globus Toolkit security libraries

Globus Toolkit 3.0 (GT3) uses a totally new security library provided by the Java CoG Kit 1.1. This new security library is based on GSS-API and is implemented entirely with open-source SSL and certificate processing libraries. When writing Web-enabled Grid applications for the Websphere platform that require the manipulation of X.509 certificates and proxies (also called Globus credentials), conflicts will arise. These conflicts are due to Websphere's use of IBM JCE as the default security provider, whereas GT3 will attempt to use it's own security extensions provided by The Legion of the Bouncy Castle and an SSLv3/TLS implementation, licensed by Claymore Systems.


1. Create proxies from default certificates with WebSphere

We will start by writing a simple JSP page to create a Globus credential, also known as proxy, as shown in Listing 1.


Listing 1. A JSP file to create a Globus credential
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<%@ page 
   language="java"
   contentType="text/html; charset=ISO-8859-1"
   import= "java.util.Properties, 
                   java.io.*, 
                   java.security.cert.*,
                   org.globus.gsi.*, 
                   org.globus.gsi.bc.*,
                   org.apache.log4j.*"
%>
<%!
  public synchronized GlobusCredential gridProxyInit(InputStream inUserCert, InputStream inUserKey , 
                   String pwd, int bits, int hours)
      throws IOException, java.security.GeneralSecurityException
  {
      X509Certificate userCert = CertUtil.loadCertificate(inUserCert);
      OpenSSLKey key           = new BouncyCastleOpenSSLKey(inUserKey); 

      System.out.println("gridProxyInit: User Cert=" + userCert + 
      " User key encrypted=" + key.isEncrypted());

      if (key.isEncrypted()) {
              try {
                   key.decrypt(pwd);
           } catch(java.security.GeneralSecurityException e) {
                   throw new 
                   java.security.GeneralSecurityException("Wrong password or other security error");
           }
      }
      System.out.println("gridProxyInit: User Priv key : " + key.getPrivateKey());

      java.security.PrivateKey userKey = key.getPrivateKey();

      BouncyCastleCertProcessingFactory factory =
                      BouncyCastleCertProcessingFactory.getDefault();

      return factory.createCredential(new X509Certificate[] {userCert},
                      userKey,
                      bits,
                      hours * 3600, GSIConstants.GSI_2_PROXY, null);

   }

%>
<%
   Logger.getRootLogger().setLevel(Level.DEBUG);

   String action   = (request.getParameter("ACTION") != null) 
                            ? request.getParameter("ACTION") : "INIT";
   String pwd      = request.getParameter("txtPWD");
   String bits     = request.getParameter("ST");
   String hours    = request.getParameter("LIFETIME");

   String Msg      = request.getParameter("MSG");

   String subject = "N/A";         // generated proxy subject
   String issuer = "N/A";
   String strength = "N/A";        // proxy strength
   String sTimeLeft = "N/A";       // proxy time left 

   // Used to load certs from db
   boolean proxyReady = false;     // is the proxy ready?

   // Init 
   if ( ! action.equalsIgnoreCase("INIT") ) {
}

   try { 
        if ( action.equalsIgnoreCase("CREATE") ) {

         String path = System.getProperty("user.home") + "/.globus/cog.properties";
         org.globus.common.CoGProperties props = new org.globus.common.CoGProperties();
         props.load(path);

         String certPath = props.getProperty("usercert");
         String keyPath = props.getProperty("userkey");

         System.out.println("test-proxy.jsp::CREATE pwd=" + pwd + " bits=" + bits + " hours=" + hours);
         System.out.println("test-proxy.jsp::Cert path:" + certPath + "\nKey path: " + keyPath);


         // create a globus cred. Certs read from def locs
         InputStream inCert = new FileInputStream(certPath); 
         InputStream inKey = new FileInputStream(keyPath); 

         int stren       = Integer.parseInt(bits);
         int life        = Integer.parseInt(hours);

         // create globus proxy
         GlobusCredential cred = gridProxyInit(inCert , inKey, pwd , stren, life);

         subject                 = cred.getSubject();
         issuer                  = cred.getIssuer();
         strength                = new Integer(cred.getStrength()).toString();
         sTimeLeft               = org.globus.util.Util.formatTimeSec(cred.getTimeLeft()); //

        // save proxy in def location
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        cred.save(bos);
        System.out.println("grid-proxy.jsp::Saving proxy into db\n" + bos.toString());

        proxyReady = true;
        Msg ="Proxy created.";

        }
   }
   catch ( Exception e ) {
           e.printStackTrace();
           response.sendRedirect("test-proxy.jsp?MSG=GridProxyInit+Error:" + e.getMessage());
   }
%>

<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="IBM WebSphere Studio">
<META http-equiv="Content-Style-Type" content="text/css">
<LINK href="../../theme/Master.css" rel="stylesheet" type="text/css">
<TITLE>test-proxy.jsp</TITLE>
<STYLE>
   TABLE, lengend {
           font-family: Verdana, Arial;
           font-size: 12px;
   }
</STYLE>
<SCRIPT LANGUAGE=javascript>
<!--
var proxyReady = <%=proxyReady%>;

function OnLoad() {
   var f = document.F1;
   if ( document.all && proxyReady ) {
           f.btnCreate.disabled = true;
           f.txtPWD.disabled = true;
   }
}

function showMsg(msg){
   window.status = msg;
}

// fires when create btn is pressed
function Proxy_OnSubmit() {
   var action = "test-proxy.jsp?ACTION=CREATE";
   var f = document.F1;

   if ( f.txtPWD.value == "" ) {
           alert("All fields are required");
           f.txtCN.focus();
           return false;
   }

   //alert("action=" + action + "\nSubmit vals. cert=" + cert + " key=" + key);
   showMsg("Working. Please wait...");
   if ( document.all )
           document.F1.btnCreate.disabled = true; // IE only

   document.F1.action = action;
   document.F1.submit(); // submit
}

//-->
</SCRIPT>

</HEAD>
<BODY onload="OnLoad()">

<H1>Grid Proxy Init</H1>
<B>Cetificates will be loaded from default locations</B>

<hr>
<% if ( Msg != null ) { %>
        <br>
        <font color=red><%=Msg%></font>
<% } %>

<FORM method="POST" name="F1" onsubmit="return Proxy_OnSubmit()">
<FIELDSET>
<LEGEND>Proxy Options</LEGEND>
        <TABLE width="100%">
                <tr class="smallfont">
                        <TD class="smallfont">Lifetime</TD>
                        <TD class="smallfont">
                                <INPUT type="radio" name="LIFETIME" value="12" checked="true">12 h   
                                <INPUT type="radio" name="LIFETIME" value="24">24 h   
                                <INPUT type="radio" name="LIFETIME" value="168">1 week   
                                <INPUT type="radio" name="LIFETIME" value="720">1 month
                        </TD>
                </tr>
                <tr class="smallfont">
                        <TD class="smallfont">Strength</TD>
                        <TD class="smallfont">
                                <INPUT type="radio" name="ST" value="512" checked="true">512   
                                <INPUT type="radio" name="ST" value="1024">1024   
                                <INPUT type="radio" name="ST" value="2048">2048   
                                <INPUT type="radio" name="ST" value="4096">4096
                        </TD>
                </tr>

        </TABLE>
</FIELDSET>

        <TABLE width="100%">
                <TR>
                        <td class="smallfont">Pass Phrase</td>
                        <td class="smallfont">
                                <INPUT name="txtPWD" type="password" maxlength="20">
                        </td> 
                </TR>
                <TR>
                        <TD> </TD>
                        <td>
                                <INPUT name="btnCreate" type="submit" value="Create" align="right">
                                  
                        </td>
                </TR>

        </TABLE>

<FIELDSET>
<LEGEND>Proxy Info</LEGEND>
        <TABLE width="100%">
                <TR class="smallfont">
                        <td class="smallfont">CN</td>
                        <td class="smallfont">
                                <font color=red></font>
                        </td> 
                </TR>
                <TR>
                        <td class="smallfont">Subject</td>
                        <td class="smallfont"><%=subject%>
                        </td> 
                </TR>
                <TR>
                        <td class="smallfont">Issuer</td>
                        <td class="smallfont"><%=issuer%>
                        </td> 
                </TR>
                <TR>
                        <td class="smallfont">Time left</td>
                        <td class="smallfont"><%=sTimeLeft%>
                        </td> 
                </TR>
                <TR>
                        <td class="smallfont">Strength</td>
                        <td class="smallfont"><%=strength%>
                        </td> 
                </TR>
        </TABLE>

</FIELDSET>
<br>
</FORM>
</BODY>
</HTML>

To successfully compile this JSP file in WebSphere Studio V5.x, make sure the following JAR files are in your WEB-INF/lib folder:

  • cog-jglobus.jar
  • cryptix-ans1.jar
  • cryptix32.jar
  • jce-jdk13-117.jar
  • jgss.jar
  • log4j-core.jar
  • puretls.jar.

All of the above files are included on the GT3 distribution.


2. Configure local certificates for testing

You must configure local certificates to be used by this JSP file, or even by the Java CoG Kit. The file cog.properties must be present under your home .globus folder. Thus, if your are logged in to your win32 system as "Administrator" then you must create: C:\Documents and Settings\Administrator\.globus\cog.properties.

Sample contents of this file are shown is Listing 2:


Listing 2. cog.properties file
#Tue Aug 26 11:46:58 EDT 2003
usercert=C\:\\Documents and Settings\\Administrator\\.globus\\usercert.pem
userkey=C\:\\Documents and Settings\\Administrator\\.globus\\userkey.pem
proxy=C\:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\x509up_u_vladimir
cacert=C\:\\Documents and Settings\\Administrator\\.globus\\simpleCA\\cacert.pem

The cog.properties file will be setup automatically if you download and install the Java CoG Kit from the Globus Web site. With these pieces in place, the JSP file will look something like Figure 1 in your Web browser.


Figure 1. Proxy init test
Proxy init test

The output of this JSP will look similar to this:


Figure 2. Creating a Globus credential
Creating a Globus credential

So far so good: we have successfully created a Globus proxy from our Web application.


3. Create certificates and private keys

The JSP code in Listing 3 creates a user certificate and private key set.


Listing 3. Create a certificate and private key pair
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<HTML>
<HEAD>
<%@ page 
        language="java"
        contentType="text/html; charset=ISO-8859-1"
        import= "java.util.*, 
                        java.io.*, 
                        java.security.*,
                        java.security.cert.*,
                        org.globus.gsi.*, 
                        org.globus.gsi.bc.*,
                        org.apache.log4j.*,
                        COM.claymoresystems.cert.*,
                        cryptix.util.mime.*"
%>
<%!
        /*
        * Write bytes into a PEM string
        */
        public static String writePEM (byte[] bytes, String hdr, String ftr)
                        throws IOException
        {
                ByteArrayOutputStream bos=new ByteArrayOutputStream();
                Base64OutputStream b64os=new Base64OutputStream(bos);
                b64os.write(bytes);
                b64os.flush();
                b64os.close();

                ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
                InputStreamReader irr=new InputStreamReader(bis);
                BufferedReader r=new BufferedReader(irr);

                StringBuffer buff = new StringBuffer();
                String line;
                buff.append(hdr); 

                while((line=r.readLine())!=null){
                        buff.append(line + "\n");
                }
                buff.append(ftr); 
                return buff.toString();

        }

        /* Create an X509 Name used for cert creation */
        private static X509Name makeCertDN(String subject) throws Exception 
        {
                Vector tdn = new Vector();
                Vector elems = new Vector();
                StringTokenizer st = new StringTokenizer(subject,",");

                for (; st.hasMoreTokens() ;) {
                        String s = st.nextToken(); // [key=value]
                        if ( s.indexOf("=") == -1 ) 
                                throw new Exception("Invalid subject format: " + subject + 
                                " Offending value: " + s);

                        String key = s.substring(0, s.indexOf("=")).trim();
                        String val = s.substring(s.indexOf("=") + 1).trim();

                        if ( val == null || val.equals(""))
                                throw new Exception("Invalid subject format: " + subject + 
                                " Offending value: " + s);

                        String[] temp = {key, val};
                        tdn.addElement(temp);
                }
                // COM.claymoresystems.cert (puretls.jar)
                return CertRequest.makeSimpleDN(tdn);
        }

        /* Cert/key creation */
        public void generateSelfSignedCertAndKey(String subject, int bits, 
                        String Pwd, StringWriter swKey, StringWriter swCert )
        throws NoSuchAlgorithmException, Exception
        {
                X509Name _subject = makeCertDN(subject);
                System.out.println("generateSelfSignedCertAndKey Cert subject: " + 
                _subject.getNameString() + 
                        " Strength=" + bits + " Pwd=" + Pwd); 

                // Generate A Cert RQ
                //StringWriter sw = new StringWriter(); // wil contain the priv key PEM
                BufferedWriter bw = new BufferedWriter(swKey);

                KeyPair kp = CertRequest.generateKey("RSA", bits, Pwd, bw, true); 

                // certs are valid for 1 year: 31536000 secs
                byte[] certBytes = CertRequest.makeSelfSignedCert(kp, _subject, 31536000);


                BufferedWriter bw1 = new BufferedWriter(swCert);
                String _certPEM = writePEM(certBytes,
                                        "-----BEGIN CERTIFICATE-----\n",
                                        "-----END CERTIFICATE-----\n");
                bw1.write(_certPEM);

                System.out.println("CertKeyGenerator: Signed Cert RQ . signedUserCert\n" + _certPEM);

        }

%>

<%
     org.apache.log4j.Logger.getRootLogger().setLevel(org.apache.log4j.Level.DEBUG);

     String action = (request.getParameter("ACTION") != null) ? request.getParameter("ACTION") : "INIT";
     String Msg = request.getParameter("MSG");
     try {
                //Properties args = com.ibm.grid.ogsa.securityextension.gsi.GSIProperties.load();
                String msg = "";

                if ( action.equalsIgnoreCase("GENERATE") ) {
                        String cn       = request.getParameter("txtCN");
                        String org      = request.getParameter("txtORG");
                        String ou       = request.getParameter("txtOU");
                        String pwd      = request.getParameter("txtPWD");

                        String subject = "O=" + org + "," + "OU="+ ou + ",CN=" + cn;
                        System.out.println("Gen certs. Subject: " + subject); 

                        StringWriter swCert        = new StringWriter(); // wil contain cert PEM
                        StringWriter swKey         = new StringWriter(); // wil contain the priv key PEM
                        generateSelfSignedCertAndKey(subject, 1024, pwd, swKey, swCert);

                        // Private key
                        System.out.println("Private key PEM\n" + swKey.toString());
                        // cert
                        System.out.println("Certificate PEM\n" + swCert.toString());

                        response.sendRedirect("test-creds.jsp?MSG=Certs+installed+successfully.");
                }

        }
        catch ( Exception e0 ) {
                e0.printStackTrace();
                response.sendRedirect("test-creds.jsp?MSG=Error+ installing+certs:" + e0.getMessage());

        }
        catch ( InternalError e ) {
                e.printStackTrace();
                response.sendRedirect("test-creds.jsp?MSG=Error+ installing+certs:" + e.getMessage());
        }
%>

<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="IBM WebSphere Studio">
<META http-equiv="Content-Style-Type" content="text/css">
<LINK href="../../theme/Master.css" rel="stylesheet" type="text/css">
<TITLE>setup-gsi.jsp</TITLE>

<SCRIPT LANGUAGE=javascript>
<!--
function showMsg(msg){
        window.status = msg;
}

function OnLoad() {
        document.F1.txtCN.focus();
        showMsg("Done");
}

// fires when create btn is pressed
function OnSubmit() {
        var f = document.F1;

        if ( f.txtCN.value == "" || f.txtPWD.value == "" || f.txtOU.value == "" ) {
                alert("All fields are required");
                f.txtCN.focus();
                return false;
        }

        showMsg("Working. Please wait...");
        if ( document.all )
                document.F1.btnCreate.disabled = true; // IE only

        document.F1.submit(); // submit
}
//-->
</SCRIPT>

</HEAD>
<BODY onload="OnLoad()">

<H1>Setup Certificate/Private key</H1>

<hr>
<% if ( Msg != null ) { %>
        <br><font color=red><%=Msg%></font><br>
<% } %>
        <B>All fileds are required</B>

    <form name="F1" method="POST" action="test-creds.jsp?ACTION=GENERATE" onsubmit="return OnSubmit()">
       <TABLE width="100%" class="smallfont">
               <tr>
                       <td>Common Name</td>
                       <td width="40%">
                               <INPUT type="text" name="txtCN" size="20" maxlength="50">
                       </td>
                       <TD>Enter your name or email</TD>
               </tr>
               <tr>
                       <td>Organizational Unit</td>
                       <td>
                               <INPUT type="text" name="txtOU" size="20" maxlength="50">
                       </td>
                       <TD class="smallfont"></TD>
               </tr>
               <tr>
                       <td>Organization</td>
                       <td>
                               <INPUT type="text" name="txtORG" size="20" maxlength="50">
                       </td>
                       <TD class="smallfont">Organization</TD>
               </tr>
               <tr>
                       <td>Pass phrase</td>
                       <td>
                               <INPUT type="password" name="txtPWD" size="20" maxlength="50">
                       </td>
                       <TD class="smallfont">Password used to encrypt the private key</TD>
               </tr>
       </TABLE>
       <hr>
       <INPUT name="btnCreate" type="submit" name="Submit" value="Install Certs">
    </form>

</BODY>
</HTML>

This code will display like this on your Web browser:


Figure 3. Setting up certificate/private key
Setting up certificate/private key

When attempting to create a certificate/private key, the following exception will be thrown by Websphere:


Listing 4. Exception thrown by security provider collisons between Websphere and GT3
java.lang.InternalError: java.security.NoSuchAlgorithmException: class configured for Cipher:
            com.ibm.crypto.provider.DESedeCipher is not a subclass of xjava.security.Cipher
    at COM.claymoresystems.crypto.PEMData.writePEMObject(PEMData.java:172)
    at COM.claymoresystems.crypto.EAYEncryptedPrivateKey.writePrivateKey(EAYEncryptedPrivateKey.java:83)
    at COM.claymoresystems.cert.CertRequest.generateKey(CertRequest.java:102)
    at jsp.article._test_2D_creds_jsp_0.generateSelfSignedCertAndKey(_test_2D_creds_jsp_0.java:108)
    at jsp.article._test_2D_creds_jsp_0._jspService(_test_2D_creds_jsp_0.java:210)

By taking a closer look at the message:

class configured for Cipher: com.ibm.crypto.provider.DESedeCipher is not a subclass of xjava.security.Cipher;

and the stack trace, we can assume that the internals of the Java CoG APIs are trying to use IBM's JCE as the default provider, which is incorrect, since the security provider should be Cryptix/Bouncy Castle. This problem arises when creating a private key. To fix the problem, the security provider Java code will need to be modified.


4. Change GT3 security providers to work with WebSphere

With the problem identified, the solution consists of a change to a few lines of code of the puretls.jar and cryptix32.jar source code. To do this, you will need to download the source from the Web sites, change the code and repackage the JAR files. The actual code changes that need to be made are listsed in the table below. For information on downloading the source, see the References section.

Table 1: Overview of changes to the GT3 security providers

JAR fileClass/LineOriginalUpdateComments
Puretls.jarPEMData.java
Line 155
Cipher ciph = Cipher.getInstance(algorithm); ((FeedbackCipher)ciph)
.setInitializationVector(iv);
Cipher ciph = Cipher.getInstance(algorithm,"Cryptix");This change will force the use of Cryptix as the security provider
Cryptix32.jarCipher.java
Line 480
cipherName = IJCE.getStandardName (cipherName, "Cipher");cipherName = CryptixProperties.getProperty ("Alg.Alias.Cipher." + cipherName);The method: IJCE. getStandardName Has been deprecated and wrongfully returns the Cipher name under Websphere (For ciphers such as DES-EDE3)

Conclusion

This article provides a useful insight to the GT3 security providers and their compatibility with WebSphere Application Server V4 and V5. If you find yourself writing Web-enabled Grid applications and need to manipulate or create certificates, keys and proxies, the information here will help you resolve incompatibilities you may encounter between the GT3 and Websphere containers.


Resources

About the author

Vladimir Silva was born in Quito, Ecuador. He received a System's Analyst degree from the Polytechnic Institute of the Army in 1994. In the same year, he came to the United States as an exchange student pursuing a career in Computer Science at Middle Tennessee State University. After graduation, he joined the IBM "Web-Ahead" technology think tank. His interests include Grid computing, Neural Nets, and artificial intelligence. He also holds numerous IT certifications including OCP, MCSD, and MCP. To contact Vladimir, or to obtain the modified versions of puretls.jar and cryptix32.jar described in this article.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=13274
ArticleTitle=IBM WebSphere Developer Technical Journal: GT3 and WebSphere compatibility
publish-date=10142003
author1-email=vsilva@us.ibm.com
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers