Реализация экспорта приватного ключа из мобильного криптокошелька
Экспорт приватного ключа — операция с максимальным threat level. Ключ появляется на экране в открытом виде и до нажатия «скрыть» уязвим для скриншотов, screen recording, shoulder surfing. Задача — минимизировать время экспозиции и количество мест, через которые ключ проходит.
Защита перед показом
Биометрическая аутентификация или PIN-код обязательны перед любым показом ключа. Недостаточно просто проверить «пользователь залогинен» — нужна именно challenge-at-point-of-action аутентификация.
iOS — LAContext.evaluatePolicy(.deviceOwnerAuthentication). Android — BiometricPrompt с BIOMETRIC_STRONG. Ключ из Keychain/Keystore запрашивается только после успешной аутентификации, не до.
Флаг preventScreenCapture / FLAG_SECURE:
// iOS — в viewWillAppear
UIScreen.main.value(forKey: "disableScreenCapture") // deprecated
// правильно:
func screenCaptureBlocking() {
let field = UITextField()
field.isSecureTextEntry = true
if let layer = field.layer.sublayers?.first {
view.layer.addSublayer(layer)
layer.frame = view.bounds
}
}
На iOS нет публичного API для блокировки скриншотов, но трюк с UITextField.isSecureTextEntry работает на iOS 13–17. На Android WindowManager.LayoutParams.FLAG_SECURE блокирует и скриншоты, и screen recording.
Показ и формат
Ключ показывается в monospace шрифте, разбитый на группы по 4 символа для читаемости. QR-код — удобный способ передачи, но тогда QR должен рендериться только в памяти и никогда не сохраняться в фото-библиотеку.
Таймер автоскрытия — 60 секунд. После истечения ключ заменяется на ••••••••••••. Повторный показ — снова биометрия.
Clipboard — осторожно
Кнопка «Скопировать» удобна, но clipboard на Android до версии 10 доступен любому приложению в фоне без разрешений. Либо не предоставлять копирование для приватного ключа, либо — копировать и автоматически очищать через 30 секунд с уведомлением пользователя.
Что тестируем
Экспорт → импорт того же ключа в другой кошелёк (MetaMask, Trust Wallet) с проверкой совпадения адреса. Поведение при отклонении биометрии. Отсутствие ключа в логах — NSLog, print, Android Log.d в продакшн-билде не должны захватывать sensitive data. Это проверяется grep'ом в CI по паттернам privateKey, mnemonic, secret.
Сроки — 1–3 дня. Если нужна поддержка нескольких форматов (hex, WIF, Base58) и QR — ближе к трём.







