DEV Community

Cover image for 3 Easy Steps to Digitally Sign PDFs in Your Flutter App
Jollen Moyani for Syncfusion, Inc.

Posted on • Originally published at syncfusion.com on

3 Easy Steps to Digitally Sign PDFs in Your Flutter App

TL;DR: Learn to digitally sign PDFs in your Flutter app using Syncfusion PDF Viewer. This guide covers setting up your Flutter project, integrating the Syncfusion package, and implementing digital signatures with clear code examples. Follow these steps to streamline document signing in your app.

Digital signatures in PDFs have become an essential tool for ensuring the authenticity, integrity, and non-repudiation of documents. We can now sign contracts electronically, speeding up the finalization of agreements and ensuring legal compliance.

This digital signature will make signing easy and efficient for sectors such as banks and financial institutions, law firms, government agencies, and more.

Syncfusion Flutter PDF Viewer also allows you to sign the PDF document digitally, and in this blog, we will walk you through the process in detail.

Let’s get started!

Digitally sign a PDF using Syncfusion Flutter PDF Viewer

Follow these steps to digitally sign your PDF document using the Syncfusion Flutter PDF Viewer widget:

Step 1: Create a Flutter app with a dependency

First, create a new Flutter app and add the syncfusion_flutter_pdfviewer dart package as a dependency.

dependencies:
  flutter:
    sdk: flutter
  syncfusion_flutter_pdfviewer: ^X.X.X
Enter fullscreen mode Exit fullscreen mode

Note: The X.X.X denotes the version of the package.

Once you have added the dependencies, import the following packages in your dart code.

import 'package:syncfusion_flutter_pdf/pdf.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure the Flutter app to digitally sign a PDF

Now, create a PdfViewer widget class and the PdfViewerState class to build and display the PDF file in the SfPdfViewer. In the _initState method, we will read the PDF file from the asset using the root bundle and assign the document bytes to the SfPdfViewer.

Then, in the AppBar, we will design the Complete Signing button, which will be enabled only after the signature is added to the field. To enable or disable the Complete Signing button, we have used the onFormFieldValueChanged callback, which will help us determine whether the signature field is signed.

We also showcase a toast message to confirm that the document has been digitally signed successfully. This message will be displayed upon pressing the Complete Signing button after the digital signing process has been successfully completed.

Refer to the following code example.

class PdfViewer extends StatefulWidget {
  const PdfViewer({super.key});

  @override
  State<PdfViewer> createState() => _PdfViewerState();
}
class _PdfViewerState extends State<PdfViewer> {
  final Map<String, Uint8List> _signedFields = <String, Uint8List>{};
  PdfDocument? _loadedDocument;
  Uint8List? _documentBytes;
  bool _canCompleteSigning = false;
  bool _canShowToast = false;

  @override
  void initState() {
    super.initState();
    // Load the PDF document from the asset.
    _readAsset('digital_signature.pdf').then((List<int> bytes) async {
      setState(() {
        _documentBytes = Uint8List.fromList(bytes);
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Digitally sign the agreement'),
        actions: [
          ElevatedButton(
            onPressed: _canCompleteSigning ? _signDocument : null,
            style: ElevatedButton.styleFrom(
              backgroundColor: _canCompleteSigning
                  ? Theme.of(context).colorScheme.primary
                  : null,
              disabledBackgroundColor: _canCompleteSigning
                  ? Theme.of(context).colorScheme.primary
                  : Colors.transparent,
              foregroundColor: _canCompleteSigning
                  ? Theme.of(context).colorScheme.onPrimary
                  : null,
            ),
            child: const Text('Complete Signing'),
          ),
        ],
      ),
      body: Column(
        children: [
          if (_canShowToast)
            Container(
              color: Colors.green,
              alignment: Alignment.center,
              child: const Text(
                ' The agreement has been digitally signed successfully.',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 18,
                ),
              ),
            ),
           Expanded(
            child: _documentBytes != null
                ? SfPdfViewer.memory(
                    _documentBytes!,
                    onDocumentLoaded: (PdfDocumentLoadedDetails details) {
                      // Store the loaded document to access the form fields.
                      _loadedDocument = details.document;
                      // Clear the signed fields when the document is loaded.
                      _signedFields.clear();
                    },
                    onFormFieldValueChanged:
                        (PdfFormFieldValueChangedDetails details) {
                      // Update the signed fields when the form field value is changed.
                      if (details.formField is PdfSignatureFormField) {
                        final PdfSignatureFormField signatureField =
                            details.formField as PdfSignatureFormField;
                        if (signatureField.signature != null) {
                          _signedFields[details.formField.name] =
                              signatureField.signature!;
                          setState(() {
                            _canCompleteSigning = true;
                          });
                        } else {
                          _signedFields.remove(details.formField.name);
                          setState(() {
                            _canCompleteSigning = false;
                          });
                        }
                      }
                    },
                  )
                : const Center(
                    child: CircularProgressIndicator(),
                  ),
          ),
        ],
      ),
    );
  }

  // Read the asset file and return the bytes.
  Future<List<int>> _readAsset(String name) async {
    final ByteData data = await rootBundle.load('assets/$name');
    return data.buffer.asUint8List();
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Digitalizing the existing signature in a PDF

Next, we will handle the digital signing process using a separate method named _signDocument, which is invoked when the Complete Signing button is pressed. In this method, we will create the digital signature by assigning a digital ID to the signature field, which already has a signature drawn.

Note: The digital signature creation process is done with the help of our Syncfusion PDF Library, which is also one of the dependent libraries of our PDF Viewer.

Finally, once the digital signature is created, we will save and reload the document to the PDF Viewer, which will showcase the signature as flattened, meaning that the document is not supposed to be modified further.

Refer to the following code example.

// Digitally sign the document and reload it to the Flutter PDF Viewer.
Future<void> _signDocument() async {
  if (_loadedDocument != null) {
    for (int fieldIndex = 0;
        fieldIndex < _loadedDocument!.form.fields.count;
        fieldIndex++) {
      final PdfField pdfField = _loadedDocument!.form.fields[fieldIndex];

      if (pdfField is PdfSignatureField &&
          _signedFields.containsKey(pdfField.name)) {
        final PdfSignatureField signatureField = pdfField;
        if (signatureField.signature == null) {
          // Load the certificate from the asset.
          final PdfCertificate certificate = PdfCertificate(
              await _readAsset('certificate.pfx'), 'password123');

          // Add the signature to the signature field.
          signatureField.signature = PdfSignature(
            certificate: certificate,
            contactInfo: 'johndoe@owned.us',
            locationInfo: 'Honolulu, Hawaii',
            reason: 'I am the author of this document.',
          );

          // Draw the signature image to the signature field.
          signatureField.appearance.normal.graphics?.drawImage(
            PdfBitmap(
              _signedFields[pdfField.name]!,
            ),
            Offset.zero & signatureField.bounds.size,
          );
          _canCompleteSigning = false;
        }
      }
    }
    // Save the signed document.
    final List<int> bytes = await _loadedDocument!.save();
    // Update the document bytes to reflect the changes.
    setState(() {
      _documentBytes = Uint8List.fromList(bytes);
      _canShowToast = true;
    });
    Future<void>.delayed(const Duration(seconds: 5), () {
      setState(() {
        _canShowToast = false;
      });
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

After executing the above code examples, we will get the output for the Windows platform, as shown in the following image .

Digitally signing a PDF using Syncfusion Flutter PDF Viewer

Digitally signing a PDF using Syncfusion Flutter PDF Viewer

GitHub reference

For the complete working project, refer to digitally sign a PDF document in Flutter GitHub demo.

Conclusion

Thanks for reading! This blog taught us how to digitally sign a PDF document using the Syncfusion Flutter PDF Viewer. Try this in your app and share your feedback in the comments below.

The new version is available for current customers to download from the License and Downloads page. If you are not a Syncfusion customer, you can try our 30-day free trial for our newest features.

You can also contact us through our support forums, support portal, or feedback portal. We are always happy to assist you!

Related blogs

Top comments (0)