Вставить скрытый дайджест в pdf с помощью библиотеки iText

Я ищу метод для вставки дайджеста (массива байтов или строки) в файл PDF с использованием библиотеки iText (Java). Я создаю дайджест из строки с помощью этого метода:

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, но его необходимо извлечь для сравнения.


person user2641200    schedule 27.08.2013    source источник
comment
String.valueOf(baos).getBytes("UTF-8") --- вы уверены, что на самом деле не хотите baos.toByteArray()? Кроме того, что касается первоначального вопроса, под дайджестом не должно быть видно в PDF вы имеете в виду, что он не должен отображаться как часть контента? Таким образом, быть доступным для программного обеспечения для обработки PDF — это нормально?   -  person mkl    schedule 27.08.2013
comment
Спасибо за помощь, для первой части у вас есть право я изменил сейчас; для второй части да, дайджест не должен отображаться в содержании, но да, должен быть доступен в программной обработке   -  person user2641200    schedule 27.08.2013


Ответы (1)


Такие личные данные могут храниться в словарях PieceInfo:

Словарь на странице (PDF 1.3) может использоваться для хранения частных данных о продуктах, соответствующих требованиям. Данные могут быть связаны со страницей или формой XObject с помощью необязательной записи PieceInfo в объекте страницы (см. Таблицу 30) или словаре формы (см. Таблицу 95). Начиная с PDF 1.4, личные данные также могут быть связаны с документом PDF посредством записи PieceInfo в каталоге документов (см. Таблицу 28).

(раздел 14.5 ISO 32000- 1)

В вашем случае 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);
    }
}

Этот класс предполагает, что значение Private является словарем, в котором, в свою очередь, хранятся личные данные. Впрочем, это может быть что угодно. Для обработки личных данных, сгенерированных другими программами, вам могут понадобиться некоторые изменения.

person mkl    schedule 27.08.2013
comment
Спасибо большое, скоро докажу :) - person user2641200; 27.08.2013
comment
Я доказал это, и я доказываю, что нужно изменить еще что-то, но не сохранять словарь в файл pdf... и я понятия не имею, как сохранить этот словарь в формате pdf... - person user2641200; 28.08.2013
comment
Вы сделали то, что описано в разделе Хранение данных документа PieceInfo? - person mkl; 28.08.2013