Как правильно подписать PDF в двух шагах, используя ITEXT7 и внешнюю подпись?C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Как правильно подписать PDF в двух шагах, используя ITEXT7 и внешнюю подпись?

Сообщение Anonymous »

Мне нужно реализовать двухэтапный процесс подписания PDF, используя ITEXT в C#.
Поток выглядит следующим образом: < /p>

Подготовьте PDF для подписания-встройте пустое поле подписи, рассчитайте хэш и верните модифицированный документ и HASH (в базе 64). /> Внешняя компания (компания A) подписывает хэш и возвращает подпись.public PrepareDocumentSignResponseDto PrepareDocumentSign(byte[] documentBytes,
AlgorithmSignature algorithmSignature, byte[] certificateBytes)
{
ArgumentNullException.ThrowIfNull(documentBytes);
ArgumentNullException.ThrowIfNull(algorithmSignature);
ArgumentNullException.ThrowIfNull(certificateBytes);

// Step 1: Draw a rectangle for the signature

Rectangle signatureRectangle;
int signaturePageNumber;

using var readerStream = new MemoryStream(documentBytes);
using var outputStream = new MemoryStream();

using var reader = new PdfReader(readerStream);
using var writer = new PdfWriter(outputStream);
using (var pdfDoc = new PdfDocument(reader, writer))
{
signatureRectangle = pdfDoc.AddRectangleSignature();
var signaturePage = pdfDoc.GetLastPage();
signaturePageNumber = pdfDoc.GetPageNumber(signaturePage);

signaturePage.AddTitle(signatureRectangle);
signaturePage.AddCertificateInfo(signatureRectangle, certificateBytes);
}

var pdfBytes = outputStream.ToArray();

// Step 2: Add an empty signature

using var finalOutput = new MemoryStream();

var hashBytes = PdfSignatureHelper.AddEmptySignature(
pdfBytes,
finalOutput,
signatureRectangle,
signaturePageNumber,
algorithmSignature);

var finalPdfBytes = finalOutput.ToArray();

return new PrepareDocumentSignResponseDto(
Convert.ToBase64String(finalPdfBytes),
Convert.ToBase64String(hashBytes));
}

public static byte[] AddEmptySignature(byte[] documentBytes, Stream outputStream, Rectangle rectangle, int pageNumber, AlgorithmSignature algorithmSignature)
{
ArgumentNullException.ThrowIfNull(documentBytes);
ArgumentNullException.ThrowIfNull(outputStream);
ArgumentNullException.ThrowIfNull(rectangle);
ArgumentOutOfRangeException.ThrowIfNegative(pageNumber);

using var readerStream = new MemoryStream(documentBytes);
using var reader = new PdfReader(readerStream);

var signerProperties = new SignerProperties();

var fieldName = PdfConstants.SignatureName(documentBytes.SignaturesCount() + 1);

signerProperties.SetSignatureAppearance(new SignatureFieldAppearance(Guid.NewGuid().ToString()));
signerProperties.SetFieldName(fieldName);
signerProperties.SetPageRect(rectangle); // Устанавливает границы подписи
signerProperties.SetPageNumber(pageNumber);

var signer = new PdfSigner(reader, outputStream, new StampingProperties());

signer.SetSignerProperties(signerProperties);

var external = new PrepareSignatureContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached, algorithmSignature);

signer.SignExternalContainer(external, PdfConstants.MaxSignatureSize);

return external.GetHash();
}
< /code>
Пользовательский контейнер для подписи, используемый во время расчета хэша: < /p>
public sealed class PrepareSignatureContainer : IExternalSignatureContainer
{
private readonly PdfDictionary _sigDic = new();
private readonly AlgorithmSignature _algorithmSignature;
private byte[] _hash;

public PrepareSignatureContainer(PdfName filter, PdfName subFilter, AlgorithmSignature algorithmSignature)
{
_algorithmSignature = algorithmSignature;
_sigDic.Put(PdfName.Filter, filter);
_sigDic.Put(PdfName.SubFilter, subFilter);
}

public byte[] GetHash() => _hash;

///
/// This method is called by iText to "sign" the document.
/// In this implementation, we only compute the hash and return an empty byte array.
/// The actual signing is performed externally.
///
public byte[] Sign(Stream data)
{
_hash = new AlgorithmSignatureFactory()
.Create(_algorithmSignature)
.ComputeHash(data);
return [];
}

public void ModifySigningDictionary(PdfDictionary signDic)
{
signDic.PutAll(_sigDic);
}
}
< /code>
Затем я прикрепляю полученную подпись: < /p>
public AttachDocumentSignResponseDto AttachDocumentSign(byte[] documentBytes, byte[] signatureBytes)
{
ArgumentNullException.ThrowIfNull(documentBytes);
ArgumentNullException.ThrowIfNull(signatureBytes);

CheckSignature(signatureBytes);

using var readerStream = new MemoryStream(documentBytes);
using var outputStream = new MemoryStream();
using var pdfReader = new PdfReader(readerStream);

IExternalSignatureContainer external = new PredefinedExternalSignatureContainer(signatureBytes);

var fieldName = PdfConstants.SignatureName(documentBytes.SignaturesCount());

PdfSigner.SignDeferred(
pdfReader,
fieldName,
outputStream,
external);

var signedPdfBytes = outputStream.ToArray();

return new AttachDocumentSignResponseDto(Convert.ToBase64String(signedPdfBytes));
}
< /code>
и пользовательский контейнер для вставки предопределенной подписи: < /p>
public sealed class PredefinedExternalSignatureContainer : IExternalSignatureContainer
{
private readonly byte[] _signatureBytes;

///
/// Constructor to initialize the signature container.
///
///
Byte array of the digital signature.
public PredefinedExternalSignatureContainer(byte[] signatureBytes)
{
_signatureBytes = signatureBytes ?? throw new ArgumentNullException(nameof(signatureBytes));
}

///
/// Method to sign the data. Returns the precomputed signature.
///
/// The stream of data to be signed.
/// The digital signature as a byte array.
public byte[] Sign(Stream data)
{
return _signatureBytes; // Returns the predefined signature. Assumes the signature was generated externally.
}

///
/// Method to modify the signature dictionary in the PDF document.
///
/// The signature dictionary to modify.
public void ModifySigningDictionary(PdfDictionary signDic)
{
signDic.Put(PdfName.Filter, PdfName.Adobe_PPKLite);
signDic.Put(PdfName.SubFilter, PdfName.Adbe_pkcs7_detached);
}
}
< /code>
Все, кажется, работает, и подпись вводится без исключений. Но Adobe Acrobat Reader сообщает о подписи как недействительной.
Вот что показывает UI:

Перевод с перевода с экрана. />
Подпись недопустима. Документ был изменен или
с момента его подписания. Последняя проверка: 2025.04.11
12:58:57 +03'00 Поле: Signature_1 на стр. 2 < /p>
< /blockquote>

Подробнее здесь: https://stackoverflow.com/questions/795 ... -signature
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Подписать отдельную подпись, используя OpenSAML
    Anonymous » » в форуме JAVA
    0 Ответы
    19 Просмотры
    Последнее сообщение Anonymous
  • Как получить данные о шагах за предыдущие дни из HealthKit?
    Anonymous » » в форуме Android
    0 Ответы
    23 Просмотры
    Последнее сообщение Anonymous
  • Как получить данные о шагах за предыдущие дни из HealthKit?
    Anonymous » » в форуме IOS
    0 Ответы
    15 Просмотры
    Последнее сообщение Anonymous
  • Проблема с «То же самое?» значение неверно в шагах 15 и 16 задачи социалистического миллионера
    Anonymous » » в форуме Python
    0 Ответы
    12 Просмотры
    Последнее сообщение Anonymous
  • Цифровая подпись Itext7 не видна
    Anonymous » » в форуме C#
    0 Ответы
    24 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»