Electronic Signature Implementation (Handwriting Drawing) in Mobile Apps
Handwritten signature on smartphone screen — it's not just "a nice picture." For legal validity, it must be bound to the signer's identity, specific document, and moment of signing. Otherwise, it's just PNG with scribbles that proves nothing.
Capturing Handwritten Signature
Collecting touch trajectory — the foundation. Need not just touchMove coordinates, but entire event stream with pressure, velocity, and timestamps. Allows animated signature playback and biometric metadata collection.
Android — low-level input:
override fun onTouchEvent(event: MotionEvent): Boolean {
val x = event.x
val y = event.y
val pressure = event.pressure // 0.0 - 1.0
val timestamp = event.eventTime
when (event.action) {
MotionEvent.ACTION_DOWN -> startStroke(x, y, pressure, timestamp)
MotionEvent.ACTION_MOVE -> {
// getHistorical* for intermediate points between events
for (i in 0 until event.historySize) {
addHistoricalPoint(
event.getHistoricalX(i),
event.getHistoricalY(i),
event.getHistoricalPressure(i),
event.getHistoricalEventTime(i)
)
}
addPoint(x, y, pressure, timestamp)
}
MotionEvent.ACTION_UP -> endStroke(x, y, pressure, timestamp)
}
return true
}
event.historySize is critical — system batches intermediate points between two ACTION_MOVE events. Ignoring historical points produces angular strokes instead of smooth curves.
iOS — UIBezierPath with Bezier smoothing:
func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let currentPoint = touch.location(in: self)
let previousPoint = touch.previousLocation(in: self)
let force = touch.force / touch.maximumPossibleForce // 3D Touch / Pencil
// Quadratic bezier for smoothing
let midPoint = CGPoint(
x: (currentPoint.x + previousPoint.x) / 2,
y: (currentPoint.y + previousPoint.y) / 2
)
path.addQuadCurve(to: midPoint, controlPoint: previousPoint)
setNeedsDisplay()
}
For Apple Pencil — predictedTouches(for:) provides predicted points for reducing drawing latency. Without predictive touches, Pencil visual response feels laggy even at 120 Hz.
Variable Stroke Width
Professional signature looks natural when stroke width changes with pressure and velocity. Math is simple: width = baseWidth + pressure * maxExtraWidth. High velocity (large distance between points) — thin line; slow movement — thick line.
fun calculateStrokeWidth(pressure: Float, velocity: Float): Float {
val pressureComponent = pressure * MAX_PRESSURE_WIDTH
val velocityComponent = (1f - velocity.coerceIn(0f, 1f)) * MAX_VELOCITY_WIDTH
return BASE_WIDTH + pressureComponent * 0.6f + velocityComponent * 0.4f
}
Biometric Metadata
To strengthen legal validity — collect signing process metadata:
- Timestamps of each stroke
- Movement velocity across segments
- Pressure (if device supports)
- Duration of each stroke and pauses between
- Total signing time
This data isn't displayed to user but stored in database and can be used if signature authenticity is challenged in court — behavioral biometrics.
Binding to Document
Signature drawing by itself is useless. Need to:
- Fix document hash before signing (SHA-256 of PDF or text content)
- Attach signature (PNG + trajectory metadata) to this hash
- Save on server with timestamp and signer ID
- Optionally: embed signature in PDF via iText (Java/Android) or PDFKit (iOS)
Server record:
{
"document_hash": "sha256:abc123...",
"signer_id": "user-uuid",
"signed_at": "2025-03-26T14:22:00Z",
"ip_address": "1.2.3.4",
"device_fingerprint": "...",
"signature_image_url": "...",
"stroke_data_encrypted": "...",
"session_metadata": {
"duration_ms": 4200,
"stroke_count": 5,
"avg_pressure": 0.72
}
}
PDF Integration
On iOS: PDFKit + CGContext for drawing signature over PDF page. For professional embedding with AcroForm fields — third-party library PSPDFKit or server-side iText via API.
On Android: PdfRenderer for display, embedding — via iText Android or Apache PDFBox.
Important: visual signature embedding in PDF ≠ digital PDF signature (created via PKI). These are different things. For legally significant PDF, you need PKI signature — handwritten signature added as additional visual element.
Ready-made SDKs vs Custom Implementation
Ready-made: SignaturePad (Android, iOS), react-native-signature-canvas, signature_pad (Flutter). Provide basic functionality quickly. Don't provide: biometric metadata, variable width with pressure, PKI integration.
If only visual signature for simple SES needed — ready SDK justified. For full AES with audit trail — custom implementation.
Timeline: custom drawing component with pressure, smoothing, PNG export + server binding to document + PDF embedding — 2–3 days per platform.







