получить файл pkcs7 из PDF и подписать его - PullRequest
0 голосов
/ 11 июня 2018

У меня есть подписанный файл PDF и файл .p7s.Мне нужно извлечь .p7s из PDF и подписать PDF (создание других .p7s).После того, как мне нужно снова вставить p7s в файл PDF.Я получаю эту ошибку при попытке получить p7s из PDF: ExceptionConverter: java.security.SignatureException: объект не инициализирован для подписания Мой код:

BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);

PdfReader pdfReader = new 
PdfReader(Files.readAllBytes(inputFile.toPath()));

AcroFields acroFields = pdfReader.getAcroFields();          
List<String> signatures = acroFields.getSignatureNames();

for (String name : signatures) {
   PdfPKCS7 pdfPkcs7 = acroFields.verifySignature(name, "BC");
   Files.write(Paths.get("~/TEST/itext/"+ name +".p7s"), 
   pdfPkcs7.getEncodedPKCS7());//ERROR HERE!
}

1 Ответ

0 голосов
/ 12 июня 2018

В теории

Вы хотите совместно подписать PDF (встречный знак? Параллельный знак?) Путем извлечения встроенного контейнера подписи CMS из PDF, добавив свою подпись вэто и повторное встраивание расширенного контейнера.

Это неправильный подход, подпись PDF предназначена для того, чтобы содержать одну подпись только для каждого поля подписи PDF, а контейнер подписи CMS, о котором мы говорим по существу, является значением такогополе, поэтому каждый встроенный контейнер подписи должен содержать ровно одну подпись.

Строго говоря, спецификация PDF позволяет использовать произвольные пользовательские схемы подписи, ограничены только «совместимые подписи».Таким образом, ваши контейнеры для подписи с несколькими подписями могут считаться действительными PDF, а не просто «подписанными с возможностью взаимодействия», то есть вы не должны ожидать, что какое-либо другое программное обеспечение будет интерпретировать подпись, как вы.В частности, Adobe Acrobat Reader распознает и отображает только одну из этих подписей.

(Действительно, некоторые крупные поставщики решений для подписи имеют встроенные контейнеры CMS с несколькими сигнатурами в PDF-файлах. Например, в настоящее время у меня естьиметь дело с подписями, сгенерированными таким поставщиком, который встраивает произвольные контейнеры для подписи CAdES-A (в частности, некоторые с несколькими подписавшими) в PDF и вызывает этот формат подписи PDF / CAdES-A, и теперь я должен объяснить своим клиентам, что ихподписи - это подписи в формате PDF, но они не совместимы, хотя это имя PDF / CAdES-A звучит как какой-то потрясающий стандарт ...)

Несколько подписей в PDF для совместимости должны применяться последовательно, как показано вэтот эскиз:

Некоторые фоны и ссылки на дополнительную информацию, ср. этот ответ .

На практике

Ваш код выглядит как код iText 5.5.x, в частности еще не код iText 7.x.В этом случае вы можете использовать код из Цифровой подписи для документов PDF Белая книга Бруно Лоуги как есть.

Очень простой пример:

public void sign(String src, String dest, Certificate[] chain, PrivateKey pk, String digestAlgorithm,
        String provider, CryptoStandard subfilter, String reason, String location)
        throws GeneralSecurityException, IOException, DocumentException {
    // Creating the reader and the stamper
    PdfReader reader = new PdfReader(src);
    FileOutputStream os = new FileOutputStream(dest);
    PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
    // Creating the appearance
    PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
    appearance.setReason(reason);
    appearance.setLocation(location);
    appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
    // Creating the signature
    ExternalDigest digest = new BouncyCastleDigest();
    ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, provider);
    MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, subfilter);
}

(пример кода 2.1: «Hello World» подписания с iText)

Поскольку в вашем случае использования необходимо подписать уже подписанный документ, вам просто нужно изменить PdfStamper.createSignature строка до

PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', true);

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

...