/*******************************************************************************
* Copyright (c) 2008, Jay Rosenthal
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Jay Rosenthal - initial API and implementation
*******************************************************************************/
package org.eclipse.buckminster.jnlp.p2.ui.certificates;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.Viewer;
/**
* X509CertificateAttributeContentProvider Structured content provided for an <a
* href="http://java.sun.com/j2se/1.4.2/docs/api/java/security/cert/X509Certificate.html">X509Certificate </a> object.
* <p>
* Currently this only supports the attributes exposed directly by X509Certificate. Some commonly used extensions may
* not be displayed. Contributions and enhancements are welcomed.
*
*/
public class X509CertificateAttributeContentProvider implements IStructuredContentProvider
{
private static String LABEL_KEYUSAGE_DIGITALSIGNATURE = "digitalSignature"; //$NON-NLS-1$
private static String LABEL_KEYUSAGE_NONREPUDIATION = "nonRepudiation"; //$NON-NLS-1$
private static String LABEL_KEYUSAGE_KEYENCIPHERMENT = "keyEncipherment"; //$NON-NLS-1$
private static String LABEL_KEYUSAGE_DATAENCIPHERMENT = "dataEncipherment"; //$NON-NLS-1$
private static String LABEL_KEYUSAGE_KEYAGREEMENT = "keyAgreement"; //$NON-NLS-1$
private static String LABEL_KEYUSAGE_CERTSIGN = "keyCertSign"; //$NON-NLS-1$
private static String LABEL_KEYUSAGE_CRLSIGN = "cRLSign"; //$NON-NLS-1$
private static String LABEL_KEYUSAGE_ENCIPHERONLY = "encipherOnly"; //$NON-NLS-1$
private static String LABEL_KEYUSAGE_DECIPHERONLY = "decipherOnly"; //$NON-NLS-1$
private ArrayList elements = new ArrayList();
private Viewer viewer = null;
private static String listDelim = ", "; //$NON-NLS-1$
private static final DateFormat _df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.FULL);
// TODO - This is a bit ugly but gets the job done... Maybe this should be a class of it's own ??
private static String keyUsageStrings[] = { LABEL_KEYUSAGE_DIGITALSIGNATURE, LABEL_KEYUSAGE_NONREPUDIATION,
LABEL_KEYUSAGE_KEYENCIPHERMENT, LABEL_KEYUSAGE_DATAENCIPHERMENT, LABEL_KEYUSAGE_KEYAGREEMENT,
LABEL_KEYUSAGE_CERTSIGN, LABEL_KEYUSAGE_CRLSIGN, LABEL_KEYUSAGE_ENCIPHERONLY, LABEL_KEYUSAGE_DECIPHERONLY };
public X509CertificateAttributeContentProvider()
{
super();
}
public void clear()
{
clear(true);
}
public void clear(boolean refresh)
{
elements.clear();
if(refresh && viewer != null)
viewer.refresh();
}
public void dispose()
{
// TODO Auto-generated method stub
}
public Object[] getElements(Object inputElement)
{
return elements.toArray();
}
public void inputChanged(Viewer aViewer, Object oldInput, Object newInput)
{
viewer = aViewer;
clear(false); // clear the viewer.
// Be safe ... check the input
if(newInput instanceof X509Certificate)
{
X509Certificate theCert = (X509Certificate)newInput;
X509CertificateAttribute ver = new X509CertificateAttribute("Version",
new Integer(theCert.getVersion()).toString());
elements.add(ver);
X509CertificateAttribute serialNum = new X509CertificateAttribute("Serial Number",
theCert.getSerialNumber().toString());
elements.add(serialNum);
X509CertificateAttribute validFrom = new X509CertificateAttribute("Valid From",
_df.format(theCert.getNotBefore()), theCert.getNotBefore());
elements.add(validFrom);
X509CertificateAttribute validTo = new X509CertificateAttribute("Valid Until",
_df.format(theCert.getNotAfter()), theCert.getNotAfter());
elements.add(validTo);
X509CertificateAttribute issuedBy = new X509CertificateAttribute("Issued by",
theCert.getIssuerX500Principal().getName(), theCert.getIssuerX500Principal());
elements.add(issuedBy);
X509CertificateAttribute IssuedToItem = new X509CertificateAttribute("Issued to",
theCert.getSubjectX500Principal().getName(), theCert.getSubjectX500Principal());
elements.add(IssuedToItem);
X509CertificateAttribute sigAlgoItem = new X509CertificateAttribute("Signature Algorithm",
theCert.getSigAlgName());
elements.add(sigAlgoItem);
boolean keyUsagesArray[] = theCert.getKeyUsage();
StringBuffer keyUsages = new StringBuffer();
//
// Only set the string field, If we got some data
if(keyUsagesArray != null && keyUsagesArray.length > 0)
{
for(int i = 0; i < keyUsagesArray.length; i++)
{
if(keyUsagesArray[i])
keyUsages.append(keyUsageStrings[i] + listDelim);
}
X509CertificateAttribute keyUsage = new X509CertificateAttribute("Key Usage",
(keyUsages.toString()).substring(0, keyUsages.length() - 2), theCert.getKeyUsage());
elements.add(keyUsage);
}
/*
* Thumbprint is not actually "in" the certificate. It is computed on the fly...
*/
X509CertificateAttribute thumbPrintItem = new X509CertificateAttribute(
"Thumbprint", getThumbprint(theCert, "SHA1")); //$NON-NLS-1$
elements.add(thumbPrintItem);
PublicKey pubKey = theCert.getPublicKey();
X509CertificateAttribute pubKeyInfoItem = new X509CertificateAttribute("Public Key Info",
getHex(pubKey.getEncoded()));
elements.add(pubKeyInfoItem);
Collection subAltNamesVctr;
try
{
subAltNamesVctr = theCert.getSubjectAlternativeNames();
// StringBuffer bfrSubAltNames = new StringBuffer();
if(subAltNamesVctr != null && subAltNamesVctr.size() > 0)
{
// TODO - Make alt names into a displayable list...
// For now just display that they exist..
X509CertificateAttribute subAltItem = new X509CertificateAttribute(
"Subject Alternate Names",
"Has Subject Alternate Names" /* bfrSubAltNames.toString() */, theCert.getSubjectAlternativeNames()); //$NON-NLS-1$
elements.add(subAltItem);
}
}
catch(CertificateParsingException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
int basicCnstrnts = theCert.getBasicConstraints();
Integer basicConstraint = new Integer(basicCnstrnts);
StringBuffer basicCnstrntsBfr = new StringBuffer();
if(basicCnstrnts == -1)
{
// Not a CA
basicCnstrntsBfr.append("Not a CA certificate" + listDelim);
}
else
{
basicCnstrntsBfr.append("CA Certificate" + listDelim);
if(basicCnstrnts == Integer.MAX_VALUE)
{
// MAX_VALUE means "no limit to the allowed length of the certification path."
basicCnstrntsBfr.append("CA certificate (max path length = {\"unlimited\"} )" + listDelim);
}
else
{
basicCnstrntsBfr.append("CA certificate (max path length = {" + basicConstraint + "} )" + listDelim);
}
}
X509CertificateAttribute basicConstraints = new X509CertificateAttribute("Basic Constraints",
(basicCnstrntsBfr.toString()).substring(0, basicCnstrntsBfr.length() - 2), basicConstraint);
elements.add(basicConstraints);
List exKeyUsg;
try
{
exKeyUsg = theCert.getExtendedKeyUsage();
StringBuffer exKeyUsgBfr = new StringBuffer();
if(exKeyUsg != null && exKeyUsg.size() > 0)
{
for(Iterator exKeyUsgIter = exKeyUsg.iterator(); exKeyUsgIter.hasNext();)
{
exKeyUsgBfr.append(((String)exKeyUsgIter.next()) + listDelim);
}
X509CertificateAttribute exKeyUsgProp = new X509CertificateAttribute("Extended Key Usage",
(exKeyUsgBfr.toString()).substring(0, exKeyUsgBfr.length() - 2),
theCert.getExtendedKeyUsage());
elements.add(exKeyUsgProp);
}
}
catch(CertificateParsingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void setSelection(X509Certificate curCert)
{
inputChanged(viewer, null, curCert);
if(viewer != null)
viewer.refresh();
}
private MessageDigest getDigest(String thumAlg)
{
MessageDigest md = null;
try
{
md = MessageDigest.getInstance(thumAlg);
}
catch(Exception e)
{
// TODO - Handle the exception or log it..
}
return md;
}
private String getHex(byte buf[])
{
String result = ""; //$NON-NLS-1$
if(buf != null)
{
for(int i = 0; i < buf.length; i++)
{
if(i > 0)
result += " "; //$NON-NLS-1$
short sValue = buf[i];
int curInt = 0;
curInt += sValue;
String converted = Integer.toHexString(curInt);
if(converted.length() > 2)
converted = converted.substring(converted.length() - 2);
result += converted.toUpperCase();
}
}
return result;
}
private String getThumbprint(X509Certificate curCert, String thumAlg)
{
String thumbPrint = ""; //$NON-NLS-1$
try
{
MessageDigest md = getDigest(thumAlg);
md.update(curCert.getEncoded());
byte rawDigest[] = md.digest();
thumbPrint = getHex(rawDigest);
}
catch(Exception e)
{
// Might if thumb print algorithm can not be loaded.
}
return thumbPrint;
}
}