Developing a Mobile App for Electronic Document Signing
At first glance, the task is straightforward: user opens a PDF, draws a signature with their finger, taps "Sign". In practice, between "drew" and "legally signed" lies an abyss filled with PKI infrastructure, certificate chains, TSA timestamps, and regulatory requirements. This is not a case where saving a raster image over the document is sufficient.
Qualified vs Simple Electronic Signature
Regulatory requirements dictate architecture more strongly than technical preferences. If the product operates in Russia, GOST R 34.10-2012 with an accredited certification authority is required. If in the EU—eIDAS, PAdES/XAdES, qualified certificate from a QTSP. For internal document circulation without legal significance—RSA-2048 or ECDSA P-256 on a self-signed certificate is enough.
Most projects start with "internal approval" and discover months later that qualified e-signature is required. Better to design with headroom: a SigningProvider abstraction with pluggable implementations—Secure Enclave, hardware token via USB-C/NFC, cloud HSM.
Where the Private Key Lives
This is the central question of the entire architecture. Three options:
Secure Enclave / Android Keystore. The key is generated directly on the chip; export is physically impossible. Signature computation happens inside the enclave—the app sends a document hash (SHA-256), receives an ECDSA signature back. On iOS: SecKeyCreateSignature with algorithm: .ecdsaSignatureMessageX962SHA256. On Android: KeyPairGenerator with KeyGenParameterSpec, then Signature.getInstance("SHA256withECDSA", "AndroidKeyStore").
NFC Token (e.g., YubiKey 5 NFC, SafeNet eToken). Smart card with PKCS#11 interface. On iOS use NFCTagReaderSession + APDU commands directly or through CoreNFC + CryptoTokenKit. On Android — IsoDep from android.nfc.tech. The token requires a PIN; the private key never leaves the card.
Cloud HSM + Mobile SDK. Providers like Entrust nShield or AWS CloudHSM provide mobile SDKs. The key lives in the HSM; the phone sends a hash over TLS mutual auth, receives a signature. Requires internet—unsuitable for offline scenarios.
For most corporate applications, optimal is: Secure Enclave / Keystore for internal document circulation + optional NFC token for legally significant operations.
Signature Format: PAdES, XAdES, CAdES
PDF documents are signed in PAdES format (PDF Advanced Electronic Signatures, ETSI EN 319 132). Implementation on a mobile client:
- Compute SHA-256 of the byte range of the PDF, excluding the reserved signature space (
ByteRange). - Form a CMS SignedData structure with attributes
signingCertificate,signingTime, ESSCertIDv2. - Optionally—obtain a timestamp from a TSA (RFC 3161): send the signature hash, receive
TSTInfo, embed inunauthenticatedAttributes. - Write the DER-encoded CMS to the reserved PDF space.
On iOS, ready-made PAdES libraries in native Swift are scarce—typically use PDFKit for structure parsing + custom CMS implementation through Security.framework. Alternative—the mobile client forms the hash, sends it to the server; the server completes the signature via itext7 or OpenPDF. Hybrid scheme: key on device, final PAdES container assembled on server.
Visual Signature vs Cryptographic
A separate module—handwritten signature. UIBezierPath on iOS with pressure sampling via UITouch.force, smoothing via Catmull-Rom spline, export to SVG/PNG. This is a visual element—it carries no cryptographic weight, but is necessary for familiar user experience.
Embedded as a PDFAnnotation over the page before cryptographic signing. Important: the visual signature must be "flattened" into the PDF before cryptographic signing—otherwise the annotation is outside the byte range of the signature and verification fails.
Signature Verification on the Receiving Side
A mobile app often must also accept signed documents. The chain: extract CMS from PDF → verify the certificate chain to a trusted root CA → check certificate status via OCSP or CRL → verify TSA timestamp → compare document hash with hash in signature.
On iOS this is CMSDecoder + SecTrustEvaluateWithError. OCSP status is checked via SecPolicyCreateRevocation with the kSecRevocationOCSPMethod flag. Offline mode: if OCSP is unavailable, decide at the policy level—either reject or allow with a "not verified" note.
Common Implementation Mistakes
The three most painful pitfalls:
-
Clock skew on the device. Signature created with
signingTimeoffset by hours (device not synchronized). TSA timestamp fixes this—another argument for its use. -
Incorrect
ByteRange. PDF is appended with metadata after hash computation—signature is invalid. Reserve space for the entire CMS container in advance and don't touch bytes outsideByteRange. -
Certificate without
nonRepudiationinkeyUsage. Verifiers like Adobe Reader or Acrobat report an untrusted signature. Ensure this when issuing the certificate.
Project Stages
Choose scheme (signature type, PKI or self-signed) → develop SigningProvider abstraction → integrate with Keychain/Keystore → PAdES implementation → UI (document viewer + handwritten signature) → corporate CA integration → security audit → publication.
Timeline: internal document circulation with Keystore, one platform—from 6 weeks. Qualified signature with TSA, NFC token, two platforms—3–5 months. Cost is calculated individually after analyzing signature type and regulatory environment requirements.







