How to delete a specific digital signature field?

Question:
How to completely remove a single Digital Signature field, while leaving other exiting Digital Signature fields alone.

Answer:

Note, if any of the signature, except perhaps the target one, are already signed, then this action will invalidate the other signed signature(s). If they other signatures are not signed, then this action should be fine.

This is a four step process.

  1. Find the field/annotation
  2. Remove the Widget annotation from the page, which is the visual appearance of the field.
  3. Remove the Field from the list of fields.
  4. Save the PDF

Find the field.
Assuming you have a name, you can do the following.

Field field = pdfdoc.GetField(fieldName);
Obj fieldObj = field.GetSDFObj();
Widget widget = new Widget(fieldObj);
if(field == null || !field.IsIndirect()) throw new Exception("Cannot delete field");
int fieldObjNum = fieldObj.GetObjNum();

Remove the widget.

// first check if we have valid page reference.
Page page = widget.GetPage();
int widgetIndex = -1;
if (page.IsValid()) {
  // double check back link is correct, often it is not.
  widgetIndex = GetIndexOfAnnotOnPage(page, fieldObjNum);
}
if (widgetIndex < 0) {
  // either there was no back link, or it was a bad one
  for (PageIterator itr = doc.GetPageIterator(); itr.HasNext(); itr.Next()) {
    widgetIndex = GetIndexOfAnnotOnPage(itr.Current(), fieldObjNum);
    if (widgetIndex >= 0) {
      page = itr.Current();
      break;
    }
  }
}
if (widgetIndex >= 0 && page.IsValid()) {
  page.AnnotRemove(widgetIndex); // if we don't get here, then there is no visual representation of the field
}

Remove the field

Obj formsObj = null;
Obj acroformsObj = pdfdoc.GetAcroForm();
if (acroformsObj != null && acroformsObj.IsDict()) {
  formsObj = acroformsObj.FindObj("Forms");
}
if (formsObj != null && formsObj.IsArray()) {
  for (int i = 0; i < formsObj.Size(); ++i) {
    Obj formObj = formsObj.GetAt(i);
    if (formObj.GetObjNum() == fieldObjNum) {
      formsObj.EraseAt(i);
      break;
    }
  }
}

Save to commit change

pdfdoc.Save(filePath, SDFDoc.SaveOptions.e_linearized);

Utility function

// return -1 on not found
int GetIndexOfAnnotOnPage(Page page, int objNum) {
  int num_annots = page.GetNumAnnots();
  for (int i = 0; i < num_annots; ++i) {
    Annot annot = page.GetAnnot(i);
    if (annot.GetSDFObj().GetObjNum() == objNum) return i;
  }
  return -1;
}