TOC PREV NEXT INDEX




Step 3 - Adding Support for Client Certificates


Some servers require the client to authenticate itself. These can be, for example, banks on the Web and any others that require authentication from the user. The user must then have a client certificate (also called personal certificate) and a private key that belongs to the public key in the certificate. In this example, a list of certificates is read from a file that contains an X.509 PEM encoded certificate followed by a PEM encoded PKCS#8 private key. Only RSA client certificates are supported.

To be able to use client certificates, the user must have a PEM encoded client certificate, immediately followed by the corresponding PKCS#8 v1.5 private key, which is also PEM encoded. This list of certificates can be loaded with the following code:

//Install the list of client/personal certificates.

    try{

        java.io.InputStream in = new

            FileInputStream(CLIENT_CERTIFICATE_FILE_NAME);

        cm.setClientCertificates(ClientCertificateList.

            restoreListFromPEM(in,null));

         in.close();

     }

     catch(IOException ex){

         System.err.println("Could not load client certificates");

}
 

In addition, the methods selectName( ) and supplyPrivateKey( ) in the certificate handler must be implemented. These are called whenever a request for authentication is received from the server. The selectName( ) gets an array of distinguished names, and is supposed to find a certificate signed by a signer whose name is on the list. The method returns a certificate chain where the first certificate is signed by the selected signer. The supplyPrivateKey( ) gets a certificate as input, and should return a private key corresponding to the certificate. That private key is used to generate a digital signature for proving the identity of the client.

public synchronized X509Certificate[] selectName(X500Name[] names){       

     CertificateManager cm = CertificateManager.getCertificateManager();

     X509Certificate[] certArray = cm.matchIssuers(names);

 

     ClientcertSelector selector = new ClientcertSelector(new Frame());

     X509Certificate cert = selector.selectCert(certArray);

 

     if(cert != null){

         return cm.getClientCertificates().getCertificateChain(cert);

     }

     else{

         return null;

     }

}
 

This code finds all the client certificates signed with one of the names from the server, creates a new instance of the class ClientcertSelector, and starts a dialog asking the user to select a certificate. If the user selects a certificate, the certificate chain that belongs to it is returned.

The supplyPrivateKey asks the certificate manager for the private key.

public synchronized PrivateKey supplyPrivateKey(X509Certificate cert){

     return CertificateManager.getCertificateManager()

         .getClientCertificates().getPrivateKey(cert);

}
 

The clientcertSelector class is a simple AWT dialog, implemented as follows:

class ClientcertSelector extends Dialog implements ActionListener{



private static final int BUFFER = 7;

     

     java.awt.List certlist = null;

     java.awt.Button okButton = null;

     java.awt.Button cancelButton = null;

     java.awt.Button foreverButton = null;

     boolean forever = false;

 

     int certNum = -1;

 

     ClientcertSelector(Frame owner) {

         super(owner);

     this.setModal(true);

     createSelector(owner);

     }

            

     ClientcertSelector(Frame owner, boolean modal) {

         super(owner, modal);

     createSelector(owner);

     }

             

     ClientcertSelector(Frame owner, String title) {

         super(owner, title);

     this.setModal(true);

     createSelector(owner);

     }

            

     ClientcertSelector(Frame owner, String title, boolean modal) {

         super(owner, title, modal);

     createSelector(owner);

     }

     

private void createSelector(Frame owner){

     this.setLayout(new GridLayout(3,1));

     this.add(new Label("Select a cerificate"));

     

     //The certificate list

     certlist = new java.awt.List(10);

     certlist.setMultipleMode(false);

     this.add(certlist);

     

     //the button panel

     Panel buttonPanel = new Panel();

     okButton = new Button("Sign");

     buttonPanel.add(okButton);

     foreverButton = new Button("Always sign");

     buttonPanel.add(foreverButton);

     cancelButton =  new Button("Cancel");

     buttonPanel.add(cancelButton);

     this.add(buttonPanel);

     

     //Add event listeners;

     okButton.addActionListener(this);

     foreverButton.addActionListener(this);

     cancelButton.addActionListener(this);

}

 

public void actionPerformed(ActionEvent ev){

     if(ev.getSource()==okButton){

         certNum = certlist.getSelectedIndex();

     }

     else if(ev.getSource()==foreverButton){

         certNum = certlist.getSelectedIndex();

         forever = true;

     }

     else if(ev.getSource()==cancelButton){

         certNum = -1;

     }

     setVisible(false);

}

 

public boolean useForever(){

     return forever;

}

 

public X509Certificate selectCert(X509Certificate[] certArray){

     //Remove the elements from the current list

     certlist.removeAll();

 

     //insert certificates

     int i = 0;

     for(i=0; i < certArray.length; i++){

         String subject = certArray[i].getSubjectDN().getName();

         String issuer = certArray[i].getIssuerDN().getName();

         certlist.add(subject);

     }

     if(i >= 1) certlist.select(0);

 

     // display the dialog

     pack();

     setSize(300,200);

     setVisible(true);

 

     if(certNum >= 0 && certNum < certArray.length){

         return certArray[certNum];

     }

     else{

         return null;

     }

}

 

     public Insets getInsets() {

         if (super.getInsets().top == 0 && super.getInsets().left == 0) {

             return new Insets(BUFFER, BUFFER, BUFFER, BUFFER);

         } else {

             return super.getInsets();

         }

     }

 

    public void refreshScreen() {

       pack();

       int x = (this.getParent().getSize().width - this.getSize().width) / 5 

       + this.getParent().getLocationOnScreen().x;

       int y = (this.getParent().getSize().height - this.getSize().height)/ 5 

       + this.getParent().getLocationOnScreen().y;     

       setLocation(x, y);

       invalidate();

    }

 }
 


Copyright 2005. ICEsoft Technologies, Inc.
http://www.icesoft.com

TOC PREV NEXT INDEX