Цепочка сертификатов, используемых для подписи, может быть в 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