/** * Copyright 2006 by Know-Center, Graz, Austria * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a * joint initiative of the Federal Chancellery Austria and Graz University of * Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. * * $Id: X509Cert.java,v 1.4 2006/08/25 17:09:41 wprinz Exp $ */ package at.knowcenter.wag.egov.egiz.sig; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.Serializable; import java.security.PublicKey; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.List; import org.apache.log4j.Logger; import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger; import at.knowcenter.wag.egov.egiz.tools.CodingHelper; import at.knowcenter.wag.egov.egiz.tools.FileHelper; public class X509Cert implements Serializable { /** * SVUID. */ private static final long serialVersionUID = 6945327015386694557L; /** * The x509 certificate binary string Base64 coded */ private String certString_ = null; /** * The name value of the issuer */ private String issuerName_ = null; /** * The serial number of the certificate */ private String serialNumber_ = null; /** * The digest value of the certificate */ private String certDigest_ = null; /** * The name value of the subject */ private String subjectName_ = null; /** * The X509Certificate object */ private X509Certificate x509Cert_ = null; /** * The logger definition. */ private static final Logger logger_ = ConfigLogger.getLogger(X509Cert.class); /** * The empty constructor not acessible from outside --> use the static init * methods instead */ private X509Cert() { } /** * Normalize the base64 coded .cer or .der string. Remove the begin and end * statement and remove all whitespaces in the string. The result string * (base64) is used by reconstructing the certiface sign by the verification * process. * * @param certString * the string to normalize * @return the normalized cert string */ private static String normalizeCertString(String certString) { certString = certString.replaceAll("-----BEGIN CERTIFICATE-----", ""); certString = certString.replaceAll("-----END CERTIFICATE-----", ""); certString = certString.replaceAll("\\s", ""); return certString; } /** * This method initialzes a X509Certificate by a string value. It must be * coded Base64 or as plain binary stream. * * @param certString * the certificate string to analyse * @return the X509Cert object * @see CertificateFactory * @see X509Certificate */ public static X509Cert initByString(String certString) { if (certString == null) { return null; } certString = normalizeCertString(certString); X509Cert x509_cert = new X509Cert(); x509_cert.setCertString(certString); try { byte[] b64_dec = certString.getBytes("US-ASCII"); if (CodingHelper.isB64(b64_dec)) { b64_dec = CodingHelper.decodeBase64(b64_dec); } else { b64_dec = CodingHelper.encodeBase64(b64_dec).getBytes("US-ASCII"); } ByteArrayInputStream bais = new ByteArrayInputStream(b64_dec); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(bais); bais.close(); x509_cert.setX509Cert(cert); String serial_num = cert.getSerialNumber().toString(); String issuer = cert.getIssuerDN().getName(); issuer = issuer.replaceAll(", ", ","); String subject_name = cert.getSubjectDN().toString(); x509_cert.setSerialNumber(serial_num); x509_cert.setIssuerName(issuer); x509_cert.setSubjectName(subject_name); if (logger_.isDebugEnabled()) { logger_.debug("Serial number from certificate:" + serial_num); logger_.debug("Issuer name from certificate :" + issuer); logger_.debug("Subject name from certificate :" + subject_name); } } catch (java.security.cert.CertificateException ce) { // nothing to do, cause certString is not X509 conformc logger_.error(ce.getMessage(), ce); } catch (IOException ioe) { // nothing to do, cause certString is not X509 conform logger_.error(ioe.getMessage(), ioe); } return x509_cert; } public static X509Cert initByX509Certificate(X509Certificate cert) throws CertificateEncodingException { X509Cert x509_cert = new X509Cert(); x509_cert.setX509Cert(cert); x509_cert.setCertString(CodingHelper.encodeBase64(cert.getEncoded())); String serial_num = cert.getSerialNumber().toString(); String issuer = cert.getIssuerDN().getName(); issuer = issuer.replaceAll(", ", ","); String subject_name = cert.getSubjectDN().toString(); x509_cert.setSerialNumber(serial_num); x509_cert.setIssuerName(issuer); x509_cert.setSubjectName(subject_name); if (logger_.isDebugEnabled()) { logger_.debug("Serial number from certificate:" + serial_num); logger_.debug("Issuer name from certificate :" + issuer); logger_.debug("Subject name from certificate :" + subject_name); } return x509_cert; } public static X509Cert initByByteArray(byte[] data) { X509Cert x509_cert = new X509Cert(); try { ByteArrayInputStream bais = new ByteArrayInputStream(data); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(bais); bais.close(); x509_cert.setX509Cert(cert); String serial_num = cert.getSerialNumber().toString(); String issuer = cert.getIssuerDN().getName(); issuer = issuer.replaceAll(", ", ","); String subject_name = cert.getSubjectDN().toString(); x509_cert.setSerialNumber(serial_num); x509_cert.setIssuerName(issuer); x509_cert.setSubjectName(subject_name); if (logger_.isDebugEnabled()) { logger_.debug("Serial number from certificate:" + serial_num); logger_.debug("Issuer name from certificate :" + issuer); logger_.debug("Subject name from certificate :" + subject_name); } } catch (java.security.cert.CertificateException ce) { // nothing to do, cause certString is not X509 conformc logger_.error(ce.getMessage(), ce); } catch (IOException ioe) { // nothing to do, cause certString is not X509 conform logger_.error(ioe.getMessage(), ioe); } return x509_cert; } /** * This method initialzes a X509Certificate by a file path value. The file * must be a plain binary file like .cer format. * * @param filePath * the certificate file to analyse * @return the X509Cert object * @see CertificateFactory * @see X509Certificate */ public static X509Cert initByFilePath(String filePath) { if (filePath == null) { return null; } X509Cert x509_cert = new X509Cert(); try { FileInputStream fis = new FileInputStream(filePath); X509Certificate cert = null; try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); cert = (X509Certificate) cf.generateCertificate(fis); } catch (java.security.cert.CertificateException ce) { fis.close(); String cert_string = FileHelper.readFromFile(filePath); return initByString(cert_string); } fis.close(); x509_cert.setX509Cert(cert); String cert_string = FileHelper.readFromFile(filePath); x509_cert.setCertString(normalizeCertString(cert_string)); String serial_num = cert.getSerialNumber().toString(); String issuer = cert.getIssuerDN().getName(); issuer = issuer.replaceAll(", ", ","); String subject_name = cert.getSubjectDN().toString(); x509_cert.setSerialNumber(serial_num); x509_cert.setIssuerName(issuer); x509_cert.setSubjectName(subject_name); if (logger_.isDebugEnabled()) { logger_.debug("Serial number from certificate:" + serial_num); logger_.debug("Issuer name from certificate :" + issuer); logger_.debug("Subject name from certificate :" + subject_name); } } catch (IOException ioe) { String cert_string = FileHelper.readFromFile(filePath); return initByString(cert_string); } return x509_cert; } /** * This method initialzes a X509Certificate by a file value. The file must be * a plain binary file like .cer format. * * @param certFile * the certificate file to analyse * @return the X509Cert object * @see CertificateFactory * @see X509Certificate */ public static X509Cert initByFile(File certFile) { return initByFilePath(certFile.getAbsolutePath()); } /** * This method checks if a certificate file is X509 conform. * * @return true if a certificate file is X509 conform, false otherwise */ public boolean isX509Cert() { return x509Cert_ != null; } /** * @return Returns the certificate digest value. * @deprecated Should not be used any more. */ public String getCertDigest() { if (certDigest_ == null) { if (certString_ != null) { byte[] cert_b64 = CodingHelper.decodeBase64(certString_); String sigAlgName = this.x509Cert_.getSigAlgName(); String digestAlg = sigAlgName.split("/")[0]; if (sigAlgName.toLowerCase().indexOf("with") != -1 ) { digestAlg = sigAlgName.substring(0,sigAlgName.toLowerCase().indexOf("with")); } byte[] cert_hash = CodingHelper.buildDigest(cert_b64, digestAlg); certDigest_ = new String(CodingHelper.encodeBase64(cert_hash)); } } return certDigest_; } /** * @return Returns the certificate Base64 binary string. */ public String getCertString() { return certString_; } /** * @return Returns the issuer string. */ public String getIssuerName() { return issuerName_; } /** * @return Returns the serial number. */ public String getSerialNumber() { return serialNumber_; } /** * @return Returns the real X509Certifcate object. * @see X509Certificate */ public X509Certificate getX509Certificate() { return x509Cert_; } /** * @return Returns the subject name. */ public String getSubjectName() { return subjectName_; } // /** // * @param certDigest // * The certDigest to set. // */ // private void setCertDigest(String certDigest) // { // certDigest_ = certDigest; // } /** * @param certString * The certString to set. */ private void setCertString(String certString) { certString_ = certString; } /** * @param issuerString * The issuerString to set. */ private void setIssuerName(String issuerString) { issuerName_ = issuerString; } /** * @param serialNumber * The serialNumber to set. */ private void setSerialNumber(String serialNumber) { serialNumber_ = serialNumber; } /** * @param cert * The x509Cert to set. */ private void setX509Cert(X509Certificate cert) { x509Cert_ = cert; } /** * @param subjectName * The subjectName to set. */ private void setSubjectName(String subjectName) { subjectName_ = subjectName; } public byte[] getTBSCertificate() throws CertificateEncodingException { return x509Cert_.getTBSCertificate(); } public String getSigAlgName() { return x509Cert_.getSigAlgName(); } public String getSigAlgOID() { return x509Cert_.getSigAlgOID(); } public List getExtendedKeyUsage() { List list = null; try { list = x509Cert_.getExtendedKeyUsage(); } catch (CertificateParsingException e) { logger_.error(e.getMessage(), e); } return null; } /** * @return the public key of the X509Certificate */ public PublicKey getPublicKey() { return x509Cert_.getPublicKey(); } /** * This method checks, if a X509Certificate has a public key with the rsa * algorithm. * * @return true if the public key is produced with rsa, false otherwise */ public boolean isRSA() { return (x509Cert_.getPublicKey().getAlgorithm()).indexOf("RSA") >= 0; } }