iText - Generating PDF hash without certificate chain

后端 未结 1 1109
鱼传尺愫
鱼传尺愫 2020-12-16 07:14

I\'m trying to build an application where the following happens:

  1. A client requests a PDF-hash from the server.
  2. The server generates the hash of a PDF-
相关标签:
1条回答
  • 2020-12-16 07:34

    It seems that you have overlooked the DeferredSigning example.

    In this example, we first create a PDF with an empty signature:

    public void emptySignature(String src, String dest, String fieldname, Certificate[] chain) throws IOException, DocumentException, GeneralSecurityException {
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, fieldname);
        appearance.setCertificate(chain[0]);
        ExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
        MakeSignature.signExternalContainer(appearance, external, 8192);
    }
    

    Granted, the public certificate chain[0] is passed to the appearance in this example, it is used to create the visual appearance and to create the PdfPKCS7 object.

    Once you have a PDF with an empty signature, you can create a PdfSignatureAppearance on the server and get the hash that can be sent to the client for signing. This can be done using the getRangeStream() method to get the ranges of PDF bytes that need to be hashed. This method returns an InputStream, that can be used like this:

    BouncyCastleDigest digest = new BouncyCastleDigest();
    PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, null, digest, false);
    byte[] hash = DigestAlgorithms.digest(is, digest.getMessageDigest(hashAlgorithm));
    Calendar cal = Calendar.getInstance();
    byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, cal, null, null, CryptoStandard.CMS);
    

    Now you can send this sh to the client for signing. You will receive another byte[] which is the actual signature that needs to be added to the PDF, let's say the byte[] is called sig.

    Your external signature container can be kept very simple: it just needs to return the signature bytes:

    class MyExternalSignatureContainer implements ExternalSignatureContainer {
        protected byte[] sig;
        public MyExternalSignatureContainer(byte[] sig) {
            this.sig = sig;
        }
        public byte[] sign(InputStream is) throws Exception {
            return sig;
        }
        public void modifySigningDictionary(PdfDictionary signDic) {
        }
    }
    

    You can now use the createSignature() method on the server:

    public void createSignature(String src, String dest, String fieldname, PrivateKey pk, Certificate[] chain) throws IOException, DocumentException, GeneralSecurityException {
        
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        ExternalSignatureContainer external = new MyExternalSignatureContainer(sig);
        MakeSignature.signDeferred(reader, fieldname, os, external);
    }
    
    0 讨论(0)
提交回复
热议问题