Получить цепочку подписи из CMSSignedData

Как я могу получить цепочку подписи от CMSSignedData (BouncyCastle), чтобы проверить ее в магазине цепочки подписей?

Certificate[] storeCertChain = store.getCertificateChain(alias)

Нет ли команды или чего-то подобного, я могу получить цепочку подписи данных? Или получить сертификат от него и там от цепочки подписи?


person nolags    schedule 17.05.2017    source источник


Ответы (1)


Цепочка сертификатов, используемых для подписи, может быть в CMSSignedData, но это не обязательно.

Согласно RFC 3852, CMS SignedData имеет следующая структура (описанная в разделе 5.1):

SignedData ::= SEQUENCE {
    version CMSVersion,
    digestAlgorithms DigestAlgorithmIdentifiers,
    encapContentInfo EncapsulatedContentInfo,
    certificates [0] IMPLICIT CertificateSet OPTIONAL,
    crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
    signerInfos SignerInfos }

Поле certificates описывается как:

сертификаты — это набор сертификатов. Предполагается, что набор сертификатов должен содержать пути сертификации от признанного «корня» или «центра сертификации верхнего уровня» ко всем подписавшим в поле signerInfos. Сертификатов может быть больше, чем необходимо, и сертификатов может быть достаточно, чтобы содержать пути сертификации от двух или более независимых центров сертификации верхнего уровня. Сертификатов также может быть меньше, чем необходимо, если предполагается, что у получателей есть альтернативные способы получения необходимых сертификатов (например, из предыдущего набора сертификатов). Сертификат подписывающей стороны МОЖЕТ быть включен.

Обратите внимание, что поле certificates является необязательным, и даже если оно присутствует, все его содержимое также является необязательным. Таким образом, это поле может содержать цепочку сертификатов, но это не гарантируется.

Если это поле присутствует, вы можете получить его с помощью BouncyCastle (я использую версию 1.56):

import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.util.Store;

CMSSignedData sigData = ...
Store store = sigData.getCertificates();

Когда сертификатов нет, я не уверен, возвращает ли getCertificates() null или пустой Store (думаю, это может варьироваться в зависимости от реализации).

Если Store не null, вы можете проверить наличие сертификата подписавшего:

import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;

SignerInformationStore signers = sigData.getSignerInfos();
Collection<SignerInformation> c = signers.getSigners();
for (SignerInformation signer : c) {
    // this collection will contain the signer certificate, if present
    Collection signerCol = store.getMatches(signer.getSID());
}

Коллекция signerCol будет содержать сертификат подписавшего, если он указан в поле certificates. Затем вы можете использовать его для проверки подписи, точно так же, как вы делали в своем другом вопросе.

Чтобы проверить, есть ли вся цепочка в структуре CMS, вы можете получить все сертификаты в Store и проверить, есть ли они там. Чтобы получить все внутри Store, вы можете использовать код, аналогичный используемому здесь:

Collection<X509CertificateHolder> allCerts = store.getMatches(null);

В используемой мной версии (BouncyCastle 1.56) передача null возвращает все сертификаты в хранилище. Затем вы можете проверить, находится ли цепочка внутри коллекции allCerts.

Если цепи нет, вам придется получить ее в другом месте.

  • если у вас есть сертификат подписавшего (конечного объекта), вы можете попробовать его, используя доступ к информации о полномочиях (отметьте этот ответ)
  • если это невозможно, вы должны загрузить цепочку или получить сертификаты с подписавшим
person Community    schedule 18.05.2017