E-Sign: Validating Signature Hashes Generated from Vector Data in ASP.NET Core C#
Storing the raw data of the signature, including point positions, velocity, and acceleration, can help strengthen the evidence. By generating and storing a hash of the raw signature data in the encrypted and digitally signed document and in a database, signed documents can be compared and validated.

In addition to encrypting and digitally signing a PDF with an electronic certificate, storing the raw data of the signature, including point positions, velocity, and acceleration, can help strengthen the evidence. By generating and storing a hash of the raw signature data in the encrypted and digitally signed document and in a database, signed documents can be compared and validated.
Since version 32.0.2 of the Document Viewer, the SignatureData object contains the raw signature data. The SignaturePoint class stores the location of each captured signature point and a time stamp.
Learn More
During the e-signing process, the document is encrypted and digitally signed and is therefore tamper-proof. Additional features, such as storing the raw signature data, including point positions, velocity, and acceleration, can enhance the evidence.
Signature Acquisition
This example shows how to extract the signature lines from the returned signature data and store a hash of it as an attachment to the created PDF document.
The first step is to use the Document Viewer to capture a signature, which is then used to sign the document. To do this, click the Sign New Document button.
Generating the Hash
The ProcessSignature method creates the hash from the signature data. This data is then stored in a local json database file.
[HttpPost]
public IActionResult ProcessSignature([FromBody] TXTextControl.Web.MVC.DocumentViewer.Models.SignatureData data)
{
if (data == null)
{
return BadRequest();
}
string signatureDataJson = JsonConvert.SerializeObject(data.SignatureLines);
string hash = CreateHash(signatureDataJson);
Envelope envelope = new Envelope
{
DocumentId = data.UniqueId,
SignatureHash = hash,
SignatureData = signatureDataJson
};
AddEnvelope(envelope);
if (SaveSignedPDF(data, envelope))
{
return Ok(true);
}
else
{
return StatusCode(500);
}
}
The CreateHash method is the calculation of a SHA256 hash of the signature lines that have previously been serialized as JSON.
private string CreateHash(string json)
{
using (SHA256 sha256Hash = SHA256.Create())
{
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(json));
return BitConverter.ToString(bytes).Replace("-", "").ToLower();
}
}
Embedding Attachment
The SaveSignedPDF method creates an Embedded
private bool SaveSignedPDF(TXTextControl.Web.MVC.DocumentViewer.Models.SignatureData data, Envelope envelope)
{
try
{
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl())
{
tx.Create();
tx.Load(Convert.FromBase64String(data.SignedDocument.Document), TXTextControl.BinaryStreamType.InternalUnicodeFormat);
var embeddedFile = new EmbeddedFile($"tx-hash_{data.UniqueId}.txt", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(envelope)), null)
{
Relationship = "Data",
MIMEType = "application/json"
};
X509Certificate2 cert = new X509Certificate2("App_Data/textcontrolself.pfx", "123");
var saveSettings = new TXTextControl.SaveSettings
{
EmbeddedFiles = new EmbeddedFile[] { embeddedFile },
CreatorApplication = "TX Text Control Sample Application",
SignatureFields = new DigitalSignature[]
{
new TXTextControl.DigitalSignature(cert, null, "txsign")
}
};
var savePath = Path.Combine("App_Data/signed", $"{data.UniqueId}.pdf");
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
tx.Save(savePath, TXTextControl.StreamType.AdobePDF, saveSettings);
}
return true;
}
catch (Exception)
{
return false;
}
}
After the document is signed, it is listed in the summary table.
Now click on the Download button to download the PDF document that was generated. You can see the attached text file in the Attachments tab when you open it in Acrobat Reader.
If you open the attachment in a text editor, you will be able to see the json structure, including the hash value that was generated.
{
"DocumentId":"5df83af0-f456-4485-a29f-6290c523067b",
"SignatureHash":"7592d7e308a1aa3cf2c26f7226c572fc1c744a223a0c6eed0431312d807d23c0",
"SignatureData":"[[{\"X\":190.0,\"Y\":29.28125,\"CreationTimeStamp\":1698671635701},...]]"
}
Then click the Choose File button and select the file you downloaded. Confirm by clicking Validate Signature Hash. You should see the following page if the signature hash comparison was successful and the stored hashes match.
Extracting the Hash
The Validate method extracts the hash information from the PDF and compares the stored hash values from the document and the local database file.
public IActionResult Validate([FromForm] IFormFile file)
{
if (file == null)
{
return NotFound();
}
byte[] bPDF = GetBytesFromFormFile(file);
var uploadedEnvelope = ExtractEnvelopeFromPDF(bPDF);
if (uploadedEnvelope == null)
{
return NotFound();
}
var envelopes = LoadEnvelopesFromJson();
var envelope = envelopes.FirstOrDefault(e => e.DocumentId == uploadedEnvelope.DocumentId);
if (envelope != null && envelope.SignatureHash == uploadedEnvelope.SignatureHash)
{
return View(true);
}
return View(false);
}
The ExtractEnvelopeFromPDF method uses the Server
private Envelope ExtractEnvelopeFromPDF(byte[] document)
{
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl())
{
tx.Create();
var loadSettings = new TXTextControl.LoadSettings
{
EmbeddedFiles = new EmbeddedFile[] { },
};
tx.Load(document, TXTextControl.BinaryStreamType.AdobePDF, loadSettings);
var embeddedFile = loadSettings.EmbeddedFiles
.FirstOrDefault(ef => ef.FileName.StartsWith("tx-hash_"));
if (embeddedFile != null)
{
return JsonConvert.DeserializeObject<Envelope>(Encoding.UTF8.GetString((byte[])embeddedFile.Data));
}
}
return null;
}
Conclusion
The storage and comparison of signature raw data hash values is a powerful feature that can add an extra layer of security and trust to e-signature workflows.
You will be able to test the sample by downloading it from our GitHub repository.
Download and Fork This Sample on GitHub
We proudly host our sample code on github.com/TextControl.
Please fork and contribute.
Requirements for this sample
- TX Text Control .NET Server
- Visual Studio 2022
Related Posts
Exporting Password Protected Documents to PDF in .NET C#
This article shows how to export password protected documents to PDF in .NET C# using TX Text Control .NET Server. Existing password protected documents can be imported, modified and exported to…
How to Secure your PDF Documents with ASP.NET Core C#
TX Text Control not only provides a sophisticated way to create PDF documents, but also to secure those PDF documents to ensure confidentiality and integrity. This article discusses the various…
Mining PDFs with Regex in C#: Practical Patterns, Tips, and Ideas
Mining PDFs with Regex in C# can be a powerful technique for extracting information from documents. This article explores practical patterns, tips, and ideas for effectively using regular…
PDF Conversion in .NET: Convert DOCX, HTML and more with C#
PDF conversion in .NET is a standard requirement for generating invoices, templates, and accessible reports. This article provides an overview of PDF conversion capabilities using TX Text Control,…
Streamline Data Collection with Embedded Forms in C# .NET
Discover how to enhance your C# .NET applications by embedding forms for data collection. This article explores the benefits of using Text Control's ASP.NET and ASP.NET Core components to create…