Атрибут BouncyCastle messageDigest не прошел проверку - PullRequest
0 голосов
/ 24 августа 2018

У меня проблема с подписью / самой проверкой подписи CADES с использованием BouncyCastle 1.59 . Мне нужно добавить атрибут messageDigest, но когда я его добавил, моя программа не работает.

Вот мой код:

Signature signature = Signature.getInstance("SHA256withRSA", new BouncyCastleProvider());
byte[] test_data = "test".getBytes();
MessageDigest dig = MessageDigest.getInstance("SHA256", new BouncyCastleProvider());
byte[] digest = dig.digest(test_data);

byte[] privateKeyContent = archivePrivateKey.getBytes();
BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(privateKeyContent)));
Security.addProvider(new BouncyCastleProvider());
PEMParser pp = new PEMParser(br);
PEMKeyPair pemKeyPair = (PEMKeyPair) pp.readObject();
KeyPair kp = new JcaPEMKeyConverter().getKeyPair(pemKeyPair);
pp.close();

signature.initSign(kp.getPrivate());
signature.update(test_data);

byte[] certContent = archiveCertificateContent.getBytes();
PemFile pemFile = new PemFile(certContent);
X509CertificateHolder cert = new X509CertificateHolder(pemFile.getPemObject().getContent());
X509Certificate certificate = new JcaX509CertificateConverter().getCertificate(cert);

// Build CMS
List certList = new ArrayList();
CMSTypedData data = new CMSProcessableByteArray(signature.sign());
certList.add(certificate);
Store certs = new JcaCertStore(certList);


byte[] certHash = dig.digest(certificate.getEncoded());
AlgorithmIdentifier algId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256);
ESSCertIDv2 essCert = new ESSCertIDv2(algId, certHash);
SigningCertificateV2 scv2 = new SigningCertificateV2(new ESSCertIDv2[] { essCert });

ASN1EncodableVector signedAttributes = new ASN1EncodableVector();
signedAttributes.add(new Attribute(PKCSObjectIdentifiers.id_aa_signingCertificateV2, new DERSet(scv2)));
//signedAttributes.add(new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(digest))));
signedAttributes.add(new Attribute(CMSAttributes.contentType, new DERSet(PKCSObjectIdentifiers.data)));

AttributeTable signedAttributesTable = new AttributeTable(signedAttributes);
signedAttributesTable.toASN1EncodableVector();

CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
JcaContentSignerBuilder contentSigner = new JcaContentSignerBuilder("SHA256withRSA");
contentSigner.setProvider(BC_PROVIDER);
SignerInfoGeneratorBuilder signerInfoBuilder = new SignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC_PROVIDER).build());
signerInfoBuilder.setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(signedAttributesTable));

gen.addSignerInfoGenerator(signerInfoBuilder.build(contentSigner.build(kp.getPrivate()), cert));
gen.addCertificates(certs);
CMSSignedData signedData = gen.generate(data, true);

// Verify signature
Store store = signedData.getCertificates();
SignerInformationStore signers = signedData.getSignerInfos();
Collection c = signers.getSigners();
Iterator it = c.iterator();
while (it.hasNext()) {
  SignerInformation signer = (SignerInformation) it.next();
  Collection certCollection = store.getMatches(signer.getSID());
  Iterator certIt = certCollection.iterator();
  X509CertificateHolder certHolder = (X509CertificateHolder) certIt.next();
  X509Certificate certFromSignedData = new JcaX509CertificateConverter().setProvider(BC_PROVIDER).getCertificate(certHolder);
  if (signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC_PROVIDER).build(certFromSignedData))) {
    System.out.println("Signature verified");
  } else {
    System.out.println("Signature verification failed");
  }
}

Когда я раскомментирую строку 35: signedAttributes.add(new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(digest))));, я получаю ошибку:

org.bouncycastle.cms.CMSSignerDigestMismatchException: значение атрибута дайджеста сообщения не соответствует вычисленному значению

Я пробовал много вариантов, конфигураций, но проблема все еще остается. Любая помощь будет очень полезна. Спасибо

1 Ответ

0 голосов
/ 31 августа 2018

Я сам не пробовал ваш код, но думаю, что проблема в дайджесте сообщений, который вы добавляете в качестве атрибута MessageDigest, а не в том, что вы действительно добавляете в SignedData.Я вижу, что вы сначала подписываете данные, используя JCA.

Signature signature = Signature.getInstance("SHA256withRSA", new BouncyCastleProvider());
byte[] test_data = "test".getBytes();
    signature.initSign(kp.getPrivate());
signature.update(test_data);
CMSTypedData data = new CMSProcessableByteArray(signature.sign());
...
CMSSignedData signedData = gen.generate(data, true);

Здесь вы помещаете подпись (а не данные, что странно) для генерации CMSSignedData.Таким образом, для contentSigner ваша подпись - это фактические данные , которые должны быть подписаны.Однако в атрибуте MessageDigest вы помещаете дайджест фактических данных.Это, скорее всего, вызывает проблему.

Теперь перейдем к более важному вопросу.Почему вы подписываете данные, используя вышеуказанный код?Это кажется неправильным для меня и, вероятно, не то, что вы хотите.Если ваша цель состоит в том, чтобы сгенерировать подписанные данные CMS для «тестовых» данных, вы должны использовать их непосредственно в signatureDataGenerator, и это позаботится о подписывающей части.

Пожалуйста, просмотрите RFC если вы еще этого не сделали.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...