Как включить LTV для подписи метки времени?

Я использую iText 5.5.3 для подписи документов PDF. Мне нужны эти документы с метками времени и поддержкой LTV. Я следовал инструкциям и использовал метод addLtv (пример кода 5.9, стр. 137 в официальном документе Lowagie). Я получаю PDF с 2-мя подписями, что нормально: первая - моя собственная, вторая - отметка времени на уровне документа.

Тем не менее, Acrobat говорит мне, что моя подпись включена LTV, но подпись отметки времени не:

http://img15.hostingpics.net/pics/727285so2.jpg

Это связано с тем, что информация об отзыве сертификата метки времени не включена в документ:

http://img15.hostingpics.net/pics/491507so2a.jpg

http://img15.hostingpics.net/pics/312720so2b.jpg

Насколько я понимаю, метод addLtv должен получить всю необходимую информацию об отзыве и внедрить ее в документ. Это правильно, или мне нужно "вручную" получать и встраивать эту информацию?

2 ответа

Решение

Вот пример кода, к которому относится этот вопрос:

public void addLtv(String src, String dest, OcspClient ocsp, CrlClient crl, TSAClient tsa) throws IOException, DocumentException, GeneralSecurityException
{
    PdfReader r = new PdfReader(src);
    FileOutputStream fos = new FileOutputStream(dest);
    PdfStamper stp = PdfStamper.createSignature(r, fos, '\0', null, true);
    LtvVerification v = stp.getLtvVerification();
    AcroFields fields = stp.getAcroFields();
    List<String> names = fields.getSignatureNames();
    String sigName = names.get(names.size() - 1);
    PdfPKCS7 pkcs7 = fields.verifySignature(sigName);
    if (pkcs7.isTsp())
    {
        v.addVerification(sigName, ocsp, crl,
            LtvVerification.CertificateOption.SIGNING_CERTIFICATE,
            LtvVerification.Level.OCSP_CRL,
            LtvVerification.CertificateInclusion.NO);
    }
    else
    {
        for (String name : names)
        {
            v.addVerification(name, ocsp, crl,
                LtvVerification.CertificateOption.WHOLE_CHAIN,
                LtvVerification.Level.OCSP_CRL,
                LtvVerification.CertificateInclusion.NO);
        }
    }
    PdfSignatureAppearance sap = stp.getSignatureAppearance();
    LtvTimestamp.timestamp(sap, tsa, null);
}

Этот код идентифицирует последнее заполненное поле подписи в PDF и проверяет, является ли это отметкой времени документа или обычной подписью.

Если это метка времени документа, код добавляет информацию проверки только для этой метки времени документа. В противном случае код добавляет информацию проверки для всех подписей.

(Предполагаемый рабочий процесс, стоящий за этим, заключается в том, что сначала документ подписывается (для сертификации и / или утверждения) несколько раз, а затем документ вводится в циклы LTV, добавляя информацию для проверки и метки времени документа, но больше никаких обычных подписей. Ваш рабочий процесс может отличаться и, следовательно, логика вашей программы тоже.)

Только после всего этого добавляется новая отметка времени документа.

Для этой окончательно добавленной метки времени информация о проверке явно не добавляется в PDF (если метки времени документа из того же TSA были применены в короткой последовательности, может быть применима информация о валидации, включенная в предыдущую метку времени). И именно поэтому Adobe Reader/Acrobat обычно не считает этот меткой времени документа LTV включенным.

Если вам нужна информация проверки для этой конечной метки времени документа, просто примените этот метод (такой же, как метод выше, просто не добавляя метку времени документа) к файлу с меткой времени документа:

public void addLtvNoTS(String src, String dest, OcspClient ocsp, CrlClient crl) throws IOException, DocumentException, GeneralSecurityException
{
    PdfReader r = new PdfReader(src);
    FileOutputStream fos = new FileOutputStream(dest);
    PdfStamper stp = new PdfStamper(r, fos, '\0', true);
    LtvVerification v = stp.getLtvVerification();
    AcroFields fields = stp.getAcroFields();
    List<String> names = fields.getSignatureNames();
    String sigName = names.get(names.size() - 1);
    PdfPKCS7 pkcs7 = fields.verifySignature(sigName);
    if (pkcs7.isTsp())
    {
        v.addVerification(sigName, ocsp, crl,
            LtvVerification.CertificateOption.SIGNING_CERTIFICATE,
            LtvVerification.Level.OCSP_CRL,
            LtvVerification.CertificateInclusion.NO);
    }
    else
    {
        for (String name : names)
        {
            v.addVerification(name, ocsp, crl,
                LtvVerification.CertificateOption.WHOLE_CHAIN,
                LtvVerification.Level.OCSP_CRL,
                LtvVerification.CertificateInclusion.NO);
        }
    }
    stp.close();
}

Фон

Причина, по которой iText addLtv Пример (не обязательно) создания PDF-файлов с поддержкой LTV заключается в том, что он ближе к лучшим методам LTV, предложенным ETSI в спецификации PAdES, чем к лучшим методам Adobe для LTV.

В соответствии с ETSI TS 102 778-4 V1.1.2 (2009-12) структура документа PDF, к которому применяется LTV, показана на рисунке 2.

Рисунок 2: Иллюстрация PDF документа с LTV

Срок службы защиты может быть дополнительно продлен после срока действия последнего примененного штампа времени документа путем добавления дополнительной информации DSS для проверки отметки времени предыдущего последнего документа вместе с отметкой времени нового документа. Это показано на рисунке 3.

Рисунок 3: Иллюстрация PDF документа с повторяющимся LTV

С другой стороны, по словам Adobe ( как написал их евангелист PDF Леонард Розентхол в списке рассылки iText в январе 2013 года),

LTV включен означает, что вся информация, необходимая для проверки файла (за исключением корневых сертификатов), содержится внутри. Так что это ваше утверждение будет правдой.

PDF подписан правильно и содержит все необходимые сертификаты, действительный ответ CRL или OSCP для каждого сертификата

Но поскольку единственный способ для того, чтобы это утверждение было правдой, - это наличие DSS, вы должны иметь DSS для появления LTV. Временная метка (обычная или на уровне документа) не требуется.

Из-за этого расхождения PDF-документы с LTV в соответствии с ETSI обычно представлены программным обеспечением Adobe, чтобы иметь одну метку времени без поддержки LTV.

Смотрите также

Что я сделал, так это внедрил данные LTV для метки времени перед меткой времени документа, запросив две метки времени (используя первую для извлечения данных LTV и обновления DSS, а вторую для фактической метки времени документа):

  1. Запросить у TSA фиктивный токен временной метки.
  2. Извлеките и проверьте цепочку доверия этого токена
  3. Добавьте ответы OSCP и CRL для сертификатов в цепочке в документ DSS.
  4. Теперь запросите вторую временную метку для документа (включая обновленный DSS) и используйте ее для временной метки PDF.
  5. Убедитесь, что две временные метки были подписаны одним и тем же сертификатом (в маловероятном случае, когда TSA использует разные сертификаты).

Извлечение сертификата подписи из токена tsa:

              IDigest messageDigest = tsaClient.GetMessageDigest();
        byte[] tsImprint = new byte[messageDigest.GetDigestSize()];
        messageDigest.DoFinal(tsImprint, 0);
        byte[] tsToken;
        try {
            tsToken = tsaClient.GetTimeStampToken(tsImprint);
        } catch(Exception e) {
            throw new GeneralSecurityException(e.Message);
        }
        Asn1Sequence asn1Seq = Asn1Sequence.GetInstance(tsToken);
        ContentInfo sigData = ContentInfo.GetInstance(asn1Seq);
        TimeStampToken token = new TimeStampToken(sigData);
        IX509Store tokenCerts = token.GetCertificates("COLLECTION");
        List<X509Certificate> signingCerts = new List<X509Certificate>();
        foreach(X509Certificate cert in tokenCerts.GetMatches(token.SignerID)) {
            signingCerts.Add(cert);
        }
        // now perform LTV steps for signingCerts[0] ...

Другие вопросы по тегам