<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Felipe Menezes</title>
    <description>The latest articles on DEV Community by Felipe Menezes (@felipefmmobile).</description>
    <link>https://dev.to/felipefmmobile</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2461270%2F37c2100d-7b02-42bc-9a3c-21a1430a032f.jpg</url>
      <title>DEV Community: Felipe Menezes</title>
      <link>https://dev.to/felipefmmobile</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/felipefmmobile"/>
    <language>en</language>
    <item>
      <title>Security iOS Apps with OWASP Best Practices for Data Protection</title>
      <dc:creator>Felipe Menezes</dc:creator>
      <pubDate>Wed, 20 Nov 2024 22:39:44 +0000</pubDate>
      <link>https://dev.to/felipefmmobile/security-ios-apps-with-owasp-best-practices-for-data-protection-2c5l</link>
      <guid>https://dev.to/felipefmmobile/security-ios-apps-with-owasp-best-practices-for-data-protection-2c5l</guid>
      <description>&lt;p&gt;After several years as iOS developer, I decided revisit some concepts of secure development, and explore some advanced topics, using OWASP as a reference for best practices. In this article, we'll start by securely saving data on device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secure Data Storage
&lt;/h2&gt;

&lt;p&gt;At this point, you already know that the UserDefaults API is not the right option to save sensitive data. What data are those? All related to personal user information or any sensitive data that could be traced back to it (name, credentials, health, address, banking, financial information), passwords and so on. This also applies to data in any documents too.&lt;/p&gt;

&lt;p&gt;To handle this, we have some options, from the basic to more advanced. Here we go:&lt;/p&gt;

&lt;h2&gt;
  
  
  Securing using Keychain
&lt;/h2&gt;

&lt;p&gt;The most secure way to store simple data is to use the Keychain, which is a data storage system in iOS that uses an encrypted database protected by hardware encryption. It's the most common and well-known way to store key-value pairs safety, and developers usually takes advantage of popular libraries like KeychainSwift.&lt;/p&gt;

&lt;p&gt;But, when exploring protection parameters, consider these options to ensure your data is truly secure using the default api. Take a look at this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func saveToKeychain(userName: String) {
        guard let data = userName.data(using: .utf8) else {
                return
            }
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: account,
            kSecValueData as String: data,
            kSecAttrAccessible as String: kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
        ]
        SecItemAdd(query as CFDictionary, nil)
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The use of &lt;em&gt;kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly&lt;/em&gt; is the best way to secure sensitive data because it forces the device to guarantee that the user has set a passcode on the device. However, if the user disables it, your data is erased. Alternatively, use &lt;em&gt;kSecAttrAccessibleWhenUnlockedThisDeviceOnly&lt;/em&gt; for other cases while keeping your data saved only on the device, not shared with iCloud.&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Because it is not shared with iCloud, keep in mind that if you want this data to be recovered during a device backup, you need to choose other options.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;And if you want to use it in another application (that you own) or widget, you can include &lt;em&gt;kSecAttrAccessGroup as String: accessGroup&lt;/em&gt; to give access to it (other project settings are required).&lt;/p&gt;

&lt;p&gt;We can requires the user’s presence to be saved or retrieved, you can also define the &lt;em&gt;.userPresence&lt;/em&gt; flag, which certifies that the user is present by prompting for authentication methods like Face ID, passcode, or Touch ID. &lt;/p&gt;

&lt;p&gt;Also, you can include an application-specific password to retrieve this data, different from the user’s passcode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;guard let access = SecAccessControlCreateWithFlags(
  nil,  // Use the default allocator.
  kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
  .userPresence, &amp;amp;error) else {
   return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Don’t forget to wipe out your data if the user log out or reinstalls your application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Keychain is a global storage at the iOS level (though not shared between apps by default). Some developers overlook this aspect of the lifecycle, allowing data to be accessed on the same device by different users. Here’s a simple way to handle this &lt;a href="https://mas.owasp.org/MASTG/0x06d-Testing-Data-Storage/#keychain-data-persistence" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  FileStorage
&lt;/h2&gt;

&lt;p&gt;For store a document file, like a PDF or other documents, you can use this code to securely save it in file storage. In some cases, you collect those files from the user to send later (or sync them). Below is a sample to securely save the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func saveFileDataStorage(fromUrl: URL) {
    let fileManager = FileManager.default
    do {
        let documentsUrl = try fileManager.url(for: .documentDirectory,
                                               in: .userDomainMask,
                                               appropriateFor: nil, create: false)
        let destinationFileUrl = documentsUrl.appendingPathComponent("myFile.pdf")
        if fileManager.fileExists(atPath: destinationFileUrl.path) {
            try fileManager.removeItem(at: destinationFileUrl)
        }
        try fileManager.moveItem(at: fromUrl, to: destinationFileUrl)
        let attributes = [FileAttributeKey.protectionKey: FileProtectionType.complete]
        try fileManager.setAttributes(attributes, ofItemAtPath: destinationFileUrl.path)

        print("File saved successfully at \(destinationFileUrl.path)")
    } catch {
        print("File Error: \(error.localizedDescription)")
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most important parameter is FileProtectionType.complete, which marks your file to be accessible only when user has unlocked the device. If the device is locked, the data becomes inaccessible until the next unlock. &lt;/p&gt;

&lt;p&gt;A good explanation can be found here and in this &lt;a href="https://developer.apple.com/documentation/uikit/protecting_the_user_s_privacy/encrypting_your_app_s_files/" rel="noopener noreferrer"&gt;Apple article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that the default protection since iOS 7 is Protected Until First User Authentication, which is not the best choice to fully protect your document.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating and Secure Private Keys (SecureEnclave and Keychain)
&lt;/h2&gt;

&lt;p&gt;Is possible to use the Keychain to generate a private key (or other types of encryption keys) to secure data in iOS and save it into Secure Enclave, the same chip that stores iOS biometric data (passcode, Touch ID, or Face ID). &lt;/p&gt;

&lt;p&gt;Private keys stored in the Secure Enclave are non-extractable, and cryptographic operations (e.g., signing, decryption) are performed inside it. &lt;/p&gt;

&lt;p&gt;Additionally, the private key material never leaves the Secure Enclave, reducing the risk of key compromise.&lt;/p&gt;

&lt;p&gt;The code below shows the piece of the attribute dictionary that generates the key: more details are available on the github project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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: account.data(using: .utf8)!,
        kSecAttrAccessControl as String: accessControl
    ]
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstjj3dt6ksywh6rn0hol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstjj3dt6ksywh6rn0hol.png" alt="Decrypt with private key" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Keep in mind, that this kind of storage is designed only for private keys, and use to be rare necessarily for common develop requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secure your CoreData database
&lt;/h2&gt;

&lt;p&gt;It's not very common, but perhaps you use CoreData to save more structured data and its relations, and need to secure it. CoreData does not encrypt its data by default.&lt;/p&gt;

&lt;p&gt;Start securing the file of your database in persistent container, defining a protection level for it, like below, using &lt;em&gt;&lt;strong&gt;FileProtectionType.complete&lt;/strong&gt;&lt;/em&gt; key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let storeURL = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!.appendingPathComponent("iOSOwaspSec.sqlite")
    let description = NSPersistentStoreDescription(url: storeURL)
        description.setOption(FileProtectionType.complete as NSObject, 
        forKey: NSPersistentStoreFileProtectionKey)
    container.persistentStoreDescriptions = [description]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your app needs to access data while in the background or when the device is locked, choose an appropriate protection level. However, you can encrypt the data even when the device is unlocked.&lt;/p&gt;

&lt;p&gt;For higher security, consider encrypting the persistent store. This technique uses the &lt;strong&gt;&lt;em&gt;SQLCipher&lt;/em&gt;&lt;/strong&gt; library to encrypt the entire database, but with a performance cost. &lt;a href="https://github.com/project-imas/encrypted-core-data" rel="noopener noreferrer"&gt;In OWASP we have a link to github project that do this.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, if you want just to secure the information in field level of your table, without lock all database with performance cost, you can create a ValueTransformer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@objc(SecureTransformer)
class SecureTransformer: ValueTransformer {
    static let key = static var key: SymmetricKey = {
        // Retrieve the key from the Keychain or generate a new one
        if let storedKeyData = KeychainHelper
            .retrieveKey(alias: KeychainHelper.keyAlias) {
               return SymmetricKey(data: storedKeyData)
           } else {
               let newKey = SymmetricKey(size: .bits256)
               let keyData = newKey.withUnsafeBytes { Data($0) }
               KeychainHelper.storeKey(keyData,
                                       alias: KeychainHelper.keyAlias)
               return newKey
           }
       }()

    override class func transformedValueClass() -&amp;gt; AnyClass {
        return NSData.self
    }
    override func transformedValue(_ value: Any?) -&amp;gt; Any? {
        guard let stringValue = value as? String else { return nil }
        let data = Data(stringValue.utf8)
        guard let sealedBox = try? ChaChaPoly.seal(data, using: SecureTransformer.key) else { return nil }
        return sealedBox.combined as NSData
    }
    override func reverseTransformedValue(_ value: Any?) -&amp;gt; Any? {
        guard let data = value as? Data else { return nil }
        guard let sealedBox = try? ChaChaPoly.SealedBox(combined: data),
              let decryptedData = try? ChaChaPoly.open(sealedBox, using: SecureTransformer.key) else { return nil }
        return String(data: decryptedData, encoding: .utf8)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And as show in the image, set the attribute’s type to Transformable, and Set the Value Transformer to &lt;strong&gt;SecureTransformer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fryl3srix8tbrd7lazrv4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fryl3srix8tbrd7lazrv4.png" alt="Transformable in CoreData Settings" width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And include the register of your transformer at some point on initialization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ValueTransformer.setValueTransformer(SecureTransformer(), 
forName: NSValueTransformerName("SecureTransformer"))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can secure save a specific item in your CoreDate table, this comes handy and avoid encrypt the entire database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article cover some best praticies of OWASP for secure your data in iOS application's.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/FelipeFMMobile/iOS_OWASP" rel="noopener noreferrer"&gt;Check the github project here.&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;And here’s a challenge for you: Can you change the project to use the private key to securely save an item in Core Data, or maybe perform another cryptographic operation?&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>mobile</category>
      <category>security</category>
    </item>
  </channel>
</rss>
