Nano Hash - криптовалюты, майнинг, программирование

Невозможно проверить цифровую подпись с помощью Apache PDFBOX

Я новичок в использовании цифровых подписей. В одном из проектов мы используем Apache PdfBox для обработки PDF-файлов с цифровой подписью. Хотя мы можем протестировать все функции, проверка подписанных файлов PDF - это то, что мы не можем взломать. Мы используем BouncyCastle в качестве провайдера. Ниже приведен код:

// Получить цифровую подпись и подписанный контент из файла pdf

byte[] signatureAsBytes = pdsignature.getContents(new FileInputStream(this.INPUT_FILE));
byte[] signedContentAsBytes = pdsignature.getSignedContent(new FileInputStream(this.INPUT_FILE));

// Проверка цифровой подписи

Security.addProvider(new BouncyCastleProvider());
Signature signer = Signature.getInstance("RSA","BC");

//Get PublicKey from p7b file
X509Certificate cert509=null;
File file = new File("C:\\certificate_file.p7b");
FileInputStream fis = new FileInputStream(file);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Collection c = cf.generateCertificates(fis);
Iterator it = c.iterator();
PublicKey pubkey;

while (it.hasNext()) 
{
   cert509 = (X509Certificate) it.next();
   pubkey = cert509.getPublicKey();
}

boolean VERIFIED=false;
Security.addProvider(new BouncyCastleProvider());
Signature signer = Signature.getInstance("RSA","BC");
PublicKey key=this.getPublicKey(false);
signer.initVerify(key);

List<PDSignature> allsigs = this.PDFDOC.getSignatureDictionaries();
Iterator<PDSignature> i = allsigs.iterator();

while(i.hasNext())
{
        PDSignature sig = (PDSignature) i.next();
        byte[] signatureAsBytes = sig.getContents(new FileInputStream(this.INPUT_FILE));
        byte[] signedContentAsBytes = sig.getSignedContent(new FileInputStream(this.INPUT_FILE));
        signer.update(signedContentAsBytes);
        VERIFIED=signer.verify(signatureAsBytes);
}

System.out.println("Verified="+VERIFIED);

Ниже приведены соответствующие выдержки из сертификата в формате p7b - я использую BouncyCastle в качестве поставщика безопасности:

  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
  Key:  Sun RSA public key, 2048 bits
  Validity: [From: Tue Aug 06 12:26:47 IST 2013,
  To: Wed Aug 05 12:26:47 IST 2015]
  Algorithm: [SHA256withRSA]

С приведенным выше кодом я всегда получаю ответ «ложно». Я не знаю, как решить эту проблему. Пожалуйста помоги


  • Насколько я понимаю, для сравнения понадобится копия неподписанной версии pdf файла. Как я могу извлечь оригинальную копию PDF-файла из подписанной копии? Любая помощь будет оценена по достоинству 21.09.2014
  • Как я могу извлечь оригинальную копию pdf-файла из подписанной копии? - для этого нужен pdsignature.getSignedContent. 22.09.2014
  • pdsignature.getSignedContent возвращает исходный контент - это я тоже понимаю. Однако проверка никогда не возвращает истину. Как я уже сказал ранее, я новичок в цифровой подписи, поэтому не могу решить эту проблему. 22.09.2014
  • Беглый взгляд на ваш код показывает, что он полностью игнорирует тип встроенной подписи PDF, adbe.x509.rsa_sha1, adbe.pkcs7.detached, adbe.pkcs7 .sha1, ETSI.CAdES и ETSI.RFC3161. Нужно ли проверять только один вид (если да, то какой)? 22.09.2014
  • Посоветуйте, пожалуйста, какой выбор правильный. Входной файл - это подписанный PDF-файл, используемый алгоритм - SHA256withRSA. 22.09.2014
  • Входной файл представляет собой подписанный PDF-файл, а используемый алгоритм - SHA256withRSA - это было ясно из вашего вопроса, но интегрированный тип подписи PDF все еще может быть любым из 5 вариантов выше. Если вы не знаете, поделитесь этим PDF-файлом для ознакомления. 22.09.2014
  • @Ranjan, ты решил это? Удалось ли проверять подписи с помощью pdfbox? 01.11.2016

Ответы:


1

Ваша основная проблема заключается в том, что существует несколько типов подписей PDF, различающихся форматом контейнера подписи и тем, что на самом деле является подписанными байтами. Ваш BC-код, с другой стороны, может проверять просто последовательности байтов голой подписи, которые содержатся в вышеупомянутых контейнерах подписи.

Типы совместимых подписей

Как уже сказано в заголовке, следующий список содержит более или менее строго определенные «взаимодействующие типы подписей». В спецификации PDF указан способ также включают полностью настраиваемые схемы подписи. Но давайте предположим, что мы находимся во взаимодействующей ситуации. Коллекция типов сигнатур сгорает до:

  • adbe.x509.rsa_sha1, определенный в ISO 32000-1 раздел 12.8.3.2 Подписи PKCS # 1; значение подписи Contents содержит объект двоичных данных PKCS # 1 в кодировке DER; этот объект данных представляет собой довольно простую подпись, в случае RSA - зашифрованную структуру, содержащую дополненный хэш документа и алгоритм хеширования.

  • adbe.pkcs7.sha1, определенный в ISO 32000-1 раздел 12.8.3.3 Подписи PKCS # 7; значение сигнатуры Contents содержит объект двоичных данных PKCS # 7 в кодировке DER; этот объект данных представляет собой большой объект-контейнер, который также может содержать метаинформацию, например он может содержать сертификаты для построения цепочек сертификатов, информацию об отзыве для проверок отзыва сертификатов, цифровые метки времени для фиксации времени подписи, ... Дайджест SHA1 диапазона байтов документа должен быть инкапсулирован в поле PKCS # 7 SignedData с ContentInfo типа Data. Дайджест этих SignedData должен быть включен как обычный дайджест PKCS # 7.

  • adbe.pkcs7.detached, определенный в ISO 32000-1 раздел 12.8.3.3 Подписи PKCS # 7; значение подписи Contents содержит объект двоичных данных PKCS # 7 в кодировке DER, см. выше. Исходный подписанный дайджест сообщения в байтовом диапазоне документа должен быть включен как обычное поле PKCS # 7 SignedData. Никакие данные не должны инкапсулироваться в поле SignedData PKCS # 7.

  • ETSI.CAdES.detached, определенный в ETSI TS 102 778-3 и будет интегрирован в ISO 32000-2; значение подписи Contents содержит закодированный в DER объект SignedData, как указано в CMS; Контейнеры сигнатур CMS являются близкими родственниками контейнеров сигнатур PKCS # 7, см. Выше. По сути, это другой профиль adbe.pkcs7.detached с более строгим определением.

  • ETSI.RFC3161, определенный в ETSI TS 102 778-4 и будет интегрирован в ISO 32000-2; значение подписи Contents содержит TimeStampToken, как указано в RFC 3161; токены отметок времени снова близки к контейнерам подписей PKCS # 7, см. выше, но они содержат специальную подструктуру данных, содержащую хэш документа, время создания отметки и информацию о выдающем сервере времени.

Я бы предложил изучить спецификации, которые я назвал, и документы, на которые есть ссылки, в основном RFC. Основываясь на этих знаниях, вы можете легко найти подходящие классы BouncyCastle для анализа различных сигнатур содержимого.

22.09.2014
  • Вы должны опубликовать этот ответ на другие вопросы. Это очень полезно для тех, кто интересуется внутренним устройством цифровой подписи PDF. 26.05.2017

  • 2

    Рабочий пример проверки adbe.pkcs7.detached подписей PDF (наиболее распространенных подписей PDF) с помощью Apache PDFBox 1.8.16 и Bouncy Castle 1.44:

    import org.apache.pdfbox.pdmodel.PDDocument;
    import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
    import org.bouncycastle.cms.CMSProcessable;
    import org.bouncycastle.cms.CMSProcessableByteArray;
    import org.bouncycastle.cms.CMSSignedData;
    import org.bouncycastle.cms.SignerInformation;
    import org.bouncycastle.cms.SignerInformationStore;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.security.cert.CertStore;
    import java.security.cert.X509Certificate;
    import java.util.Collection;
    import java.util.Iterator;
    import java.util.List;
    
    public class PDFBoxValidateSignature {
        public static void main(String[] args) throws Exception {
            File signedFile = new File("sample-signed.pdf");
            // We load the signed document.
            PDDocument document = PDDocument.load(signedFile);
            List<PDSignature> signatureDictionaries = document.getSignatureDictionaries();
            // Then we validate signatures one at the time.
            for (PDSignature signatureDictionary : signatureDictionaries) {
                // NOTE that this code currently supports only "adbe.pkcs7.detached", the most common signature /SubFilter anyway.
                byte[] signatureContent = signatureDictionary.getContents(new FileInputStream(signedFile));
                byte[] signedContent = signatureDictionary.getSignedContent(new FileInputStream(signedFile));
                // Now we construct a PKCS #7 or CMS.
                CMSProcessable cmsProcessableInputStream = new CMSProcessableByteArray(signedContent);
                CMSSignedData cmsSignedData = new CMSSignedData(cmsProcessableInputStream, signatureContent);
                SignerInformationStore signerInformationStore = cmsSignedData.getSignerInfos();
                Collection signers = signerInformationStore.getSigners();
                CertStore certs = cmsSignedData.getCertificatesAndCRLs("Collection", (String) null);
                Iterator signersIterator = signers.iterator();
                while (signersIterator.hasNext()) {
                    SignerInformation signerInformation = (SignerInformation) signersIterator.next();
                    Collection certificates = certs.getCertificates(signerInformation.getSID());
                    Iterator certIt = certificates.iterator();
                    X509Certificate signerCertificate = (X509Certificate) certIt.next();
                    // And here we validate the document signature.
                    if (signerInformation.verify(signerCertificate.getPublicKey(), (String) null)) {
                        System.out.println("PDF signature verification is correct.");
                        // IMPORTANT: Note that you should usually validate the signing certificate in this phase, e.g. trust, validity, revocation, etc. See http://www.nakov.com/blog/2009/12/01/x509-certificate-validation-in-java-build-and-verify-chain-and-verify-clr-with-bouncy-castle/.
                    } else {
                        System.out.println("PDF signature verification failed.");
                    }
                }
            }
        }
    }
    

    Не уверен, что есть официальный пример для этого, я проверил официальные примеры для PDFBox 1.8.4 и ничего не нашел.

    21.07.2017
  • Не могли бы вы включить импорт всех этих классов, на которые вы ссылаетесь, не из стандартной библиотеки? 01.07.2020
  • @ CarlesBarrobés, готово. 12.12.2020
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..