be.fedict.eidviewer.lib.X509Utilities.java Source code

Java tutorial

Introduction

Here is the source code for be.fedict.eidviewer.lib.X509Utilities.java

Source

/*
 * eID Middleware Project.
 * Copyright (C) 2010-2013 FedICT.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, see
 * http://www.gnu.org/licenses/.
 */

package be.fedict.eidviewer.lib;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.security.Signature;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.logging.Logger;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.openssl.PEMWriter;

import be.fedict.trust.client.TrustServiceDomains;

/**
 *
 * @author Frank Marien
 */
public class X509Utilities {
    private static final Logger logger = Logger.getLogger(X509Utilities.class.getName());
    private static final int CONSTRAINT_DIGITALSIGNATURE = 0;
    private static final int CONSTRAINT_NONREPUDIATION = 1;
    private static final List<String> keyUsageStringNames;

    static {
        keyUsageStringNames = new ArrayList<String>(9);
        keyUsageStringNames.add("constraint_digitalSignature");
        keyUsageStringNames.add("constraint_nonRepudiation");
        keyUsageStringNames.add("constraint_keyEncipherment");
        keyUsageStringNames.add("constraint_dataEncipherment");
        keyUsageStringNames.add("constraint_keyAgreement");
        keyUsageStringNames.add("constraint_keyCertSign");
        keyUsageStringNames.add("constraint_cRLSignKey");
        keyUsageStringNames.add("constraint_encipherOnly");
        keyUsageStringNames.add("constraint_decipherOnly");
    }

    public static boolean isSelfSigned(X509Certificate certificate) {
        return certificate.getIssuerDN().equals(certificate.getSubjectDN());
    }

    public static boolean isCertificateAuthority(X509Certificate certificate) {
        return (certificate.getBasicConstraints() != -1) && isSelfSigned(certificate);
    }

    public static String getCN(X509Certificate certificate) {
        String[] dn = certificate.getSubjectDN().getName().split("\\s*,\\s*");
        for (String dnPart : dn) {
            String[] labelValue = dnPart.trim().split("=");
            if (labelValue.length == 2 && labelValue[0].equalsIgnoreCase("CN"))
                return labelValue[1].trim();
        }
        return null;
    }

    public static String getHumanReadableName(X509Certificate certificate) {
        String commonName = getCN(certificate);
        ResourceBundle bundle = ResourceBundle.getBundle("be/fedict/eidviewer/lib/resources/X509Utilities");
        if (bundle != null) {
            try {
                return bundle.getString(commonName);
            } catch (MissingResourceException mre) {
                // intentionally empty ; will return commonName below
            }
        }

        return commonName;
    }

    public static List<String> getKeyUsageStrings(ResourceBundle bundle, boolean[] keyUsage) {
        List<String> uses = new ArrayList<String>(9);
        for (int i = 0; i < keyUsage.length; i++)
            if (keyUsage[i])
                uses.add(bundle.getString(keyUsageStringNames.get(i)));
        return uses;
    }

    public static boolean hasDigitalSignatureConstraint(X509Certificate certificate) {
        return certificate.getKeyUsage()[CONSTRAINT_DIGITALSIGNATURE];
    }

    public static boolean hasNonRepudiationConstraint(X509Certificate certificate) {
        return certificate.getKeyUsage()[CONSTRAINT_NONREPUDIATION];
    }

    public static void setCertificateChainsFromCertificates(EidData eidData, X509Certificate rootCert,
            X509Certificate citizenCert, X509Certificate authenticationCert, X509Certificate signingCert,
            X509Certificate rrnCert) {
        if (rootCert != null && citizenCert != null) {
            if (authenticationCert != null) {
                logger.fine("Setting Authentication Certificate Chain");
                List<X509Certificate> authChain = new LinkedList<X509Certificate>();
                authChain.add(authenticationCert);
                authChain.add(citizenCert);
                authChain.add(rootCert);
                eidData.setAuthCertChain(new X509CertificateChainAndTrust(
                        TrustServiceDomains.BELGIAN_EID_AUTH_TRUST_DOMAIN, authChain));
            }

            if (signingCert != null) {
                logger.fine("Setting Signing Certificate Chain");
                List<X509Certificate> signChain = new LinkedList<X509Certificate>();
                signChain.add(signingCert);
                signChain.add(citizenCert);
                signChain.add(rootCert);
                eidData.setSignCertChain(new X509CertificateChainAndTrust(
                        TrustServiceDomains.BELGIAN_EID_NON_REPUDIATION_TRUST_DOMAIN, signChain));
            }

            if (rrnCert != null) {
                logger.fine("Setting RRN Certificate Chain");
                List<X509Certificate> rrnChain = new LinkedList<X509Certificate>();
                rrnChain.add(rrnCert);
                rrnChain.add(rootCert);
                eidData.setRRNCertChain(new X509CertificateChainAndTrust(
                        TrustServiceDomains.BELGIAN_EID_NATIONAL_REGISTRY_TRUST_DOMAIN, rrnChain));
            }
        }
    }

    // TODO, there are now cards with SHA2?
    public static boolean isValidSignature(X509Certificate certificate, byte[] data, byte[] data2,
            byte[] signature) {
        try {
            Signature verifier = Signature.getInstance("SHA1withRSA");
            verifier.initVerify(certificate);
            verifier.update(data);
            if (data2 != null)
                verifier.update(data2);
            return verifier.verify(signature);
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean isValidSignature(X509Certificate certificate, byte[] data, byte[] signature) {
        return isValidSignature(certificate, data, null, signature);
    }

    public static void certificateToDERFile(X509Certificate certificate, File file)
            throws CertificateEncodingException, IOException {
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            outputStream.write(certificate.getEncoded());
        } finally {
            if (outputStream != null)
                outputStream.close();
        }
    }

    public static void certificateToPEMFile(X509Certificate certificate, File file)
            throws CertificateEncodingException, IOException {
        PEMWriter pemWriter = null;
        try {
            pemWriter = new PEMWriter(new OutputStreamWriter(new FileOutputStream(file)));
            pemWriter.writeObject(certificate);
        } finally {
            if (pemWriter != null)
                pemWriter.close();
        }
    }

    public static void certificateChainToPEMFile(List<X509Certificate> certificates, File file) throws IOException {
        PEMWriter pemWriter = null;
        try {
            pemWriter = new PEMWriter(new OutputStreamWriter(new FileOutputStream(file)));
            for (X509Certificate certificate : certificates)
                pemWriter.writeObject(certificate);
        } finally {
            if (pemWriter != null)
                pemWriter.close();
        }
    }

    public static String eidBase64Encode(byte[] data) {
        Base64 encoder = new Base64(60, new byte[] { ' ' }, false);
        return new String(encoder.encode(data)).trim();
    }

    public static String X509CertToBase64String(X509Certificate certificate) {
        if (certificate == null)
            return null;

        try {
            return eidBase64Encode(certificate.getEncoded());
        } catch (CertificateEncodingException e) {
            return null;
        }
    }

}