无法验证pdf签名。 itext,pdf,GOST3410

时间:2014-08-18 11:45:32

标签: java pdf itext gost3410

我正在尝试验证pdf文件中的签名。其中有三个。我已经使用我在互联网上找到的代码签署了该文件,并根据我的需要采用,因此它也可能是正确的。这是签名文件pdf file

Verifier代码:

package com.mycompany.verifysignature;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.bouncycastle.crypto.digests.GOST3411Digest;
import ru.CryptoPro.CAdES.CAdESSignature;
import ru.CryptoPro.CAdES.CAdESType;

public class Main {

public static void main(String args[]) {

    try {
        ArrayList<Map<String, String>> resList = new ArrayList<Map<String, String>>();

                    InputStream pdfIs = new FileInputStream("/home/user1/Desktop/321-17.pdf");

        com.itextpdf.text.pdf.PdfReader reader = new com.itextpdf.text.pdf.PdfReader(pdfIs);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        com.itextpdf.text.pdf.PdfStamper stamper = com.itextpdf.text.pdf.PdfStamper.createSignature(reader, baos, '\0');
        com.itextpdf.text.pdf.PdfSignatureAppearance sap = stamper.getSignatureAppearance();

        com.itextpdf.text.pdf.AcroFields fields = reader.getAcroFields();
        for (String signame : fields.getSignatureNames()) {
            HashMap<String, String> m = new HashMap();
            m.put("name", signame.toString());
                            System.out.println("name:"+signame);
            com.itextpdf.text.pdf.PdfDictionary sig = fields.getSignatureDictionary(signame);
            if (sig != null && sig.getAsString(com.itextpdf.text.pdf.PdfName.REASON) != null) {
                m.put("reason", sig.getAsString(com.itextpdf.text.pdf.PdfName.REASON).toString()
                    .replaceAll("\"", "\\\""));
                                    System.out.println("reason:"+sig.getAsString(com.itextpdf.text.pdf.PdfName.REASON).toString()
                    .replaceAll("\"", "\\\""));
            } else {
                m.put("reason", "undefined");
                                    System.out.println("reason:undefined");
            }


            byte signature[] = null;

            if (sig != null && sig.getBytes() != null) {
                signature = sig.getBytes();
            }

            byte hash[] = calcHash(sap.getRangeStream());

            if (hash != null) {

                CAdESSignature  cadesSignature = new CAdESSignature(signature, hash, CAdESType.CAdES_X_Long_Type_1);

                try {
                    cadesSignature.verify(null);
                    m.put("valid", "true");
                                            System.out.println("valid:true");
                } catch(Exception ex) {
                    m.put("valid", "false");
                                            System.out.println("valid:false");
                }
            } else {
                m.put("valid", "\"undefined\"");
                                    System.out.println("valid:undefined");
            }


//              com.itextpdf.text.pdf.security.PdfPKCS7 pk = fields.verifySignature(signame);
//              
//              m.put("valid", new Boolean(pk.verify()).toString());
//                                System.out.println("valid:"+new Boolean(pk.verify()).toString());

            resList.add(m);
        }
            } catch (Exception ex) {
                ex.printStackTrace();
            }

}



public static byte[] calcHash(InputStream is) {
    if (is == null) return null;
    try {
        GOST3411Digest digest = new GOST3411Digest();

        byte node[] = readBytesFromStream(is);
        digest.update(node, 0, node.length);

        byte[] resBuf = new byte[digest.getDigestSize()];
        digest.doFinal(resBuf, 0);

        return resBuf;
    } catch (Throwable e) {
        e.printStackTrace();
        //throw new Exception(e);
    }
    return null;
}   

private static byte[] readBytesFromStream(InputStream is) throws Exception {
    ArrayList<Object[]> c = new ArrayList();
    int n, size = 0;
    byte b[] = null;
    if (is == null) throw new Exception("input stream is null");
    try {
        while ((n = is.read(b = new byte[1024])) > 0) {
            c.add(new Object[] { n, b });
            size += n;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    byte rv[] = new byte[size];
    int pos = 0;
    for (Object[] bb : c) {
        for (int i = 0; i < (Integer) bb[0]; i++) {
            rv[pos++] = ((byte[]) bb[1])[i];
        }
    }
    return rv;
}



}

我已经使用GOST3411签署了文件摘要,其中包含在cryptopro网站上生成的测试证书。

当我用pdf阅读器打开这个文件时,它说有3个签名。我真的签了三次。但上面的代码取自pdf签名名称,这些名称与我写的名称不相同。它们看起来像Signature1,Signature2等。在所有三种情况下都应该写成“CN”。请帮忙。我做错了什么?

1 个答案:

答案 0 :(得分:1)

OP提供的文件321-174.pdf仅使用一个签名而非三个签名,主要错误是签名词典内容的内容不是 CMS签名,而是文本上的东西,可能是base64 编码。因此,代码之间的某些解码似乎是必要的。

据说我在规范ISO 32000-1的表257 - SubFilter值算法支持中找不到GOST3410 - 因此它在这种情况下的使用很可能不会被接受。