org.sinekartads.applet.SignApplet.java Source code

Java tutorial

Introduction

Here is the source code for org.sinekartads.applet.SignApplet.java

Source

/*
 * Copyright (C) 2014 - 2015 Jenia Software.
 *
 * This file is part of Sinekarta-ds
 *
 * Sinekarta-ds is Open SOurce Software: you can redistribute it and/or modify
 * it under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sinekartads.applet;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.sinekartads.exception.InvalidCertificateException;
import org.sinekartads.exception.InvalidPKCS11DriverException;
import org.sinekartads.exception.InvalidPinException;
import org.sinekartads.exception.InvalidSmartCardException;
import org.sinekartads.exception.PKCS11DriverNotFoundException;
import org.sinekartads.exception.PinLockedException;
import org.sinekartads.exception.SmartCardAccessException;
import org.sinekartads.exception.SmartCardReaderNotFoundException;
import org.sinekartads.smartcard.DigitalSignatureClient;
import org.sinekartads.utils.JSONUtils;
import org.sinekartads.utils.X509Utils;

public class SignApplet extends BaseApplet {

    private static final String FUNCTION_SIGN_DIGEST = "signDigest";
    private static final String FUNCTION_SELECT_CERTIFICATE = "selectCertificate";
    private static final String FUNCTION_LOGIN = "login";
    private static final String FUNCTION_SELECT_DRIVER = "selectDriver";

    private static final long serialVersionUID = -2886113966359858032L;

    private static final Logger tracer = Logger.getLogger(SignApplet.class);

    private transient DigitalSignatureClient digitalSignatureClient;

    @Override
    public void init() {
        tracer.info("Initializing the signing applet.");
        super.init();
    }

    @Override
    public void destroy() {
        if (digitalSignatureClient != null) {
            try {
                digitalSignatureClient.close();
            } catch (SmartCardAccessException e) {
                // nothing to do..
            }
        }
        super.destroy();
        tracer.info("signing applet destroyed");
    }

    @Override
    public void stop() {
        tracer.info("stop requested");
        if (digitalSignatureClient != null) {
            try {
                digitalSignatureClient.close();
            } catch (SmartCardAccessException e) {
                // nothing to do..
            }
        }
        super.stop();
        tracer.info("stop done");
    }

    @Override
    public String execFunction(String function, String param) {
        if (function.equals(FUNCTION_SELECT_DRIVER)) {
            return selectDriver(param);
        } else if (function.equals(FUNCTION_LOGIN)) {
            return login(param);
        } else if (function.equals(FUNCTION_SELECT_CERTIFICATE)) {
            return selectCertificate(param);
        } else if (function.equals(FUNCTION_SIGN_DIGEST)) {
            return signDigest(param);
        }
        return null;
    }

    public String selectDriver(String param) {

        AppletRequestDTO request = JSONUtils.deserializeJSON(AppletRequestDTO.class, param);

        String driver = StringUtils.trim(request.getDriver());
        if (digitalSignatureClient == null) {
            digitalSignatureClient = new DigitalSignatureClient();
        } else {
            try {
                digitalSignatureClient.close();
            } catch (SmartCardAccessException e) {
                // nothing to do..
            }
        }

        tracer.info(FUNCTION_SELECT_DRIVER);
        tracer.info(String.format("driver: %s", driver));

        AppletResponseDTO resp = new AppletResponseDTO(FUNCTION_SELECT_DRIVER);
        try {
            digitalSignatureClient.setDriver(driver);
            digitalSignatureClient.open();
            digitalSignatureClient.verifyDriver();
            resp.setResult(digitalSignatureClient.getDriver());
        } catch (SmartCardReaderNotFoundException e) {
            tracer.error("Impossibile trovare il lettore di SmartCard", e);
            resp.addActionError("Impossibile trovare il lettore di SmartCard - " + e.getMessage(), e);
        } catch (InvalidSmartCardException e) {
            tracer.error(e.getMessage(), e);
            resp.addActionError("SmartCard non riconosciuta - " + e.getMessage(), e);
        } catch (PKCS11DriverNotFoundException e) {
            tracer.error(e.getMessage(), e);
            resp.addFieldError("scDriver", "Driver SmartCard non trovato - " + e.getMessage());
        } catch (InvalidPKCS11DriverException e) {
            tracer.error(e.getMessage(), e);
            resp.addFieldError("scDriver", "Driver SmartCard non riconosciuto - " + e.getMessage());
        } catch (SmartCardAccessException e) {
            tracer.error(e.getMessage(), e);
            resp.addActionError("Error SmartCard - " + e.getMessage(), e);
        } catch (Throwable e) {
            tracer.error(e.getMessage(), e);
            resp.addActionError("Exception SmartCard - " + e.getMessage(), e);
        }

        tracer.info(String.format("respJSON: %s", JSONUtils.serializeJSON(resp)));
        return JSONUtils.serializeJSON(resp);
    }

    public String login(String param) {

        AppletRequestDTO request = JSONUtils.deserializeJSON(AppletRequestDTO.class, param);

        String pin = StringUtils.trim(request.getPin());
        tracer.info(FUNCTION_LOGIN);
        tracer.info(String.format("pin:    %s", pin));

        if (digitalSignatureClient.isEmptyDriver()) {
            String selectDriverResp = selectDriver(param);
            AppletResponseDTO respSelectDriver = JSONUtils.deserializeJSON(AppletResponseDTO.class,
                    selectDriverResp);
            if (respSelectDriver.checkError()) {
                return JSONUtils.serializeJSON(respSelectDriver);
            }
        }

        AppletResponseDTO resp = new AppletResponseDTO(FUNCTION_LOGIN);
        try {
            if (digitalSignatureClient != null && StringUtils.isNotBlank(request.getDriver())) {
                digitalSignatureClient.setPin(pin);
                String[] aliases = digitalSignatureClient.certificateList();
                if (ArrayUtils.isNotEmpty(aliases)) {
                    String aliasesJSON = JSONUtils.serializeJSON(aliases);
                    resp.setResult(aliasesJSON);
                }
            } else {
                tracer.error("Specificare un driver smartcard");
                resp.addFieldError("scDriver", "campo obbligatorio");
            }
        } catch (InvalidPinException e) {
            tracer.error("pin non riconosciuto", e);
            resp.addFieldError("scPin", "pin non riconosciuto");
        } catch (PinLockedException e) {
            tracer.error("pin bloccato", e);
            resp.addFieldError("scPin", "pin bloccato");
        } catch (SmartCardReaderNotFoundException e) {
            tracer.error("lettore SmartCard non trovato", e);
            resp.addFieldError("scPin", "lettore SmartCard non trovato");
        } catch (Throwable e) {
            tracer.error("login fallito a causa di un errore interno", e);
            resp.addFieldError("scPin", "login fallito a causa di un errore interno");
        }

        tracer.info(String.format("respJSON: %s", JSONUtils.serializeJSON(resp)));
        return JSONUtils.serializeJSON(resp);
    }

    public String selectCertificate(String param) {

        AppletRequestDTO request = JSONUtils.deserializeJSON(AppletRequestDTO.class, param);

        String alias = StringUtils.trim(request.getAlias());
        tracer.info(FUNCTION_SELECT_CERTIFICATE);
        tracer.info(String.format("alias:  %s", alias));

        if (digitalSignatureClient.isEmptyDriver()) {
            String selectDriverResp = selectDriver(param);
            AppletResponseDTO respSelectDriver = JSONUtils.deserializeJSON(AppletResponseDTO.class,
                    selectDriverResp);
            if (respSelectDriver.checkError()) {
                return JSONUtils.serializeJSON(respSelectDriver);
            }
        }

        if (digitalSignatureClient.isEmptyPin()) {
            String loginResp = login(param);
            AppletResponseDTO respLogin = JSONUtils.deserializeJSON(AppletResponseDTO.class, loginResp);
            if (respLogin.checkError()) {
                return JSONUtils.serializeJSON(respLogin);
            }
        }

        AppletResponseDTO resp = new AppletResponseDTO(FUNCTION_SELECT_CERTIFICATE);
        try {
            digitalSignatureClient.setAlias(alias);
            X509Certificate signingCertificate = digitalSignatureClient.selectCertificate();
            if (signingCertificate != null) {
                resp.setResult(X509Utils.rawX509CertificateToHex(signingCertificate));
            }
        } catch (CertificateException e) {
            tracer.error("impossibile reperire il certificato per l'identit %s", e);
            processError(resp, "impossibile reperire il certificato per l'identit %s", e);
        } catch (InvalidCertificateException e) {
            tracer.error("impossibile reperire il certificato per l'identit %s", e);
            processError(resp, "impossibile reperire il certificato per l'identit %s", e);
        } catch (Throwable e) {
            tracer.error("scelta certificato fallita a causa di un errore interno", e);
            processError(resp, "scelta certificato fallita a causa di un errore interno", e);
        }

        tracer.info(String.format("respJSON: %s", JSONUtils.serializeJSON(resp)));
        return JSONUtils.serializeJSON(resp);
    }

    public String signDigest(String param) {

        AppletRequestDTO request = JSONUtils.deserializeJSON(AppletRequestDTO.class, param);

        String hexDigest = StringUtils.trim(request.getHexDigest());
        tracer.info(FUNCTION_SIGN_DIGEST);

        if (digitalSignatureClient.isEmptyDriver()) {
            String selectDriverResp = selectDriver(param);
            AppletResponseDTO respSelectDriver = JSONUtils.deserializeJSON(AppletResponseDTO.class,
                    selectDriverResp);
            if (respSelectDriver.checkError()) {
                return JSONUtils.serializeJSON(respSelectDriver);
            }
        }

        if (digitalSignatureClient.isEmptyPin()) {
            String loginResp = login(param);
            AppletResponseDTO respLogin = JSONUtils.deserializeJSON(AppletResponseDTO.class, loginResp);
            if (respLogin.checkError()) {
                return JSONUtils.serializeJSON(respLogin);
            }
        }

        if (digitalSignatureClient.isEmptyAlias()) {
            String selectCertificateResp = selectCertificate(param);
            AppletResponseDTO respSelectCertificate = JSONUtils.deserializeJSON(AppletResponseDTO.class,
                    selectCertificateResp);
            if (respSelectCertificate.checkError()) {
                return JSONUtils.serializeJSON(respSelectCertificate);
            }
        }

        AppletResponseDTO resp = new AppletResponseDTO(FUNCTION_SIGN_DIGEST);
        try {
            resp.setResult(digitalSignatureClient.sign(hexDigest));
        } catch (Exception e) {
            tracer.error("errore rilevato nell'applicazione della firma digitale da SmartCard", e);
            processError(resp, "errore rilevato nell'applicazione della firma digitale da SmartCard", e);
        }

        tracer.info(String.format("respJSON: %s", JSONUtils.serializeJSON(resp)));
        return JSONUtils.serializeJSON(resp);
    }

    private void processError(AppletResponseDTO resp, String errorMessage, Throwable errorCause) {
        if (StringUtils.isBlank(errorMessage)) {
            errorMessage = errorCause.getClass().getName();
        }
        resp.addActionError(errorMessage, errorCause);
        tracer.error(errorMessage, errorCause);
    }

}