Java tutorial
/* * 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()); } }