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
Wie kann man ein PDF in zwei Schritten mit iText7 und externer Signatur richtig unterschreiben? ⇐ C#
-
- Similar Topics
- Replies
- Views
- Last post