com.teasoft.teavote.util.Signature.java Source code

Java tutorial

Introduction

Here is the source code for com.teasoft.teavote.util.Signature.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.teasoft.teavote.util;

//import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
//import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.teasoft.teavote.exceptions.MissingParameterException;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 *
 * @author Elikem
 */
@Service
public class Signature {

    @Autowired
    MyResource res;

    private PublicKey getPublicKey()
            throws IOException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException {
        Resource resource = res.getResource("classpath:gotaSafui");
        byte[] pubKeyBytes;
        try (InputStream pubKeyInputStream = resource.getInputStream()) {
            pubKeyBytes = IOUtils.toByteArray(pubKeyInputStream);
            pubKeyBytes = Base64.decodeBase64(pubKeyBytes);
        }
        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(pubKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("DSA", "SUN");
        PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
        return pubKey;
    }

    private PrivateKey getPrivateKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        Resource resource = res.getResource("classpath:xormeSafui");
        byte[] privKeyBytes;
        try (InputStream privKeyInputStream = resource.getInputStream()) {
            privKeyBytes = IOUtils.toByteArray(privKeyInputStream);
            privKeyBytes = Base64.decodeBase64(privKeyBytes);
        }
        PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(privKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("DSA");
        PrivateKey privKey = keyFactory.generatePrivate(privKeySpec);
        return privKey;
    }

    //    public Signature getSignature(String base64Signature) throws NoSuchAlgorithmException, NoSuchProviderException {
    //        byte[] sigToVerify = Base64.decodeBase64(base64Signature);
    //        java.security.Signature sig = java.security.Signature.getInstance("SHA1withDSA", "SUN");
    //    }
    public boolean verifyFile(String pathToFile) throws FileNotFoundException, NoSuchAlgorithmException,
            NoSuchProviderException, InvalidKeyException, IOException, SignatureException, InvalidKeySpecException {
        File fileToVerify = new File(pathToFile);
        FileInputStream originalFileIs = new FileInputStream(fileToVerify);

        String dataPathToVerify = new ConfigLocation().getConfigPath() + File.separator + "dataToVerify.sql";
        File dataToVerify = new File(dataPathToVerify);
        FileOutputStream fw = new FileOutputStream(dataToVerify);

        //Read the caution message and signature out
        byte[] cautionMsg = new byte[175]; //Caution section occupies 175 bytes
        originalFileIs.read(cautionMsg);

        //Read and Write the rest of the bytes in original file into data to verify
        byte[] buffer = new byte[1024];
        int nRead = 0;
        while ((nRead = originalFileIs.read(buffer)) != -1) {
            fw.write(buffer, 0, nRead);
        }
        //Close originalFileIs and dataToVerify
        originalFileIs.close();
        fw.close();

        //Get signature from caution/signation message
        byte[] sigToVerify = new byte[64];
        for (int i = 0, j = 0; i < cautionMsg.length; i++) {
            if (i >= 106 && i < 170) {
                sigToVerify[j++] = cautionMsg[i];
            }
        }
        //decode signature bytes
        sigToVerify = Base64.decodeBase64(sigToVerify);
        //        sigToVerify = com.sun.org.apache.xml.internal.security.utils.Base64.decode(sigToVerify);

        java.security.Signature sig = java.security.Signature.getInstance("SHA1withDSA", "SUN");
        sig.initVerify(getPublicKey());
        //Get digital signature
        FileInputStream datafis = new FileInputStream(dataPathToVerify);
        BufferedInputStream bufin = new BufferedInputStream(datafis);
        int len;
        while (bufin.available() != 0) {
            len = bufin.read(buffer);
            sig.update(buffer, 0, len);
        }
        bufin.close();
        //Delete fileToVerify
        dataToVerify.delete();
        return sig.verify(sigToVerify);

    }

    /**
     * Signs a given sql backup digitally. The file to sign is modified by
     * prepending the public key to it. The resultant file is digitally signed.
     * The public key is removed and a caution message and the digital signature
     * is written at the top of the file.
     *
     * In verifying the file, the caution message and digital signature must be
     * replaced with the public key
     *
     * @param pathToData
     * @throws FileNotFoundException
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws InvalidKeyException
     * @throws SignatureException
     * @throws InvalidKeySpecException
     */
    public void signData(String pathToData) throws FileNotFoundException, IOException, NoSuchAlgorithmException,
            NoSuchProviderException, InvalidKeyException, SignatureException, InvalidKeySpecException {
        String pathToDuplicate = new ConfigLocation().getConfigPath() + File.separator + "duplicate.sql";
        try ( //Create a copy of the file
                FileInputStream originalFileIs = new FileInputStream(pathToData)) {
            File duplicateFile = new File(pathToDuplicate);
            try (FileOutputStream fos = new FileOutputStream(duplicateFile)) {
                fos.write(IOUtils.toByteArray(originalFileIs));
                //fos.flush();
                originalFileIs.close();
            }
        }

        byte[] buffer = new byte[1024];
        int nRead = 0;

        java.security.Signature dsa = java.security.Signature.getInstance("SHA1withDSA", "SUN");
        dsa.initSign(getPrivateKey());
        FileInputStream fis = new FileInputStream(pathToData);
        BufferedInputStream bufin = new BufferedInputStream(fis);
        int len;
        while ((len = bufin.read(buffer)) >= 0) {
            dsa.update(buffer, 0, len);
        }
        ;
        bufin.close();
        byte[] realSig = dsa.sign();

        //Create file starting with the signature
        String sigString = "-- " + Base64.encodeBase64String(realSig);
        String caution = "-- CAUTION: THIS FILE IS DIGITALLY SIGNED. DO NOT MODIFY IT. ANY CHANGE WILL RENDER IT UNRESTORABLE";

        FileOutputStream signedDataFw = new FileOutputStream(pathToData);
        signedDataFw.write("--\n".getBytes());
        signedDataFw.write((caution + "\n").getBytes());
        signedDataFw.write((sigString + "\n").getBytes());
        signedDataFw.write("--\n".getBytes());
        signedDataFw.write("\n".getBytes());
        //Write data to file.
        File duplicateFile = new File(pathToDuplicate);
        FileInputStream duplicateFileReader = new FileInputStream(duplicateFile);

        while ((nRead = duplicateFileReader.read(buffer)) != -1) {
            signedDataFw.write(buffer, 0, nRead);
        }
        //signedDataFw.flush();
        signedDataFw.close();
        duplicateFileReader.close();
        duplicateFile.delete();
    }

    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public JSONResponse nullPointerException(NullPointerException e) {
        return new JSONResponse(false, 0, null, e.getMessage());
    }

    @ExceptionHandler(SignatureException.class)
    @ResponseBody
    public JSONResponse signatureException(SignatureException e) {
        return new JSONResponse(false, 0, null, e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public JSONResponse exception(Exception e) {
        return new JSONResponse(false, 0, null, e.getMessage());
    }

    @ExceptionHandler(EmptyResultDataAccessException.class)
    @ResponseBody
    public JSONResponse exception(EmptyResultDataAccessException e) {
        return new JSONResponse(false, 0, null, e.getMessage());
    }

    @ExceptionHandler(MissingParameterException.class)
    @ResponseBody
    public JSONResponse exception(MissingParameterException e) {
        return new JSONResponse(false, 0, null, e.getMessage());
    }

}