简体   繁体   English

使用iText库在pdf中插入隐藏的摘要

[英]Insert hidden digest in pdf using iText library

I search a method for insert a digest (byte array or String) into PDF file using iText library (Java). 我使用iText库(Java)搜索将摘要(字节数组或字符串)插入PDF文件的方法。 I create the digest from a String with this method: 我使用以下方法从字符串创建摘要:

private String crypt(double x, ByteArrayOutputStream baos) throws UnsupportedEncodingException, NoSuchAlgorithmException{
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(String.valueOf(x).getBytes("UTF-8"));
    md.update(String.valueOf(baos).getBytes("UTF-8"));
    byte[] digest = md.digest();

    StringBuffer sb = new StringBuffer();
    for(byte d:digest){
        sb.append(Integer.toHexString(0xFF & d));
    }
    return sb.toString();
}

The digest should be not seen in PDF, but it must be exctracted for comparison. 摘要不应在PDF中看到,但必须将其摘要进行比较。

Such private data can be stored in PieceInfo dictionaries: 此类私有数据可以存储在PieceInfo词典中:

A page-piece dictionary (PDF 1.3) may be used to hold private conforming product data. 分页字典(PDF 1.3)可用于保存私有的符合条件的产品数据。 The data may be associated with a page or form XObject by means of the optional PieceInfo entry in the page object (see Table 30) or form dictionary (see Table 95). 数据可以通过页面对象(请参见表30)或表单字典(请参见表95)中的可选PieceInfo条目与页面或表单XObject关联。 Beginning with PDF 1.4, private data may also be associated with the PDF document by means of the PieceInfo entry in the document catalogue (see Table 28). 从PDF 1.4开始,私有数据也可以通过文档目录中的PieceInfo条目与PDF文档相关联(请参见表28)。

(section 14.5 of ISO 32000-1 ) ISO 32000-1第14.5节)

In your case the PieceInfo in the document catalogue seem most apropos. 在您的情况下,文档目录中的PieceInfo似乎最合适

Using iText you can store data there and retrieve them back again like this using the DocumentPieceInfo helper class below: 使用iText,您可以在此处存储数据,然后使用下面的DocumentPieceInfo帮助器类像这样再次取回数据:

Storing document PieceInfo data 存储文件PieceInfo数据

PdfName appName = new PdfName("MYAPP");
PdfName dataName = new PdfName("Hash");

DocumentPieceInfo dpi = new DocumentPieceInfo();

PdfReader reader = new PdfReader(...);
dpi.addPieceInfo(reader, appName, dataName, new PdfString(data));

PdfStamper stamper = new PdfStamper(reader, ...);
stamper.close();

Retrieving document PieceInfo data 检索文件PieceInfo数据

PdfName appName = new PdfName("MYAPP");
PdfName dataName = new PdfName("Hash");

DocumentPieceInfo dpi = new DocumentPieceInfo();

PdfReader reader = new PdfReader("target/test-outputs/test-with-piece-info.pdf");
PdfObject myData = dpi.getPieceInfo(reader, appName, dataName);

The DocumentPieceInfo helper class DocumentPieceInfo帮助程序类

public class DocumentPieceInfo
{
    static PdfName PIECE_INFO = new PdfName("PieceInfo");
    static PdfName LAST_MODIFIED = new PdfName("LastModified");
    static PdfName PRIVATE = new PdfName("Private");

    void addPieceInfo(PdfReader reader, PdfName app, PdfName name, PdfObject value)
    {
        PdfDictionary catalog = reader.getCatalog();
        PdfDictionary pieceInfo = catalog.getAsDict(PIECE_INFO);
        if (pieceInfo == null)
        {
            pieceInfo = new PdfDictionary();
            catalog.put(PIECE_INFO, pieceInfo);
        }

        PdfDictionary appData = pieceInfo.getAsDict(app);
        if (appData == null)
        {
            appData = new PdfDictionary();
            pieceInfo.put(app, appData);
        }

        PdfDictionary privateData = appData.getAsDict(PRIVATE);
        if (privateData == null)
        {
            privateData = new PdfDictionary();
            appData.put(PRIVATE, privateData);
        }

        appData.put(LAST_MODIFIED, new PdfDate());
        privateData.put(name, value);
    }

    PdfObject getPieceInfo(PdfReader reader, PdfName app, PdfName name)
    {
        PdfDictionary catalog = reader.getCatalog();

        PdfDictionary pieceInfo = catalog.getAsDict(PIECE_INFO);
        if (pieceInfo == null)
            return null;

        PdfDictionary appData = pieceInfo.getAsDict(app);
        if (appData == null)
            return null;

        PdfDictionary privateData = appData.getAsDict(PRIVATE);
        if (privateData == null)
            return null;

        return privateData.get(name);
    }
}

This class assumes the Private value to be a dictionary in which in turn the private data are stored. 此类假定Private值是一个字典,在其中又存储了私有数据。 It may be anything, though. 可能是任何东西。 To process the private data generated by other programs, you may need some variation. 要处理其他程序生成的私有数据,您可能需要进行一些更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM