Как широко известно, операционная система iOS считается одной из самых безопасных мобильных операционных систем, но каждая система может быть уважаемой в определенный момент, но вот некоторые хитрости, которые мы можем сделать приложение более безопасным.

  1. Включить ATS в мобильных приложениях
    ATS (безопасность передачи приложений) была введена начиная с iOS 9, она позволяет выполнять все наши запросы в безопасных сетях Apple, что означает любое соединение, которое приложение устанавливает с внешним миром. должен использовать протокол HTTPS и TLS1.2.

2. Хранение информации в KeyChain, а не в NSUserDefaults
NSUserDefaults позволяет нам сохранять небольшие фрагменты информации, которые необходимо сохранять между запусками приложений и перезапусками устройства. Вся информация, сохраненная как часть UserDefaults, сохраняется в виде обычного текста в plist, который не зашифрован и может быть прочитан любым, у кого есть доступ к устройству. Если мы хотим сохранить информацию в зашифрованном виде, нам нужно использовать KeyChain, зашифрованный контейнер для хранения паролей для приложений и безопасных сервисов. Apple использует одну и ту же технологию для управления паролями в Mac OS и iOS.

3. Обнаружение джейлбрейка
Поведение и логика приложения могут быть легко скомпрометированы хакером без особых усилий на взломанном устройстве. Как разработчики, мы должны сделать так, чтобы хакеру было как можно сложнее добраться до внутренних деталей приложения. Мы определенно должны добавить логику для проверки взломанного устройства в первую очередь при запуске приложения. И после информирования пользователя мы можем использовать следующий смысл, чтобы проверить, есть ли у iPhone побег из тюрьмы.

import Foundation
import UIKit

extension UIDevice {
    var isSimulator: Bool {
        return TARGET_OS_SIMULATOR != 0
    }
    
    var isJailBroken: Bool {
        get {
            if UIDevice.current.isSimulator { return false }
            if JailBrokenHelper.hasCydiaInstalled() { return true }
            if JailBrokenHelper.isContainsSuspiciousApps() { return true }
            if JailBrokenHelper.isSuspiciousSystemPathsExists() { return true }
            return JailBrokenHelper.canEditSystemFiles()
        }
    }
}
    
private struct JailBrokenHelper {
    static func hasCydiaInstalled() -> Bool {
        return UIApplication.shared.canOpenURL(URL(string: "cydia://")!)
    }
    
    static func isContainsSuspiciousApps() -> Bool {
        for path in suspiciousAppsPathToCheck {
            if FileManager.default.fileExists(atPath: path) {
                return true
            }
        }
        return false
    }
    
    static func isSuspiciousSystemPathsExists() -> Bool {
        for path in suspiciousSystemPathsToCheck {
            if FileManager.default.fileExists(atPath: path) {
                return true
            }
        }
        return false
    }
    
    static func canEditSystemFiles() -> Bool {
        let jailBreakText = "Developer Insider"
        do {
            try jailBreakText.write(toFile: jailBreakText, atomically: true, encoding: .utf8)
            return true
        } catch {
            return false
        }
    }
    
    /**
     Add more paths here to check for jail break
     */
    static var suspiciousAppsPathToCheck: [String] {
        return ["/Applications/Cydia.app",
                "/Applications/blackra1n.app",
                "/Applications/FakeCarrier.app",
                "/Applications/Icy.app",
                "/Applications/IntelliScreen.app",
                "/Applications/MxTube.app",
                "/Applications/RockApp.app",
                "/Applications/SBSettings.app",
                "/Applications/WinterBoard.app"
        ]
    }
    
    static var suspiciousSystemPathsToCheck: [String] {
        return ["/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist",
                "/Library/MobileSubstrate/DynamicLibraries/Veency.plist",
                "/private/var/lib/apt",
                "/private/var/lib/apt/",
                "/private/var/lib/cydia",
                "/private/var/mobile/Library/SBSettings/Themes",
                "/private/var/stash",
                "/private/var/tmp/cydia.log",
                "/System/Library/LaunchDaemons/com.ikey.bbot.plist",
                "/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist",
                "/usr/bin/sshd",
                "/usr/libexec/sftp-server",
                "/usr/sbin/sshd",
                "/etc/apt",
                "/bin/bash",
                "/Library/MobileSubstrate/MobileSubstrate.dylib"
        ]
    }
}

3. Только журналы отладки

Разработчики используют отладочное сообщение в качестве инструмента для отладки поведения приложения и наблюдения за его потоком. Когда приложение находится в стадии разработки, мы склонны регистрировать некоторую информацию, чтобы помочь разработчикам создавать функции. Но это может раскрыть конфиденциальную информацию и внутреннюю работу приложения. Чтобы убедиться, что мы храним этот журнал только для целей разработки, мы используем эту строку кода.

#если ОТЛАДКА

распечатать («журнал»)

#endif

4. Использование сторонних библиотек

Сторонние библиотеки — отличный способ избежать повторного создания многих вещей, которые мы хотим сделать в нашем мобильном приложении. Они определенно экономят нам много времени, в то же время есть некоторые вещи, с которыми нам нужно быть осторожными при использовании сторонних приложений. Всегда существует риск того, что эти библиотеки внедрят вредоносный код в нашу кодовую базу. Мы всегда должны просматривать ссылку на Github, лицензию, количество звезд и проверку кода/безопасности любого стороннего приложения перед его фактической интеграцией. Рекомендуется использовать сторонние приложения в пользовательском интерфейсе и сохранять исходную функцию ядра приложения.

5. Защита файловых данных

Всякий раз, когда мы сохраняем какой-либо файл в нашем приложении, мы должны использовать эти параметры для безопасного сохранения информации

  • Полная защита (NSFileProtectionComplete)
  • Защищено, если не открыто (NSFileProtectionCompleteUnlessOpen)
  • Защищено до аутентификации первого пользователя (NSFileProtectionCompleteUntilFirstUserAuthentication)

6. Шифрование данных
с использованием симметричных ключей

Шифрование и дешифрование данных с использованием симметричного ключа — распространенный способ защиты данных. Вы можете использовать один из двух доступных шифров: ChaChaPoly (ChaCha20-Poly1305) или AES-GCM в CryptoSwift:

let encryptedData = try! ChaChaPoly.seal(data, using: key).combined
let sealedBox = try! ChaChaPoly.SealedBox(combined: encryptedData)
let decryptedData = try! ChaChaPoly.open(sealedBox, using: key)

Однако вы всегда должны следить за тем, чтобы эти симметричные ключи не были жестко закодированы в вашем приложении. Вы можете сгенерировать симметричный ключ во время выполнения, а затем безопасно сохранить его в связке ключей. Таким образом, никто не получит доступ к вашему ключу для расшифровки данных.

Выполнение соглашения о ключах

Во многих случаях вам потребуется выполнить некоторую форму обмена ключами для обмена криптографическими ключами по небезопасному каналу. С протоколами согласования ключей, такими как Эллиптическая кривая Диффи-Хеллмана (ECDH), вы можете получить общий секрет.

  1. Создайте пары закрытый/открытый ключ для Алисы и Боба
let alicePrivateKey = P256.KeyAgreement.PrivateKey()
let alicePublicKey = alicePrivateKey.publicKey
let bobPrivateKey = P256.KeyAgreement.PrivateKey()
let bobPublicKey = bobPrivateKey.publicKey

И Алиса, и Боб создают свои собственные пары закрытый/открытый ключ и делятся своими открытыми ключами.

  1. Получение общего секрета
let aliceSharedSecret = try! alicePrivateKey.sharedSecretFromKeyAgreement(with: bobPublicKey)
let bobSharedSecret = try! bobPrivateKey.sharedSecretFromKeyAgreement(with: alicePublicKey)

Теперь мы смогли получить общий секрет, используя собственный закрытый ключ вместе с открытым ключом контрагента. aliceSharedSecret и bobSharedSecret теперь одинаковы.

  1. Созданный секретный номер сам по себе не должен использоваться в качестве ключа шифрования. Вместо этого его можно использовать для создания гораздо более крупного и более безопасного ключа шифрования с использованием вывода ключа HKDF или X9.63.
let usedSalt = "Secure iOS App".data(using: .utf8)!
let symmetricKey = aliceSharedSecret.hkdfDerivedSymmetricKey(
    using: SHA256.self,
    salt: protocolSalt,
    sharedInfo: Data(),
    outputByteCount: 32
)

Вот так вообще можно было реализовать! Также обратите внимание, что у Apple есть реализация Диффи-Хеллмана в iOS как часть Secure Transport. Вот Справочник по безопасному транспорту.

Наконец, это всего лишь несколько простых настроек, позволяющих сделать наше приложение безопасным и менее уважаемым. Более того, для каждой технологии, которую мы используем в повседневной жизни, всегда есть скрытый черный ход 😎