Уявіть: клієнт підписує договір через мобільний додаток, а потім оскаржує справжність. Без біометричних метаданих такий спір вирішити неможливо. Ми стикалися з цим у проєкті для фінтеху — довелося доопрацьовувати підпис з нуля. Наш підхід: комбінуємо захоплення траєкторії з тиском та швидкістю, прив'язуємо до хешу документа та зберігаємо аудиторський слід. Мобільні додатки все частіше потребують вбудованого модуля рукописного підпису — від банківських документів до медичних карток. Але ілюзія «просто картинка» небезпечна: підпис на екрані не має юридичної сили без прив'язки до особи, документа та часу. Ми вирішуємо це завдання на рівні Android (Kotlin, Jetpack Compose) та iOS (Swift, SwiftUI), використовуючи низькорівневе захоплення траєкторії та біометричні метадані. Наш досвід — понад 10 проєктів з інтеграцією підписів у документообіг, гарантуємо стабільну роботу на всіх пристроях. Вартість такого рішення окупається за рахунок зниження ризиків судових спорів.
Захоплення рукописного підпису
Збір траєкторії дотику — основа. Потрібні не просто координати touchMove, а весь потік подій з тиском, швидкістю та часовими мітками. Це дозволяє відтворити підпис анімовано та зібрати біометричні метадані.
Android — низькорівневе введення:
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 -> { 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 критичне — між двома ACTION_MOVE система батчить проміжні точки. Ігнорування історичних точок дає кутові штрихи замість плавних кривих.
iOS — UIBezierPath з Bezier-згладжуванням:
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 let midPoint = CGPoint( x: (currentPoint.x + previousPoint.x) / 2, y: (currentPoint.y + previousPoint.y) / 2 ) path.addQuadCurve(to: midPoint, controlPoint: previousPoint) setNeedsDisplay() } Для Apple Pencil використовуємо predictedTouches(for:) — без передбачених точок відгук при 120 Hz сприймається як запізнілий.
Змінна товщина лінії
Професійний підпис виглядає природно, коли товщина штриха змінюється з тиском та швидкістю. Математика проста: width = baseWidth + pressure * maxExtraWidth. При високій швидкості — тонка лінія, при повільному русі — товста.
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 } Як забезпечити юридичну значущість? — біометричні метадані
Для посилення юридичної сили збираємо метадані процесу підписання:
- Часові мітки кожного штриха
- Швидкість руху по ділянках
- Натиск (якщо пристрій підтримує)
- Тривалість кожного штриха та паузи між ними
- Загальний час підписання
Докладніше про збір метаданих
Кожен штрих фіксується з точністю до мілісекунди. Використовуємо поведінкову біометрію — унікальний патерн тиску та швидкості складно підробити. Без цих даних підпис — лише PNG.Ці дані зберігаються в базі та можуть бути використані при судовому оскарженні справжності підпису — поведінкова біометрія. Без них підпис — лише PNG.
Прив'язка до документа
Малюнок підпису сам по собі некорисний. Потрібно:
- Зафіксувати хеш документа до підписання (SHA-256 PDF або текстового вмісту)
- Прикріпити підпис (PNG + метадані траєкторії) до цього хешу
- Зберегти на сервері з timestamp та ідентифікатором підписанта
- Опціонально: вбудувати підпис у PDF через iText (Java/Android) або PDFKit (iOS)
Серверний запис:
{ "document_hash": "sha256:abc123...", "signer_id": "user-uuid", "signed_at": "timestamp", "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 } } Чому не варто економити на біометрії? Порівняння підходів
| Критерій | Готовий SDK (SignaturePad та ін.) | Кастомна реалізація |
|---|---|---|
| Швидкість впровадження | 1–2 дні | 3–4 дні |
| Біометричні метадані | Ні | Повний збір |
| Змінна товщина з тиском | Обмежено | Налаштовувана |
| Інтеграція з PKI | Ні | Можлива |
| Юридична сила | Тільки ПЕП | НЕП з аудит-треком |
Готові SDK виправдані для простих сценаріїв (ПЕП), але якщо потрібна НЕП з можливістю судового оскарження — кастом реалізація в 2–3 рази надійніша.
Додаткова таблиця: дані для аудиту
| Параметр | Значення |
|---|---|
| Кількість точок на підпис | 500–1500 |
| Розмір метаданих | 2–5 КБ |
| Точність часу | ±1 мс |
| Підтримувані пристрої | iOS 14+, Android 8+ |
PDF інтеграція
На iOS: PDFKit + CGContext для малювання підпису поверх сторінки PDF. Для професійного вбудовування з полями AcroForm — стороння бібліотека PSPDFKit або серверний iText через API.
На Android: PdfRenderer для відображення, вбудовування — через iText Android або Apache PDFBox.
Важливий момент: візуальне вбудовування підпису в PDF ≠ цифровий підпис PDF (який створюється через PKI). Це різні речі. Для юридично значущого PDF-документа потрібен саме PKI-підпис — рукописний підпис додається як додатковий візуальний елемент.
Що входить у роботу
При замовленні під ключ ви отримуєте:
- Компонент малювання підпису для iOS та Android з підтримкою тиску та згладжування
- Серверний модуль прив'язки до документа (хеш, метадані, timestamp)
- Інтеграцію з PDF (вбудовування підпису)
- Документацію по API та приклади інтеграції
- Технічну підтримку на 2 тижні
Оцінку проєкту робимо за 1 день. Замовте кастомну реалізацію — отримайте повний контроль над біометрією. Зв'яжіться з нами для консультації.
Строки: 3–4 дні на одну платформу, 5–7 днів на обидві. Отримайте консультацію.







