# Multiple Signatures

> Collect signatures from several people in a WPF application and sign all signature fields in one save, with separate certificates and optional timestamps.

- **Product:** TX Text Control .NET for WPF
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for WPF > Digital Signatures > Multiple Signatures
- **2754 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/multiple/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/multiple/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/multiple/llms-full.txt

---

An agreement between a discloser and a vendor needs two signatures that can be told apart and checked one by one. In TX Text Control, each of them is a signature field with its own name, and each field is signed with its own `DigitalSignature`: its own certificate, its own timestamp, its own entry in the signature panel of a PDF reader. All of them are applied together, in the save that turns the finished document into a PDF.

The fields themselves, with their images and signer data, are described in [Signature Fields and Signature Appearance](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/signature-fields/llms-full.txt). The examples use an agreement whose signature fields are named `sign_discloser`, `sign_vendor` and `init_vendor`; users insert such fields as [Signature Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/signature-fields/llms-full.txt) in Document Editor describes.

### How Several Signatures Are Written

- **An array of signatures.** [SaveSettings.SignatureFields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/savesettings/signaturefields-property/llms-full.txt) takes one [DigitalSignature](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/digitalsignature/llms-full.txt) per field. Each has its own certificate and time server URL, so one field can carry a trusted timestamp and another the computer's time.
- **A single save.** TX Text Control creates signatures only when it saves a document as PDF. A PDF that it loads becomes an editable document, as [PDF Import and Its Limitations](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/pdf/import/llms-full.txt) explains, so signatures aren't added to an existing PDF one by one. The document collects the signature images of its signers in an editable format, and the last save signs all fields.
- **Separate entries.** PDF readers list every signature with the name of its field and a validation status of its own.
- **Fields, not the document signature.** `SaveSettings.DigitalSignature` signs once, with one certificate. Several signatures need signature fields.

### Sign Several Fields in One Save

The following handler signs the agreement in the editor with two certificates. The discloser's field gets a trusted timestamp; the vendor's signature and initials get the date and time of the computer. It needs `using System.Security.Cryptography.X509Certificates;`, `using System.Windows;` and `using TXTextControl;` in *MainWindow.xaml.cs*.

```csharp
private void signAgreementButton_Click(object sender, RoutedEventArgs e)
{
    // The discloser's and the vendor's certificates
    X509Certificate2 discloserCertificate = X509CertificateLoader.LoadPkcs12FromFile(
        "certificate.pfx", "123", X509KeyStorageFlags.Exportable);
    X509Certificate2 vendorCertificate = X509CertificateLoader.LoadPkcs12FromFile(
        "vendor.pfx", "123", X509KeyStorageFlags.Exportable);

    string[] names = { "sign_discloser", "sign_vendor", "init_vendor" };

    foreach (string name in names)
    {
        SignatureField field = textControl1.SignatureFields.GetItem(name);

        if (field == null)
        {
            MessageBox.Show(this, $"The document has no signature field named {name}.");
            return;
        }

        // The image shown in the field (filter index 4 is PNG)
        field.Image = new SignatureImage($"{name}.png", 4);
    }

    SaveSettings saveSettings = new SaveSettings()
    {
        SignatureFields = new DigitalSignature[]
        {
            // With a trusted timestamp
            new DigitalSignature(discloserCertificate, "http://timestamp.digicert.com", "sign_discloser"),

            // With the date and time of this computer
            new DigitalSignature(vendorCertificate, "", "sign_vendor"),
            new DigitalSignature(vendorCertificate, "", "init_vendor")
        }
    };

    textControl1.Save("nda-signed.pdf", StreamType.AdobePDFA, saveSettings);
}
```

The code works as follows:

- *vendor.pfx* is a second test certificate, made the same way as *certificate.pfx* in [Create a Self-Signed Certificate for Testing](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/pdf/sign/#create-a-self-signed-certificate-for-testing). The computer that signs needs the private key of every certificate it uses.
- [SignatureFieldCollection.GetItem](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signaturefieldcollection/getitem-method/llms-full.txt) returns `null` for a name the document doesn't contain, so the handler stops before it saves an incomplete agreement. [SignatureField.Image](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signaturefield/image-property/llms-full.txt) sets the image of each field from a PNG file named after it.
- Each `DigitalSignature` names its field in the third parameter and takes a time server URL or an empty string in the second.
- The `Save` call creates one PDF/A document with three signatures.

`X509CertificateLoader` needs .NET 9 or higher. The constructor to use with .NET 8 and the .NET Framework is shown in [Load the Certificate From a PFX File](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/certificates/#load-the-certificate-from-a-pfx-file).

### Collect Signatures From Several People

When the parties sign one after the other, each with the same WPF application on their own computer, the document travels in the TX Text Control format until the organization certifies it:

1. **Prepare the document** with one named field and the signer data per signer, and save it in the TX Text Control format, for example as *nda.tx*.
2. **Let each signer add their signature.** The signer opens the document, puts the image of their signature into their field, as [Add a Signature Image](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/signature-fields/#add-a-signature-image) shows, and saves the document for the next signer:

```csharp
private void saveForNextSignerButton_Click(object sender, RoutedEventArgs e)
{
    // Keep the signatures of this signer in the TX Text Control format
    textControl1.Save("nda.tx", StreamType.InternalUnicodeFormat);
}
```

1. **Certify the document** once every field has its image, by signing all fields in one save.

The handler for the last step signs every named field with the organization's certificate and a trusted timestamp. While a field has no image, it names the missing fields instead of creating the PDF:

```csharp
private void certifyButton_Click(object sender, RoutedEventArgs e)
{
    X509Certificate2 certificate = X509CertificateLoader.LoadPkcs12FromFile(
        "certificate.pfx", "123", X509KeyStorageFlags.Exportable);

    List<string> missing = new List<string>();
    List<DigitalSignature> signatures = new List<DigitalSignature>();

    foreach (SignatureField field in textControl1.SignatureFields)
    {
        if (string.IsNullOrEmpty(field.Name))
        {
            continue;
        }

        // A field without an image hasn't been signed by its signer yet
        if (field.Image == null)
        {
            missing.Add(field.Name);
            continue;
        }

        signatures.Add(new DigitalSignature(certificate, "http://timestamp.digicert.com", field.Name));
    }

    if (missing.Count > 0)
    {
        MessageBox.Show(this, "Not signed yet: " + string.Join(", ", missing));
        return;
    }

    SaveSettings saveSettings = new SaveSettings()
    {
        SignatureFields = signatures.ToArray()
    };

    textControl1.Save("nda-signed.pdf", StreamType.AdobePDFA, saveSettings);
}
```

The code works as follows:

- `Image` is `null` for a field without a signature image, so the loop knows which signers are still missing. `List<T>` needs `using System.Collections.Generic;`.
- Every complete field gets a `DigitalSignature` with the organization's certificate. If each signer's certificate is available on the certifying computer, pass that certificate for their field instead, as in the previous section.
- Only a complete document becomes a PDF/A document. Until then it stays in the TX Text Control format, where it can still be changed.

Between two signers, the images in the fields prove nothing: until the certificates are applied, anyone who can open and save *nda.tx* can change them. Store the file where only the signers can change it.

### Check Documents With Several Signatures

In Adobe Acrobat Reader, the **Signatures** panel shows each signature of the PDF with the name of its field, and a click on a signed field opens its validation status. How field signatures and a document signature look in the panel is compared in the blog article [Understanding the Differences: Signing a PDF Document vs. Signing Signature Fields in a PDF in C#](https://www.textcontrol.com/blog/2024/10/08/signing-a-pdf-document-vs-signing-signature-fields-in-a-pdf-in-csharp/).

### Next Steps

- [Signature Fields and Signature Appearance](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/signature-fields/llms-full.txt): the images and signer data of the fields.
- [Certificates](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/certificates/llms-full.txt): let each signer choose a certificate.
- [Timestamp Configuration](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/timestamps/llms-full.txt): trusted timestamps for the signatures.

---

## Nearby

- **Previous:** [Signature Fields and Signature Appearance](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/signature-fields/llms-full.txt)
- **Next:** [Timestamp Configuration](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/timestamps/llms-full.txt)
