Bouncycastle и атрибут времени подписания S/MIME

Я новичок в подписании/сертификате, но после проверки Google + SO я не могу найти ответ. У меня есть базовый код для создания подписи файла для отдельной подписи PKCS #7, и пока все хорошо... Клиент, который проверяет подпись, доволен сгенерированной подписью. Теперь у меня есть новое требование, чтобы включить дату/время, когда исходный файл был подписан с использованием атрибута времени подписи S/MIME.

Мой код до сих пор для работы с ним:

    final Attribute signingAttribute = new Attribute(CMSAttributes.signingTime, new DERSet(new DERUTCTime(new Date()))); 
    signedAttributes.add(new Attribute(CMSAttributes.contentType, new DERSet(new ASN1ObjectIdentifier("1.2.840.113549.1.7.1"))));
    signedAttributes.add(new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(hash))));
    signedAttributes.add(signingAttribute);
    final AttributeTable signedAttributesTable = new AttributeTable(signedAttributes);
    final DefaultSignedAttributeTableGenerator signedAttributeGenerator = new DefaultSignedAttributeTableGenerator(signedAttributesTable);
    // now proceed for the signing process with BouncyCastle
    final JcaSimpleSignerInfoGeneratorBuilder builder = new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setDirectSignature(true);
    builder.setSignedAttributeGenerator(signedAttributeGenerator);
    final SignerInfoGenerator signerGenerator = builder.build("SHA1withRSA", key, cert);

    final CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
    ...

Затем код после этого тот же, что и для создания подписи... Но не работает.

Одна вещь, которой я на самом деле не являюсь, касается хэша для messageDigest:

    signedAttributes.add(new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(hash))));

Я получил хэш, сгенерированный как:

    MessageDigest md = MessageDigest.getInstance("SHA1", "BC");
    md.update(fileToSign.getBytes("UTF-8"));
    hash = md.digest();        

но я совершенно не уверен, что это правильный способ получить хэш? И общий способ получения сгенерированного атрибута времени подписи S/MIME...

Любые подсказки или общее объяснение того, что я пропустил, будут приветствоваться.


person Yoda    schedule 08.08.2013    source источник


Ответы (1)


Хорошо, после того, как вы покопаетесь в коде, решение будет простым... Во-первых, код можно упростить, и проблема вовсе не связана с хэшем.

Для получения времени подписания у нас может быть только один атрибут:

final ASN1EncodableVector signedAttributes = new ASN1EncodableVector();
final Attribute signingAttribute = new Attribute(CMSAttributes.signingTime, new DERSet(new DERUTCTime(new Date()))); 
signedAttributes.add(signingAttribute);
// Create the signing table
final AttributeTable signedAttributesTable = new AttributeTable(signedAttributes);
// Create the table table generator that will added to the Signer builder
final DefaultSignedAttributeTableGenerator signedAttributeGenerator = new DefaultSignedAttributeTableGenerator(signedAttributesTable);


final JcaSimpleSignerInfoGeneratorBuilder builder = new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BouncyCastleProvider.PROVIDER_NAME);
builder.setSignedAttributeGenerator(signedAttributeGenerator); 
// ****** DO NOT call: setDirectSignature(true); *****
final SignerInfoGenerator signerGenerator = builder.build("SHA1withRSA", key, cert);

Критическая часть здесь находится в комментируемой части:

// ****** DO NOT call: setDirectSignature(true); *****

При вызове setDirectSignature(true) это в основном отменяет всю работу, проделанную ранее. Согласно документации:

Если переданный флаг имеет значение true, подпись подписывающей стороны будет основана на данных, а не на наборе подписанных атрибутов, и подписанные атрибуты не будут включены.

Вот и все... с этого момента сгенерированная подпись будет иметь время подписания...

Я проверил с моим новым клиентом, и предыдущая ошибка/журнал, который я получал, исчезла

person Yoda    schedule 08.08.2013
comment
Здравствуйте, Йода, я предполагаю, что вам удалось использовать PKCS # 7 (только с открытым ключом) для подписи / шифрования сообщения SMIME, которое отправляется тому, кто владеет закрытым ключом. Я застрял в этой проблеме, и, может быть, вы можете прислать мне выдержку из своего кода, делающего это? Спасибо за вашу помощь ! - person Julien Gecko; 16.08.2017