Ваш исходный код и пример подписи
Для начала расшифровка байтов подписи с помощью открытого ключа вашего сертификата приводит к чему-то, что явно не дополнено ни PKCS1-v1_5, ни EMSA-PSS.Таким образом, ваша смарт-карта либо не подписывает, используя закрытый ключ, связанный с этим сертификатом C=TR,SERIALNUMBER=90000000684,CN=DENİZ KASAR
, либо возвращает результат, который не является массивом байтов простой подписи для подписи RSASSA-PKCS1-v1_5 или RSASSA-PSS для ввода хеш-кода.значение.
Возможно, на вашей карте несколько закрытых ключей для разных сертификатов, и вы указали неправильный адрес.Вероятно, есть другая проблема.
Кроме того, вы вызываете getAuthenticatedAttributeBytes
с этими параметрами
byte[] signatureHash = signature.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);
, затем сохраняете hash
в локальной переменной _hash
, но, наконец,Вызовите GetEncodedPKCS7
с этими параметрами
byte[] encodedSignature = _signature.GetEncodedPKCS7(_signatureHash, null, null, null, CryptoStandard.CMS);
Это выглядит неверно, параметры этих вызовов (кроме клиента TSA), как ожидается, будут совпадать, вы должны также использовать _hash
здесь.
Ваш последний пример подписи
В комментарии вы подтвердили, что ваша смарт-карта имеет два сертификата.Очевидно, в вашем более новом коде вы также успешно обратились к приложению для подписи сертификата, которым вы хотите подписать, в качестве байтов подписи после того, как расшифровка RSA заканчивается 0xbc
, который является индикатором для подписей RSASSA-PSS.
Это такжеОднако есть и недостаток: API подписи iText 5.x не был реализован с учетом RSASSA-PSS, и, в частности, класс PdfPKCS7
не может правильно создавать контейнеры CMS из сигнатур RSASSA-PSS.
Это не такЭто означает, однако, что вы не можете использовать iText для подписи с помощью своей карты, вам просто нужно реализовать больше в своем собственном коде, в частности, вы должны собрать весь контейнер для подписи.
Для этого вы используете это MakeSignature
helper
/**
* Sign the document using an external container, usually a PKCS7. The signature is fully composed
* externally, iText will just put the container inside the document.
* @param sap the PdfSignatureAppearance
* @param externalSignatureContainer the interface providing the actual signing
* @param estimatedSize the reserved size for the signature
* @throws GeneralSecurityException
* @throws IOException
* @throws DocumentException
*/
public static void SignExternalContainer(PdfSignatureAppearance sap, IExternalSignatureContainer externalSignatureContainer, int estimatedSize)
и просто нужно реализовать IExternalSignatureContainer
для построения и возврата контейнера сигнатур CMS в его методе Sign
, который подписывает данные из данного потока.
Youможет создать этот контейнер CMS, используя классы BouncyCastle или, возможно, даже классы Microsoft.К сожалению, тем не менее, я в основном занимаюсь практической подписью на Java, а не на .Net, поэтому я не могу с этим ничего поделать.
В случае подписей RSASSA-PKCS1-v1_5
Альтернативным подходом было бы проверить, можете ли вы указать своей смарт-карте генерировать подписи RSASSA-PKCS1-v1_5 вместо этого, поскольку это позволит вам использовать iText для генерации контейнера CMS.Я бы не рекомендовал это, поскольку RSASSA-PKCS1-v1_5 более открыт для атак, чем RSASSA-PSS.
В комментарии вы специально задали вопрос об этом случае.В этом случае я бы предложил вам значительно изменить код подписи.В настоящее время он использует сочетание старых более низкоуровневых и новых высокоуровневых API-интерфейсов для подписи iText.Вам следует использовать только новый API.
В этом случае код подписи будет сокращен до этого ключевого кода
using (PdfReader reader = new PdfReader(SRC))
using (FileStream os = new FileStream(DEST, FileMode.Create))
{
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = "MyRes";
appearance.Location = "MyLoc";
appearance.SetVisibleSignature(new Rectangle(36, 748, 250, 400), 1, "SIG");
// Creating the signature
CustomExternalSignature pks = new CustomExternalSignature();
MakeSignature.SignDetached(appearance, pks, pks.GetChain(), null, null, null, 0, CryptoStandard.CMS);
}
в сочетании с классом помощника CustomExternalSignature
, объединяющим код вашего устройства:
public class CustomExternalSignature : IExternalSignature
{
public ICollection<X509Certificate> GetChain()
{
[essentially your GetChain method, but return the List as is, don't make it an array]]
}
public string GetEncryptionAlgorithm()
{
return "RSA";
}
public string GetHashAlgorithm()
{
return "SHA256";
}
public byte[] Sign(byte[] message)
{
[your code to call the smart card function to sign the message using RSASSA-PKCS1-v1_5]
[you might or might not have to hash the message first, I don't know that smart card API you use]
}
}