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

时间:2013-08-27 09:51:36

标签: java security pdf itext digest

我使用iText库(Java)搜索将摘要(字节数组或字符串)插入PDF文件的方法。我用这种方法从String创建摘要:

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();
}

摘要不应在PDF中看到,但必须将其摘录以进行比较。

1 个答案:

答案 0 :(得分:4)

此类私人数据可以存储在 PieceInfo 词典中:

  

页面字典(PDF 1.3)可用于保存符合私人要求的产品数据。数据可以通过页面对象中的可选 PieceInfo 条目(参见表30)或表单字典(参见表95)与页面或表单XObject相关联。从PDF 1.4开始,私有数据也可以通过文档目录中的 PieceInfo 条目与PDF文档相关联(参见表28)。

     

ISO 32000-1的第14.5节)

在您的情况下,文档目录中的 PieceInfo 似乎最适合。

使用iText,您可以在那里存储数据并使用下面的DocumentPieceInfo帮助程序类重新检索它们:

存储文档 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();

检索文档 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);

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);
    }
}

此类假定私有值为字典,其中依次存储私有数据。但它可能是任何东西。要处理其他程序生成的私人数据,您可能需要进行一些变更。