Реализация электронной подписи в мобильном приложении
Финтех, юридические сервисы и HR-платформы требуют юридически значимой подписи документов. Мы внедряем НЭП и КЭП под ключ: от генерации ключей в Secure Enclave до серверной верификации и timestamp. Наш опыт — 5+ лет и 10+ проектов для iOS и Android.
Электронная подпись — криптографическая операция. Документ подписывается приватным ключом пользователя. Верификатор проверяет подпись публичным ключом. Различают 3 вида: КЭП (с сертификатом от аккредитованного УЦ), НЭП (своя PKI) и ПЭП. Для большинства коммерческих кейсов достаточно НЭП — стоимость реализации от 25 000 ₽. КЭП нужна для госуслуг. Интеграция с КЭП-провайдером обходится от 80 000 ₽.
Как мы генерируем ключи на мобильном устройстве
Приватный ключ генерируется на устройстве. Он хранится в Keychain (iOS) или Android Keystore. Публичный ключ регистрируется на сервере. Приватный ключ никогда не покидает Secure Enclave или TEE. Это полностью исключает перехват ключа через сеть или файловую систему.
| Платформа | Хранилище | Биометрия | Аппаратная защита |
|---|---|---|---|
| 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 ₽.
Долгосрочная валидность и timestamp
Если документ должен оставаться валидным после истечения сертификата, применяем 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 — при долгосрочном хранении подпись становится неверифицируемой после истечения сертификата.







