org.sinekartads.integration.cms.SignCMSonAlfresco.java Source code

Java tutorial

Introduction

Here is the source code for org.sinekartads.integration.cms.SignCMSonAlfresco.java

Source

/*
 * Copyright (C) 2010 - 2012 Jenia Software.
 *
 * This file is part of Sinekarta
 *
 * Sinekarta is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Sinekarta 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 General Public License for more details.
 *
 */
package org.sinekartads.integration.cms;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Test;
import org.sinekartads.applet.AppletRequestDTO;
import org.sinekartads.applet.AppletResponseDTO;
import org.sinekartads.applet.AppletResponseDTO.ActionErrorDTO;
import org.sinekartads.applet.AppletResponseDTO.FieldErrorDTO;
import org.sinekartads.applet.SignNOApplet;
import org.sinekartads.dto.ResultCode;
import org.sinekartads.dto.domain.DocumentDTO;
import org.sinekartads.dto.domain.SignatureDTO;
import org.sinekartads.dto.domain.TimeStampRequestDTO;
import org.sinekartads.dto.domain.VerifyDTO;
import org.sinekartads.dto.request.BaseRequest;
import org.sinekartads.dto.request.SkdsDocumentDetailsRequest;
import org.sinekartads.dto.request.SkdsFindRefByNameRequest;
import org.sinekartads.dto.request.SkdsSignRequest.SkdsPostSignRequest;
import org.sinekartads.dto.request.SkdsSignRequest.SkdsPreSignRequest;
import org.sinekartads.dto.response.BaseResponse;
import org.sinekartads.dto.response.SkdsDocumentDetailsResponse;
import org.sinekartads.dto.response.SkdsFindRefByNameResponse;
import org.sinekartads.dto.response.SkdsSignResponse.SkdsPostSignResponse;
import org.sinekartads.dto.response.SkdsSignResponse.SkdsPreSignResponse;
import org.sinekartads.integration.BaseIntegrationTC;
import org.sinekartads.model.domain.SecurityLevel.VerifyResult;
import org.sinekartads.model.domain.SignDisposition;
import org.sinekartads.model.domain.SignatureType.SignCategory;
import org.sinekartads.model.domain.TimeStampInfo;
import org.sinekartads.model.domain.Transitions.VerifiedSignature;
import org.sinekartads.model.domain.VerifyInfo;
import org.sinekartads.model.oid.DigestAlgorithm;
import org.sinekartads.model.oid.SinekartaDsObjectIdentifiers;
import org.sinekartads.util.DNParser;
import org.sinekartads.util.HexUtils;
import org.sinekartads.util.TemplateUtils;
import org.sinekartads.util.x509.X509Utils;
import org.sinekartads.utils.JSONUtils;

public class SignCMSonAlfresco extends BaseIntegrationTC {

    static final DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

    static Logger tracer = Logger.getLogger(SignCMSonAlfresco.class);

    private static final String SOURCE_NAME = "pippo.txt";

    private static final int PORT = 8080;
    private static final String HOST_NAME = "localhost";
    //   private static final String HOST_NAME = "jeniasrv014.jenia.it";
    private static final String USER = "admin";
    private static final String PWD = "admin";

    @Test
    public void test() throws Exception {
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
            Security.addProvider(new BouncyCastleProvider());
        }

        SignNOApplet applet = new SignNOApplet();
        try {

            // Main options
            boolean applyMark = true;
            boolean useFakeSmartCard = true;
            String driver;
            String scPin;
            if (useFakeSmartCard) {
                driver = "fake";
                scPin = "123";
            } else {
                driver = "libbit4ipki.so";
                scPin = "18071971";
            }

            // Test products
            String[] aliases;
            String alias;
            X509Certificate certificate;
            X509Certificate[] certificateChain;
            byte[] fingerPrint;
            byte[] digitalSignature;

            // Communication unities
            DocumentDTO[] documents;
            String jsonResp;
            SkdsDocumentDetailsResponse detailsResp;
            SkdsPreSignResponse preSignResp;
            SkdsPostSignResponse postSignResp;
            AppletResponseDTO appletResponse;
            SignatureDTO emptySignatureDTO;
            SignatureDTO chainSignatureDTO;
            SignatureDTO digestSignatureDTO;
            SignatureDTO signedSignatureDTO;
            SignatureDTO finalizedSignatureDTO;
            VerifyDTO verifyDTO;

            // Init the applet
            try {
                AppletRequestDTO req = new AppletRequestDTO();
                req.setDriver(driver);
                appletResponse = applet.selectDriver(req);
            } catch (Exception e) {
                tracer.error("error during the applet initialization", e);
                throw e;
            }

            // Login with the smartCard
            try {
                AppletRequestDTO req = new AppletRequestDTO();
                req.setDriver(driver);
                req.setPin(scPin);
                appletResponse = applet.login(req);
                aliases = (String[]) JSONUtils.deserializeJSON(String[].class, extractJSON(appletResponse));
            } catch (Exception e) {
                tracer.error("error during the applet login", e);
                throw e;
            }

            // Choose the signing alias
            StringBuilder buf = new StringBuilder();
            for (String a : aliases) {
                buf.append(a).append(" ");
            }
            alias = aliases[0];
            tracer.info(String.format("available aliases:   %s", buf));
            tracer.info(String.format("signing alias:       %s", alias));

            // Load the certificate chain from the applet
            try {
                AppletRequestDTO req = new AppletRequestDTO();
                req.setDriver(driver);
                req.setPin(scPin);
                req.setAlias(alias);
                appletResponse = applet.selectCertificate(req);
                certificate = (X509Certificate) X509Utils.rawX509CertificateFromHex(extractJSON(appletResponse));
                tracer.info(String.format("certificate:         %s", certificate));
                certificateChain = new X509Certificate[] { certificate };
            } catch (Exception e) {
                tracer.error("error during the certificate selection", e);
                throw e;
            }

            // FindRefByName
            String sourceRef = null;
            try {
                SkdsFindRefByNameRequest req = new SkdsFindRefByNameRequest();
                req.setName(SOURCE_NAME);
                SkdsFindRefByNameResponse findResp = postJsonRequest(req, SkdsFindRefByNameResponse.class);
                if (ResultCode.valueOf(findResp.getResultCode()) == ResultCode.SUCCESS) {
                    sourceRef = findResp.getNodeRef();
                } else {
                    throw new Exception(findResp.getMessage());
                }
            } catch (Exception e) {
                tracer.error("error during the pre sign phase", e);
                throw e;
            }

            // DocumentDetails
            try {
                //            String sourceRef = getNodeRefId("pippo.txt");
                SkdsDocumentDetailsRequest req = new SkdsDocumentDetailsRequest();
                req.setNodeRefs(new String[] { sourceRef });
                //            req.setNodeRefs ( new String[] {SOURCE_REF} );
                detailsResp = postJsonRequest(req, SkdsDocumentDetailsResponse.class);
                if (ResultCode.valueOf(detailsResp.getResultCode()) == ResultCode.SUCCESS) {
                    documents = detailsResp.documentsFromBase64();
                } else {
                    throw new Exception(detailsResp.getMessage());
                }
                String fileName = documents[0].getBaseDocument().getFileName();
                if (applyMark) {
                    documents[0].setDestName(fileName + ".p7m.tsd");
                } else {
                    documents[0].setDestName(fileName + ".p7m");
                }
            } catch (Exception e) {
                tracer.error("error during the pre sign phase", e);
                throw e;
            }

            // empty signature - initialized with the SHA256withRSA and RSA algorithms
            emptySignatureDTO = new SignatureDTO();
            emptySignatureDTO.setSignAlgorithm(conf.getSignatureAlgorithm().getName());
            emptySignatureDTO.setDigestAlgorithm(conf.getDigestAlgorithm().getName());
            emptySignatureDTO.signCategoryToString(SignCategory.CMS);

            // Add to the empty signature the timeStamp request if needed
            TimeStampRequestDTO tsRequestDTO = new TimeStampRequestDTO();
            if (applyMark) {
                tsRequestDTO.timestampDispositionToString(SignDisposition.TimeStamp.ENVELOPING);
                tsRequestDTO.messageImprintAlgorithmToString(DigestAlgorithm.SHA256);
                tsRequestDTO.nounceToString(BigInteger.TEN);
                tsRequestDTO.setTsUrl("http://ca.signfiles.com/TSAServer.aspx");
            }
            emptySignatureDTO.setTimeStampRequest(tsRequestDTO);

            // chain signature - contains the certificate chain
            chainSignatureDTO = TemplateUtils.Instantiation.clone(emptySignatureDTO);
            chainSignatureDTO.certificateChainToHex(certificateChain);
            documents[0].setSignatures(new SignatureDTO[] { chainSignatureDTO });

            // PreSign phase - join the content with the certificate chain and evaluate the digest
            try {
                SkdsPreSignRequest req = new SkdsPreSignRequest();
                req.documentsToBase64(documents);
                preSignResp = postJsonRequest(req, SkdsPreSignResponse.class);
                if (ResultCode.valueOf(preSignResp.getResultCode()) == ResultCode.SUCCESS) {
                    documents = preSignResp.documentsFromBase64();
                    digestSignatureDTO = documents[0].getSignatures()[0];
                } else {
                    throw new Exception(preSignResp.getMessage());
                }
            } catch (Exception e) {
                tracer.error("error during the pre sign phase", e);
                throw e;
            }

            // signed signature - sign the digest with the smartCard to obtain the digitalSignature
            try {
                fingerPrint = digestSignatureDTO.getDigest().fingerPrintFromHex();
                tracer.info(String.format("fingerPrint:         %s", HexUtils.encodeHex(fingerPrint)));
                AppletRequestDTO req = new AppletRequestDTO();
                req.setDriver(driver);
                req.setPin(scPin);
                req.setAlias(alias);
                req.setHexDigest(HexUtils.encodeHex(fingerPrint));
                appletResponse = applet.signDigest(req);
                digitalSignature = HexUtils.decodeHex((String) extractJSON(appletResponse));
                tracer.info(String.format("digitalSignature:    %s", HexUtils.encodeHex(digitalSignature)));
                signedSignatureDTO = TemplateUtils.Instantiation.clone(digestSignatureDTO);
                signedSignatureDTO.digitalSignatureToHex(digitalSignature);
                documents[0].getSignatures()[0] = signedSignatureDTO;
            } catch (Exception e) {
                tracer.error("error during the digital signature evaluation", e);
                throw e;
            }

            // PostSign phase - add the digitalSignature to the envelope and store the result into the JCLResultDTO
            try {
                SkdsPostSignRequest req = new SkdsPostSignRequest();
                req.documentsToBase64(documents);
                postSignResp = postJsonRequest(req, SkdsPostSignResponse.class);
                if (ResultCode.valueOf(postSignResp.getResultCode()) == ResultCode.SUCCESS) {
                    documents = postSignResp.documentsFromBase64();
                    finalizedSignatureDTO = documents[0].getSignatures()[0];
                } else {
                    throw new Exception(postSignResp.getMessage());
                }
            } catch (Exception e) {
                tracer.error("error during the envelope generation", e);
                throw e;
            }

            //         // Verify phase - load the envelope content and verify the nested signature 
            //         try {
            //            jsonResp = signatureService.verify ( envelopeHex, null, null, VerifyResult.VALID.name() );
            //            verifyDTO = extractResult ( VerifyDTO.class, jsonResp );
            //         } catch(Exception e) {
            //            tracer.error("error during the envelope verification", e);
            //            throw e;
            //         }
            //         
            //         // finalized signature - enveloped signed and eventually marked, not modifiable anymore
            //         try {
            //            verifyResult = (VerifyInfo) converter.toVerifyInfo( verifyDTO );
            //         } catch(Exception e) {
            //            tracer.error("unable to obtain the verifyInfo from the DTO", e);
            //            throw e;
            //         }
            //         
            //         try {
            //            for(VerifiedSignature < ?, ?, VerifyResult, ?> verifiedSignature : verifyResult.getSignatures() ) {
            //               tracer.info(String.format ( "signature validity:  %s", verifiedSignature.getVerifyResult().name() ));
            //               tracer.info(String.format ( "signature type:      %s", verifiedSignature.getSignType().name() ));
            //               tracer.info(String.format ( "disposition:         %s", verifiedSignature.getDisposition().name() ));
            //               tracer.info(String.format ( "digest algorithm:    %s", verifiedSignature.getDigest().getAlgorithm().name() ));
            //               tracer.info(String.format ( "finger print:        %s", HexUtils.encodeHex(verifiedSignature.getDigest().getFingerPrint()) ));
            //               tracer.info(String.format ( "counter signature:   %s", verifiedSignature.isCounterSignature() ));
            //               tracer.info(String.format ( "signature algorithm: %s", verifiedSignature.getSignAlgorithm().name() ));
            //               tracer.info(String.format ( "digital signature:   %s", HexUtils.encodeHex(verifiedSignature.getDigitalSignature()) ));
            //               tracer.info(String.format ( "reason:              %s", verifiedSignature.getReason() ));
            //               tracer.info(String.format ( "signing location:    %s", verifiedSignature.getLocation() ));
            //               tracer.info(String.format ( "signing time:        %s", formatDate(verifiedSignature.getSigningTime()) ));
            //               tracer.info(String.format ( "\n "));
            //               tracer.info(String.format ( "signing certificate chain: "));
            //               for ( X509Certificate cert : verifiedSignature.getRawX509Certificates() ) {
            //                  showCertificate(cert);
            //               }
            //               if ( verifiedSignature.getTimeStamps() != null ) {
            //                  tracer.info(String.format ( "\n "));
            //                  tracer.info(String.format ( "timestamps: "));
            //                  for ( TimeStampInfo mark : verifiedSignature.getTimeStamps() ) {
            //                     tracer.info(String.format ( "timestamp validity:  %s", mark.getVerifyResult().name() ));
            //                     tracer.info(String.format ( "timestamp authority: %s", mark.getTsaName() ));
            //                     tracer.info(String.format ( "timestamp authority: %s", mark.getTsaName() ));
            //                     tracer.info(String.format ( "message imprint alg: %s", mark.getMessageInprintInfo().getAlgorithm().name() ));
            //                     tracer.info(String.format ( "message imprint:     %s", HexUtils.encodeHex(mark.getMessageInprintInfo().getFingerPrint()) ));
            //                     tracer.info(String.format ( "digest algorithm:    %s", mark.getDigestAlgorithm().name() ));
            //                     tracer.info(String.format ( "digital signature:   %s", HexUtils.encodeHex(mark.getDigitalSignature()) ));
            //                     tracer.info(String.format ( "signature algorithm: %s", mark.getSignAlgorithm().name() ));
            //                     tracer.info(String.format ( "timestamp certificate: "));
            //                     for ( X509Certificate cert : mark.getRawX509Certificates() ) {
            //                        showCertificate(cert);
            //                     }
            //                  }
            //               }
            //            }
            //         } catch(Exception e) {
            //            tracer.error("unable to print the verify results", e);
            //            throw e;
            //         }
            //         
        } finally {
            applet.close();
        }
    }

    private String extractJSON(AppletResponseDTO resp) throws Exception {
        String json;
        if (resp.checkSuccess()) {
            json = resp.getResult();
        } else {
            StringBuilder buf = new StringBuilder();
            for (FieldErrorDTO fieldError : resp.getFieldErrors()) {
                for (String errorMessage : fieldError.getErrors()) {
                    buf.append(String.format("fieldError  - %s: %s\n", fieldError.getField(), errorMessage));
                }
            }
            for (ActionErrorDTO actionError : resp.getActionErrors()) {
                buf.append(String.format("actionError - %s\n", actionError.getErrorMessage()));
            }
            throw new Exception(buf.toString());
        }
        return json;
    }

    private void showCertificate(X509Certificate certificate) {
        Map<String, String> dns = DNParser.parse(certificate.getSubjectDN());
        tracer.info(String.format("subject:             %s", dns.get(SinekartaDsObjectIdentifiers.dn_commonName)));
        tracer.info(String.format("country:             %s", dns.get(SinekartaDsObjectIdentifiers.dn_countryName)));
        tracer.info(String.format("organization:        %s",
                dns.get(SinekartaDsObjectIdentifiers.dn_organizationName)));
        tracer.info(String.format("organization unit:   %s",
                dns.get(SinekartaDsObjectIdentifiers.dn_organizationUnitName)));
        tracer.info(String.format("not before:          %s", formatDate(certificate.getNotBefore())));
        tracer.info(String.format("not after:           %s", formatDate(certificate.getNotAfter())));
        dns = DNParser.parse(certificate.getIssuerDN());
        tracer.info(String.format("issuer:              %s", dns.get(SinekartaDsObjectIdentifiers.dn_commonName)));
    }

    private String formatDate(Date date) {
        if (date == null)
            return "";
        return dateFormat.format(date);
    }

    public static <SkdsResponse extends BaseResponse> SkdsResponse postJsonRequest(BaseRequest request,
            Class<SkdsResponse> responseClass) throws IllegalStateException, IOException {

        SkdsResponse response = null;
        InputStream respIs = null;
        DefaultHttpClient httpclient = null;
        try {
            HttpHost targetHost = new HttpHost(HOST_NAME, PORT, "http");

            httpclient = new DefaultHttpClient();

            httpclient.getCredentialsProvider().setCredentials(
                    new AuthScope(targetHost.getHostName(), targetHost.getPort()),
                    new UsernamePasswordCredentials(USER, PWD));

            AuthCache authCache = new BasicAuthCache();

            BasicScheme basicAuth = new BasicScheme();
            authCache.put(targetHost, basicAuth);

            BasicHttpContext localcontext = new BasicHttpContext();
            localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);

            HttpPost httppost = new HttpPost("/alfresco/service" + request.getJSONUrl() + ".json?requestType=json");

            String req = request.toJSON();
            ByteArrayEntity body = new ByteArrayEntity(req.getBytes());
            httppost.setEntity(body);
            HttpResponse resp = httpclient.execute(targetHost, httppost, localcontext);
            HttpEntity entityResp = resp.getEntity();
            respIs = entityResp.getContent();

            response = TemplateUtils.Encoding.deserializeJSON(responseClass, respIs);

            EntityUtils.consume(entityResp);
            //      } catch(Exception e) {
            //         String message = e.getMessage();
            //         if ( StringUtils.isBlank(message) ) {
            //            message = e.toString();
            //         }
            //         tracer.error(message, e);
            //         throw new RuntimeException(message, e);
        } finally {
            if (httpclient != null) {
                httpclient.getConnectionManager().shutdown();
            }
            IOUtils.closeQuietly(respIs);
        }
        return response;
    }

}