将Signed Hash集成到原始PDF中 [英] Integrate Signed Hash into original PDF

查看:98
本文介绍了将Signed Hash集成到原始PDF中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将签名的哈希值集成到原始PDF中,但是签名的有效性仍然存在错误。

I am integrating a signed hash in an original PDF, and I still have an error on the validity of the signature. it's say that a pdf has been changed after signing.

在以下步骤中:我计算了哈希,然后将其发送以进行签名,最后得到了哈希符号,然后继续进行集成原始pdf

below the steps: I calculate the hash then I send it for signature and finally I get the hash sign and I proceed to the integration in the original pdf

package com.example.hashdocument;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.security.*;
import com.lexpersona.commons.utils.ProcessLauncher;
import java.io.*;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.*;


public class Test2 {

    private static final String SRC = "B:/Hash-et-Reconstitution/tmp/Doc_test.pdf";
    private static final String DST = "B:/Hash-et-Reconstitution/tmp/Doc_test_DST.pdf";
    private static final String HASH = "B:/Hash-et-Reconstitution/tmp/Doc_test_hashed.hash";
    
    private static final String PATH_BAT = "C:/Repo_LP7/lpcommand.bat";
    private static final String PIN = "123456";
    private static final String CERTIFICATE = "C:/lp7command/tools/certificate.p12";
    private static final String SIGNED_HASH = "B:/Hash-et-Reconstitution/tmp/doc_signed.hash";
    
    private static byte[] readFileToByteArray(File file){
        FileInputStream fis = null;
        byte[] bArray = new byte[(int) file.length()];
        try{
          fis = new FileInputStream(file);
          fis.read(bArray);
          fis.close();                   
        }catch(IOException ioExp){
          ioExp.printStackTrace();
        }
        return bArray;
      }
    public static File bytesToFile(byte[] fileByte,String pathFile)  {
        File file = new File(pathFile);
        try {
            OutputStream os = new FileOutputStream(file);
            os.write(fileByte);
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }
    public static byte[] signDocument() throws IOException {
        
        
        ProcessLauncher p = new ProcessLauncher(System.out, System.err);
        int exec;
        exec = p.exec("cmd.exe /c "+PATH_BAT+" <nul "+ SIGNED_HASH +" "+ PIN+" "
                + HASH+" "+CERTIFICATE, null, null);

        byte[] signedHash = readFileToByteArray(new File(SIGNED_HASH));
        
        return signedHash;
    }
     
    
    public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException {
        
        PdfSignatureAppearance appearance = null;
        ByteArrayOutputStream  os = null;
        String hash_document = "";
        
        InputStream data = null;
        int contentEstimated = 8192;

        PdfReader reader = new PdfReader(SRC);

        reader.unethicalreading = true;
        reader.setAppendable(true);

        int pdfPagenumber = 1;

        pdfPagenumber = reader.getNumberOfPages(); // Sign on last page

        os = new ByteArrayOutputStream ();
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);

        Calendar cal = Calendar.getInstance();        
        appearance = stamper.getSignatureAppearance();        
        appearance.setSignDate(cal);
        //appearance.setAcro6Layers(false);
        appearance.setReason("Signature de contrat");
        appearance.setLocation("MAROC");              
        appearance.setImage(null);
        appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);

        Rectangle rect = new Rectangle(300, 300, 20, 20);        
        appearance.setVisibleSignature(rect, pdfPagenumber, null);

        HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
        exc.put(PdfName.CONTENTS, new Integer(contentEstimated * 2 + 2));
        PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
        dic.setReason(appearance.getReason()); 
        dic.setLocation(appearance.getLocation());
        dic.setContact(appearance.getContact());
        dic.setDate(new PdfDate(appearance.getSignDate()));
        appearance.setCryptoDictionary(dic);

        appearance.preClose(exc);

        data = appearance.getRangeStream();    

        MessageDigest messageDigest;
        String provider = null;
        String hashAlgorithm = DigestAlgorithms.SHA256;
        if (provider == null){
            messageDigest = MessageDigest.getInstance(hashAlgorithm);
        }else {
            messageDigest = MessageDigest.getInstance(hashAlgorithm,provider);
        }


        int read = 0;
        byte[] buff = new byte[contentEstimated];

        while ((read = data.read(buff, 0, contentEstimated)) > 0)
        {
            messageDigest.update(buff,0,read);                      
        }
        byte[] hashDigest = messageDigest.digest();

        byte[] documentHash = org.bouncycastle.util.encoders.Hex.encode(hashDigest);

        //eSign Start        
        hash_document = new String(documentHash, "UTF-8");        
        System.out.println("Document Hash :"+hash_document);
        

        
        PrintStream out = new PrintStream(new FileOutputStream(HASH));
        out.print(hash_document);
        
        
        byte[] hashdocumentByte = signDocument();
        
        //////////////////// ADD SIGNED BYTES/HASH TO PDF DOCUMENT.      
        int contentEstimated2 = 8192;
        byte[] paddedSig = new byte[contentEstimated2];
        byte[] signedDocByte = hashdocumentByte;
        
        System.arraycopy(signedDocByte, 0, paddedSig, 0, signedDocByte.length);
        
        PdfDictionary dic2 = new PdfDictionary();
        dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));

        appearance.close(dic2);
        
        try(OutputStream outputStream = new FileOutputStream(DST)) {
            os.writeTo(outputStream);
        }

        os.close(); 
        
    }
}


推荐答案

您对这段代码有何看法:首先,我计算哈希并将其发送到服务器A进行签名

what do you think abous this code : First i calculate the hash and send to server A for signature

    PdfReader reader = new PdfReader(SRC);
    FileOutputStream os = new FileOutputStream(TEMP);
    PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
    PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
    appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
    //appearance.setCertificate(chain[0]);
    ExternalSignatureContainer external = new 
    ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
    MakeSignature.signExternalContainer(appearance, external, 8192);

    InputStream inp = appearance.getRangeStream();  

    BouncyCastleDigest digest = new BouncyCastleDigest();


     byte[] hash = DigestAlgorithms.digest(inp, digest.getMessageDigest("SHA256"));
     System.out.println("hash to sign : "+ hash);
     bytesToFile(hash, HASH);
     byte[] hashdocumentByte = TEST.signed_hash(hash);
     
     PdfReader reader2 = new PdfReader(TEMP);
    FileOutputStream os2 = new FileOutputStream(DEST);
    ExternalSignatureContainer external2 = new 
    MyExternalSignatureContainer(hashdocumentByte,null);
    MakeSignature.signDeferred(reader2, "sig", os2, external2);

在服务器B中,我在其中签名哈希值:

And in the server B where i sign the hash :

        BouncyCastleProvider providerBC = new BouncyCastleProvider();
        Security.addProvider(providerBC);

        // we load our private key from the key store
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream(CERTIFICATE), PIN);
        String alias = (String)ks.aliases().nextElement();
        Certificate[] chain = ks.getCertificateChain(alias);
        PrivateKey pk = (PrivateKey) ks.getKey(alias, PIN);
        
        
     PrivateKeySignature signature = new PrivateKeySignature(pk, "SHA256", null);
       BouncyCastleDigest digest = new BouncyCastleDigest();
        Calendar cal = Calendar.getInstance();
        String hashAlgorithm = signature.getHashAlgorithm();
        System.out.println(hashAlgorithm);
        PdfPKCS7 sgn = new PdfPKCS7(null, chain, "SHA256", null, digest, false);

        byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);
        byte[] extSignature = signature.sign(sh);

        System.out.println(signature.getEncryptionAlgorithm());
        sgn.setExternalDigest(extSignature, null, signature.getEncryptionAlgorithm());
        return sgn.getEncodedPKCS7(hash, null, null, null, CryptoStandard.CMS);

这篇关于将Signed Hash集成到原始PDF中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆