Реалізація електронного підпису в мобільному додатку
Фінтех, юридичні сервіси та HR-платформи потребують юридично значущого підпису документів. Ми впроваджуємо НЕП та КЕП під ключ: від генерації ключів у Secure Enclave до серверної верифікації та timestamp. Наш досвід — 5+ років і 10+ проектів для iOS та Android.
Електронний підпис — криптографічна операція. Документ підписується приватним ключем користувача. Верифікатор перевіряє підпис публічним ключем. Розрізняють 3 види: КЕП (з сертифікатом від акредитованого ЦСК), НЕП (власна PKI) та ПЕП. Для більшості комерційних кейсів достатньо НЕП — вартість реалізації від 25 000 ₽. КЕП потрібна для держпослуг. Інтеграція з КЕП-провайдером коштує від 80 000 ₽.
Як генерувати ключі на мобільному пристрої?
Приватний ключ генерується на пристрої за допомогою криптографічних алгоритмів, таких як ECDSA (еліптичні криві) з хеш-функцією SHA-256. Він зберігається в Keychain (iOS) або Android Keystore. Публічний ключ реєструється на сервері. Приватний ключ ніколи не покидає Secure Enclave або TEE. Це повністю виключає перехоплення ключа через мережу або файлову систему. Впровадження НЕП займає в 3 рази менше часу, ніж КЕП.
| Платформа | Сховище | Біометрія | Апаратний захист |
|---|---|---|---|
| iOS | Keychain + Secure Enclave | kSecAttrAccessControl з біометрією |
Secure Enclave (A7+) |
| Android | Android Keystore + TEE | setUserAuthenticationRequired |
TEE (ARM TrustZone) |
Генерація ключової пари на Android:
val keyPairGenerator = KeyPairGenerator.getInstance( KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore" ) keyPairGenerator.initialize( KeyPairGeneratorSpec.Builder(context) .setAlias("user_signing_key") .setKeyType("EC") .setKeySize(256) .setSubject(X500Principal("CN=User")) .setSerialNumber(BigInteger.ONE) .setStartDate(startDate) .setEndDate(endDate) .build() ) val keyPair = keyPairGenerator.generateKeyPair() val publicKeyBase64 = Base64.encode(keyPair.public.encoded) iOS, Swift:
let attributes: [String: Any] = [ kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeySizeInBits as String: 256, kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave, kSecPrivateKeyAttrs as String: [ kSecAttrIsPermanent as String: true, kSecAttrApplicationTag as String: "com.example.signing".data(using: .utf8)! ] ] var error: Unmanaged<CFError>? guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else { // обработать ошибку } let publicKey = SecKeyCopyPublicKey(privateKey)! Чому біометрична аутентифікація обов'язкова?
Для юридично значущих операцій ключ повинен бути захищений підтвердженням особи. Ключ доступний лише після успішної біометричної аутентифікації. Face ID обробляє запит за 0,5 секунди. На Android біометрія Class 3 в 1000 разів надійніша за PIN-код за стандартом FIDO Alliance. Наші проекти проходять аудит OWASP MASVS з результатом 95%+.
keyGenParameterSpec = KeyGenParameterSpec.Builder(...) .setUserAuthenticationRequired(true) .setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG) .build() При кожному підписанні створюється CryptoObject з об'єктом Signature. У callback onAuthenticationSucceeded отримуємо розблокований підпис.
Які формати підпису та як верифікувати на сервері?
Для стандартизації використовуємо CMS (RFC 5652) або JWS (RFC 7515). JWS зручніший для REST API. На сервері верифікація через PyJWT, jose або nimbus-jose-jwt.
| Формат | Стандарт | Застосування | Типовий розмір |
|---|---|---|---|
| CMS/PKCS#7 | RFC 5652 | Документообіг, CAdES | 3–10 КБ |
| JWS | RFC 7515 | REST API | 0,5–2 КБ |
| XML DSig | W3C | Державні системи | 5–20 КБ |
RFC 5652 — Cryptographic Message Syntax (CMS)
Що входить в роботу
Етапи нашої роботи з впровадження ЕП:
- Проектування схеми ключів та вибір формату підпису (CMS або JWS) — 1 день.
- Генерація ключової пари, налаштування Secure Enclave або Android Keystore — 1 день.
- Інтеграція біометричної аутентифікації та реалізація UI підписання — 1 день.
- Серверна верифікація підписів з підтримкою timestamp RFC 3161 — 1 день.
- Тестування безпеки, документація та навчання команди — 1 день.
Разом — 3–5 робочих днів. Вартість базової НЕП від 25 000 ₽.
Як забезпечити довгострокову валідність підпису?
Якщо документ повинен залишатися валідним після закінчення сертифіката, застосовуємо RFC 3161 Trusted Timestamping. TSA підписує хеш документа та фіксує час. Навіть при компрометації ключа timestamp доводить момент створення підпису. Публічні TSA: Freetsa.org, DigiCert. Інтеграція через bouncycastle на Android та Security.framework на iOS. Рекомендуємо формат CAdES-LT — він включає вбудований сертифікат TSA та спрощує верифікацію через 10–20 років. Термін зберігання юридично значущих документів з коректним timestamp — від 5 до 25 років.
Варіанти інтеграції із зовнішніми КЕП-провайдерами
Для кваліфікованого підпису в Росії: КриптоПро, Рутокен, ViPNet. У кожного є мобільні SDK. Інтеграція через CryptoPro CSP SDK — підписання на стороні токена. Для міжнародних кейсів застосовуємо DocuSign SDK, Adobe Sign API, HelloSign. Для проектів в Білорусі підходять AvSoft та Авест. Наша команда знає особливості кожного провайдера — це економить 2–3 тижні на вивчення документації.
НЕП: 3–5 днів, від 25 000 ₽. КЕП із зовнішнім провайдером — індивідуальна оцінка після аналізу вимог та API. Оцінимо ваш проект безкоштовно — зв'яжіться з нами та отримайте попередній план за 1 день.
Типові помилки при реалізації
- Зберігання ключа в SharedPreferences або UserDefaults — ключ легко витягується. Використовуйте лише апаратне сховище.
- Ігнорування біометричного захисту — підпис може бути створений без відома власника.
- Відсутність timestamp — при довгостроковому зберіганні підпис стає неверифікованим після закінчення сертифіката.







