Wie kann man ein PDF in zwei Schritten mit iText7 und externer Signatur richtig unterschreiben?C#

Ein Treffpunkt für C#-Programmierer
Anonymous
 Wie kann man ein PDF in zwei Schritten mit iText7 und externer Signatur richtig unterschreiben?

Post by Anonymous »

Ich muss einen zweistufigen PDF-Signaturprozess unter Verwendung von iText in C#implementieren. /> Eine externe Firma (Firma A) signiert den Hash und gibt die Signatur zurück.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>
Benutzerdefinierte Signaturbehälter, die während der Hash -Berechnung verwendet werden: < /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>
Dann füge ich die empfangene Signatur mit: < /p>
beipublic 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>
und der benutzerdefinierte Container zum Einfügen der vordefinierten Signatur: < /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>
Alles scheint zu funktionieren, und die Signatur wird ohne Ausnahmen injiziert. Aber Adobe Acrobat Reader meldet die Signatur als ungültig. />
Die Signatur ist nicht gültig. Das Dokument wurde seit seiner Unterzeichnung modifiziert oder
beschädigt. Zuletzt überprüft: 2025.04.11
12:58:57 +03'00 Feld: Signature_1 auf Seite 2 < /p>
< /blockquote>
Hinweis: Ich verwende einen GOST für Hashing. Dann unterschreibe ich den Hash mit einem anderen GOST -Algorithmus und danach rufe ich die Anhangsmethode

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post