package test.pdf;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.cert.Certificate;
import java.util.Arrays;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;

import test.keystore.MyKeyStore;

public class TestPdfHashIssue {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		// args[0] keystore file path
		// args[1] keystore password
		// args[2] source pdf file path
		// args[3] signer certificate alias

		MyKeyStore ks = new MyKeyStore(MyKeyStore.KS_TYPE);
		ks.load(args[0], args[1].toCharArray());

		TestPdfHashIssue pdf = new TestPdfHashIssue();
		byte[] hash1 = pdf.getHash(args[2], ks.getCertificateChain(args[3]));
		System.out.println("Hash 1: " + Arrays.toString(hash1));

		byte[] hash2 = pdf.getHash(args[2], ks.getCertificateChain(args[3]));
		System.out.println("Hash 2: " + Arrays.toString(hash2));

		if (Arrays.equals(hash1, hash2)) {
			System.out.println("Same hash!");
		} else {
			System.err.println("Different hash :(");
		}
	}

	private byte[] getHash(String srcPdfPath, Certificate[] chain) throws Exception {
		int keySize = 128;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		PdfReader reader = new PdfReader(srcPdfPath);
		PdfStamper stp = PdfStamper.createSignature(reader, baos, '\0');

		PdfSignatureAppearance sap = stp.getSignatureAppearance();
		sap.setCrypto(null, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
		sap.setExternalDigest(new byte[keySize], new byte[20], "RSA");
		sap.preClose();

		// input stream to byte array
		byte[] result;
		{
			InputStream is = sap.getRangeStream();
			byte[] buff = new byte[8192];
			int read = -1;
			ByteArrayOutputStream ba = new ByteArrayOutputStream();
			while ((read = is.read(buff)) > 0) {
				ba.write(buff, 0, read);
			}
			buff = null;
			result = ba.toByteArray();
			ba.close();
		}

		// computing hash
		{
			MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
			messageDigest.update(result);
			result = messageDigest.digest();
		}

		return result;
	}

}
