Assinatura digital com Java

Boa tarde;
No meu sistema, eu crio um documento com o jasper report, guardo ele em uma pasta do meu computador, o que eu preciso, é ter certeza de que ele foi assinado digitalmente, eu fiz o código pra ele assinar, e aparentemente ele funciona, só que eu queria que no documento, em alguma parte dele, mostrasse que o documento foi assinado, tem como fazer isso ? e se não tiver, como eu posso atestar que ele foi assinado digitalmente ?

É mais ou menos isso que eu quero fazer

Meu código que faz a assinatura:

package br.com.ufpr.es.modelo;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;

public class Remetente {

	

	private PublicKey pubKey;

	public PublicKey getPubKey() {
		return pubKey;
	}

	public void setPubKey(PublicKey pubKey) {
		this.pubKey = pubKey;
	}

	public byte[] geraAssinatura(byte[] mensagem) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
		Signature sig = Signature.getInstance("DSA");

		// Geração das chaves públicas e privadas
		KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
		SecureRandom secRan = new SecureRandom();
		kpg.initialize(512, secRan);
		KeyPair keyP = kpg.generateKeyPair();
		this.pubKey = keyP.getPublic();
		PrivateKey priKey = keyP.getPrivate();

		// Inicializando Obj Signature com a Chave Privada
		sig.initSign(priKey);

		// Gerar assinatura
		sig.update(mensagem);
		byte[] assinatura = sig.sign();

		return assinatura;
	}

}


package br.com.ufpr.es.modelo;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;

public class Destinatario {
	
	public void recebeMensagem(PublicKey pubKey, byte[] mensagem, byte[] assinatura) throws
	   NoSuchAlgorithmException, InvalidKeyException, SignatureException {
	       Signature clientSig = Signature.getInstance("DSA");  
	       clientSig.initVerify(pubKey);  
	       clientSig.update(mensagem);  
	          
	       if (clientSig.verify(assinatura)) {  
	           //Mensagem corretamente assinada
	          System.out.println("A Mensagem recebida foi assinada corretamente.");
	       } else {
	           //Mensagem não pode ser validada
	          System.out.println("A Mensagem recebida NÃO pode ser validada.");
	       }  
	   }

}

método no main

public void assinarDocumento() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
		
		Remetente remetenteAssiDig = new Remetente();
		File arquivo = new File(enderecoArquivo);
		byte[] mensagem  = new byte[(int) arquivo.length()];
		//gerar assinatura
		byte[] assinatura = remetenteAssiDig.geraAssinatura(mensagem);

		//armazena chave pública
		PublicKey pubKey = remetenteAssiDig.getPubKey();
		
		//Envia dados ao destinatário
		Destinatario destinatarioAssiDig = new Destinatario();
		destinatarioAssiDig.recebeMensagem(pubKey, mensagem, assinatura);
	}
1 curtida

Conheço isso em python:

Interessante, mas eu preciso em Java mesmo

Estou precisando de um código assim.

Da para fazer com itext:

import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Security;
import java.util.ArrayList;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.security.PdfPKCS7;

public class PDFSignature {

	public PdfPKCS7 verifySignature(AcroFields fields, String name) throws GeneralSecurityException, IOException {
		System.out.println("Signature covers whole document: " + fields.signatureCoversWholeDocument(name));
		System.out.println("Document revision: " + fields.getRevision(name) + " of " + fields.getTotalRevisions());
        PdfPKCS7 pkcs7 = fields.verifySignature(name);
        System.out.println("Integrity check OK? " + pkcs7.verify());
        return pkcs7;
	}
	
	public void verifySignatures(String path) throws IOException, GeneralSecurityException {
		System.out.println(path);
        PdfReader reader = new PdfReader(path);
        AcroFields fields = reader.getAcroFields();
        ArrayList<String> names = fields.getSignatureNames();
		for (String name : names) {
			System.out.println("===== " + name + " =====");
			verifySignature(fields, name);
		}
		System.out.println();
	}
	
	public static void main(String[] args) throws Exception {
		if (args.length != 1) {
			throw new Exception("Invalid input file");
		}
		String filename = args[0];
		java.io.File f = new File(filename);
		if (!f.isFile() || !f.canRead()) {
			throw new Exception(String.format("Cannot read file: %1", filename));
		}
		
		LoggerFactory.getInstance().setLogger(new SysoLogger());
		BouncyCastleProvider provider = new BouncyCastleProvider();
		Security.addProvider(provider);
		PDFSignature app = new PDFSignature();
		app.verifySignatures(f.getAbsolutePath());
	}
}
1 curtida

Eu fiz algo parecido, com iText.
Cheguei a validar isso no adobe, fica show de bola.
Tem material no google.
Se eu achar meu projeto, te passo pra você conferir.

E seu fizesse só uma variável que recebe o nome da sessão por exemplo, e valida-se, se assinou, a variável do ireport é preenchida, se não assinou, dá um erro em tela ? Poderia ser um jeito ?

Até onde lembro, isso não funciona.