be.fedict.eidviewer.lib.file.imports.Version35CSVFile.java Source code

Java tutorial

Introduction

Here is the source code for be.fedict.eidviewer.lib.file.imports.Version35CSVFile.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.file.imports;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.codec.binary.Base64;

import be.fedict.eid.applet.service.Address;
import be.fedict.eid.applet.service.DocumentType;
import be.fedict.eid.applet.service.Gender;
import be.fedict.eid.applet.service.Identity;
import be.fedict.eid.applet.service.impl.tlv.DataConvertorException;
import be.fedict.eid.applet.service.impl.tlv.DateOfBirthDataConvertor;
import be.fedict.eidviewer.lib.EidData;
import be.fedict.eidviewer.lib.X509CertificateChainAndTrust;
import be.fedict.eidviewer.lib.X509Utilities;
import be.fedict.eidviewer.lib.file.helper.TextFormatHelper;
import be.fedict.trust.client.TrustServiceDomains;

/**
 *
 * @author Frank Marien
 */
public class Version35CSVFile {
    private static final Logger logger = Logger.getLogger(Version35CSVFile.class.getName());
    private static final int CERTFIELDS = 4;
    private static final int CERT_NAME_OFFSET = 0;
    private static final int CERT_DATA_OFFSET = 2;

    // token numbers of fixed parts
    private static final int DOCUMENTTYPE = 3;
    private static final int FIRSTNAMES = 4;
    private static final int LASTNAME = 5;
    private static final int GENDER = 6;
    private static final int BIRTHDATE = 7;
    private static final int PLACEOFBIRTH = 8;
    private static final int NATIONALITY = 10;
    private static final int NATIONALNUMBER = 11;
    private static final int CARDNUMBER = 16;
    private static final int CARDCHIPNUMBER = 17;
    private static final int CARDVALIDFROM = 18;
    private static final int CARDVALIDUNTIL = 19;
    private static final int CARDISSUINGMUNICIPALITY = 20;
    private static final int STREETANDNUMBER = 22;
    private static final int ZIP = 23;
    private static final int MUNICIPALITY = 24;
    private static final int PHOTO = 30;
    private static final int RRNCERTIFICATE = 53;
    private static final int CERTCOUNT = 55;
    private static final int CERTBASE = 56; // variable number of certs starts here.

    private CertificateFactory certificateFactory = null;
    private Address address = null;
    private Identity identity = null;
    private X509Certificate rootCert = null;
    private X509Certificate citizenCert = null;
    private X509Certificate authenticationCert = null;
    private X509Certificate signingCert = null;
    private X509Certificate rrnCert = null;
    private EidData eidData = null;
    private DateFormat dateFormat = null;
    private byte[] photo = null;
    private int variableCertCount = -1;

    public static void load(File file, EidData eidData) throws CertificateException, IOException {
        Version35CSVFile v35CVSFile = new Version35CSVFile(eidData);
        v35CVSFile.load(file);
    }

    public Version35CSVFile(EidData eidData) {
        this.eidData = eidData;
        dateFormat = new SimpleDateFormat("dd.MM.yyyy");
    }

    public void load(File file) throws CertificateException, FileNotFoundException, IOException {
        logger.fine("Loading Version 35X CSV File");

        String line = null;

        certificateFactory = CertificateFactory.getInstance("X.509");
        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file), "utf-8");
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        line = bufferedReader.readLine();
        if (line != null) {
            String[] tokens = line.split(";");
            for (int tokenNumber = 0; (variableCertCount < 0) && (tokenNumber < tokens.length); tokenNumber++) {
                String token = tokens[tokenNumber];
                logger.log(Level.FINEST, "token #{0} : [{1}]", new Object[] { tokenNumber, token });

                try {

                    switch (tokenNumber) {
                    case DOCUMENTTYPE:
                        identity = new Identity();
                        identity.documentType = DocumentType.toDocumentType(token.getBytes("utf-8"));
                        if (identity.documentType == null)
                            logger.log(Level.SEVERE, "Unknown Document Type \"{0}\"", token);
                        break;

                    case FIRSTNAMES:
                        TextFormatHelper.setFirstNamesFromString(identity, token);
                        break;

                    case LASTNAME:
                        identity.name = token;
                        break;

                    case GENDER:
                        identity.gender = token.equals("M") ? Gender.MALE : Gender.FEMALE;
                        break;

                    case BIRTHDATE: {
                        logger.fine("field BIRTHDATE");
                        DateOfBirthDataConvertor dateOfBirthConvertor = new DateOfBirthDataConvertor();
                        identity.dateOfBirth = dateOfBirthConvertor.convert(token.getBytes("utf-8"));
                    }
                        break;

                    case PLACEOFBIRTH:
                        identity.placeOfBirth = token;
                        break;

                    case NATIONALITY:
                        identity.nationality = token;
                        break;

                    case NATIONALNUMBER:
                        identity.nationalNumber = token;
                        break;

                    case CARDNUMBER:
                        identity.cardNumber = token;
                        break;

                    case CARDCHIPNUMBER:
                        identity.chipNumber = token;
                        break;

                    case CARDVALIDFROM: {
                        GregorianCalendar validityBeginCalendar = new GregorianCalendar();
                        try {
                            validityBeginCalendar.setTime(dateFormat.parse(token));
                            identity.cardValidityDateBegin = validityBeginCalendar;
                        } catch (ParseException ex) {
                            logger.log(Level.SEVERE, "Failed to parse Card Validity Start Date \"" + token + "\"",
                                    ex);
                        }
                    }
                        break;

                    case CARDVALIDUNTIL:
                        GregorianCalendar validityEndCalendar = new GregorianCalendar();
                        try {
                            validityEndCalendar.setTime(dateFormat.parse(token));
                            identity.cardValidityDateEnd = validityEndCalendar;
                        } catch (ParseException ex) {
                            logger.log(Level.SEVERE, "Failed to parse Card Validity End Date \"" + token + "\"",
                                    ex);
                        }
                        break;

                    case CARDISSUINGMUNICIPALITY:
                        identity.cardDeliveryMunicipality = token;
                        break;

                    case STREETANDNUMBER:
                        address = new Address();
                        address.streetAndNumber = token;
                        break;

                    case ZIP:
                        address.zip = token;
                        break;

                    case MUNICIPALITY:
                        address.municipality = token;
                        break;

                    case PHOTO:
                        byte[] tokenBytes = token.getBytes();
                        eidData.setPhoto(Base64.decodeBase64(tokenBytes));
                        break;

                    case RRNCERTIFICATE:
                        logger.finer("Gathering RRN Certificate");
                        try {
                            rrnCert = (X509Certificate) certificateFactory.generateCertificate(
                                    new ByteArrayInputStream(Base64.decodeBase64(token.getBytes())));
                        } catch (CertificateException ex) {
                            logger.log(Level.SEVERE, "Failed to RRN Certificate", ex);
                        }
                        break;

                    case CERTCOUNT:
                        logger.finer("Certificate Count: [" + token + "]");
                        variableCertCount = Integer.parseInt(token);
                        break;
                    }
                } catch (UnsupportedEncodingException ex) {
                    logger.log(Level.SEVERE, "Unsupported Encoding for Token " + tokenNumber, ex);
                } catch (DataConvertorException ex) {
                    logger.log(Level.SEVERE,
                            "Couldn't Convert Date \"" + tokens[tokenNumber] + "\" in Token " + tokenNumber, ex);
                }
            } // done looping over fixed parts..

            if (identity != null) {
                TextFormatHelper.setFirstNamesFromStrings(identity, identity.getFirstName(),
                        identity.getMiddleName());
                eidData.setIdentity(identity);
            }

            if (address != null)
                eidData.setAddress(address);

            // get variableCertCount variable certs
            for (int i = 0; i < variableCertCount; i++) {
                X509Certificate thisCertificate = null;
                int certOffset = CERTBASE + (CERTFIELDS * i);
                String certType = tokens[certOffset + CERT_NAME_OFFSET];
                String certData = tokens[certOffset + CERT_DATA_OFFSET];

                logger.finer("Gathering " + certType + " Certificate");

                try {
                    thisCertificate = (X509Certificate) certificateFactory.generateCertificate(
                            new ByteArrayInputStream(Base64.decodeBase64(certData.getBytes())));
                } catch (CertificateException ex) {
                    logger.log(Level.SEVERE, "Failed to Convert Signing Certificate", ex);
                    thisCertificate = null;
                }

                if (thisCertificate != null) {
                    if (certType.equalsIgnoreCase("Authentication"))
                        authenticationCert = thisCertificate;
                    else if (certType.equalsIgnoreCase("Signature"))
                        signingCert = thisCertificate;
                    else if (certType.equalsIgnoreCase("CA"))
                        citizenCert = thisCertificate;
                    else if (certType.equalsIgnoreCase("Root"))
                        rootCert = thisCertificate;
                }
            }

        }

        if (rootCert != null && citizenCert != null) {
            logger.fine("Certificates were gathered");

            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));
            }

            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));
            }
        }
        inputStreamReader.close();
    }

    public void fromIdentityAddressPhotoAndCertificates(Identity identity, Address address, byte[] photo,
            X509Certificate authCert, X509Certificate signCert, X509Certificate citizenCert,
            X509Certificate rrnCert, X509Certificate rootCert) throws Exception {
        this.identity = identity;
        this.address = address;
        this.photo = photo;
        this.authenticationCert = authCert;
        this.signingCert = signCert;
        this.rrnCert = rrnCert;
        this.citizenCert = citizenCert;
        this.rootCert = rootCert;
    }

    public static void X509CertToCSV(X509Certificate certificate, String label, OutputStreamWriter writer)
            throws Exception {
        writer.write(String.format("%s;1;%s;;", label, X509Utilities.eidBase64Encode(certificate.getEncoded())));
    }

    public static void toCSV(Version35CSVFile v35File, OutputStream outputStream) throws Exception {
        /* version;type;name;surname;gender;date_of_birth;location_of_birth;nobility;nationality;
        national_nr;special_organization;member_of_family;special_status;logical_nr;chip_nr;
        date_begin;date_end;issuing_municipality;version;street;zip;municipality;country;
        file_id;file_id_sign;file_address;file_address_sign; */

        /* picturedata;picturehash */

        /*
        serial_nr;component_code;os_nr;os_version;softmask_nr;softmask_version;applet_version;
        global_os_version;applet_interface_version;PKCS1_support;key_exchange_version;
        application_lifecycle;graph_perso;elec_perso;elec_perso_interface;
        */

        /* challenge, response */

        /*
         * RRN Cert
         */

        /*
        certificatescount;certificate1;certificate2;...
        */

        /*
         * PIN codes
         */

        DateFormat dottyDate = new SimpleDateFormat("dd.MM.yyyy");

        OutputStreamWriter writer = new OutputStreamWriter(outputStream);

        logger.finest(TextFormatHelper.dateToRRNDate(v35File.identity.dateOfBirth.getTime()).toUpperCase());

        // write all fixed pos data
        writer.write(String.format(
                "1;eid;;%02d;%s;%s;%c;%s;%s;%s;%s;%s;%s;%s;%s;%1d;%s;%s;%s;%s;%s;;%s;%s;%s;be;;;;;%s;;;;;;;;;;;;;;;;;;;;;RRN;1;%s;;",
                v35File.identity.documentType.getKey(), v35File.identity.firstName, v35File.identity.name,
                (v35File.identity.gender == Gender.FEMALE ? 'F' : 'M'),
                TextFormatHelper.dateToRRNDate(v35File.identity.dateOfBirth.getTime()).toUpperCase(),
                v35File.identity.placeOfBirth,
                (v35File.identity.nobleCondition != null ? v35File.identity.nobleCondition : ""),
                v35File.identity.nationality, v35File.identity.nationalNumber,
                (v35File.identity.duplicate != null ? v35File.identity.duplicate : ""),
                (v35File.identity.specialOrganisation != null ? v35File.identity.specialOrganisation : ""),
                (v35File.identity.memberOfFamily ? "1" : ""),
                (v35File.identity.specialStatus != null ? v35File.identity.specialStatus.ordinal() : 0),
                // logicalNumber
                v35File.identity.cardNumber, v35File.identity.chipNumber,
                dottyDate.format(v35File.identity.cardValidityDateBegin.getTime()),
                dottyDate.format(v35File.identity.cardValidityDateEnd.getTime()),
                v35File.identity.cardDeliveryMunicipality,
                // version
                v35File.address.streetAndNumber, v35File.address.zip, v35File.address.municipality,
                // file_id
                // file_id_sign
                // file_address
                // file_address_sign
                X509Utilities.eidBase64Encode(v35File.photo),
                // picturehash
                // serial_nr
                // component_code
                // os_nr
                // os_version
                // softmask_nr
                // softmask_version
                // applet_version
                // global_os_version
                // applet_interface_version
                // PKCS1_support
                // key_exchange_version
                // application_lifecycle
                // graph_perso
                // elec_perso
                // elec_perso_interface
                // challenge
                // response
                X509Utilities.eidBase64Encode(v35File.rrnCert.getEncoded())));

        // write variable number of certificates
        int ncerts = 0;
        if (v35File.authenticationCert != null)
            ncerts++;
        if (v35File.signingCert != null)
            ncerts++;
        if (v35File.citizenCert != null)
            ncerts++;
        if (v35File.rootCert != null)
            ncerts++;
        writer.write(String.format("%d;", ncerts));
        if (v35File.authenticationCert != null)
            X509CertToCSV(v35File.authenticationCert, "Authentication", writer);
        if (v35File.signingCert != null)
            X509CertToCSV(v35File.signingCert, "Signature", writer);
        if (v35File.citizenCert != null)
            X509CertToCSV(v35File.citizenCert, "CA", writer);
        if (v35File.rootCert != null)
            X509CertToCSV(v35File.rootCert, "Root", writer);

        // write variable number of pin codes..
        writer.write("0"); // zero PIN codes in this file
        writer.flush();
        writer.close();

    }
}