logo

Database

Non-encrypted confidential information

Need

Secure storage and encryption of confidential information and credentials

Context

• Usage of Swift for iOS and macOS app development

• Usage of UIKit for building modern and responsive user interfaces

• Usage of Foundation for building responsive and customizable web interfaces

• Usage of Firebase for building scalable and real-time web and mobile applications

Description

1. Non compliant code

import UIKit
import Foundation
import Firebase

// Scenario 1: login credentials stored in UserDefaults
class LoginViewController: UIViewController {

    @IBOutlet weak var usernameField: UITextField!...

**Login credentials stored in UserDefaults.** This Swift code is a simple view controller for a login screen. When the login button is tapped, the entered username and password are stored directly in UserDefaults without any encryption. UserDefaults is not a secure place to store sensitive information as it's stored in plain text, so anyone with access to the file system can easily retrieve it. **Data fetched from Firebase stored locally.** The code fetches data from a Firebase Firestore database and stores it locally using UserDefaults. Since the data is stored in plain text, if the device is lost or stolen an attacker could access it without needing to decrypt anything. **Credentials encoded (not encrypted) in Base64.** The `username` and `password` are hardcoded, concatenated, and encoded into Base64 before being printed to the console. Base64 is an encoding, not an encryption algorithm, so anyone who obtains the encoded string can trivially decode it back to the original credentials. **Confidential information encoded (not encrypted) in hexadecimal.** A confidential string is converted to its hexadecimal representation and printed to the console. As with Base64, hexadecimal encoding is reversible by design and provides no real protection for the data. In every case above, the underlying mistake is the same: sensitive data is either left in plain text or merely encoded, never encrypted, before being stored or logged.

2. Steps

• Remove hard-coded credentials and confidential information from the source code.

• Avoid storing confidential information in plain text, and never treat encoding (e.g. Base64, hexadecimal) as a substitute for encryption.

• Use a secure storage mechanism, such as the Keychain, instead of UserDefaults for confidential information and credentials.

• Encrypt confidential information before storing or transmitting it, using a strong algorithm appropriate for the sensitivity of the data (e.g. AES).

• Ensure encryption keys are securely generated, stored, and managed, and are never hardcoded in the application.

• Use secure communication protocols (e.g., HTTPS) when transmitting or fetching confidential information over the network.

• Implement proper authentication and access controls to restrict unauthorized access to confidential information.

• Consider implementing remote wipe or additional data-protection features to mitigate the risk of device theft or loss.

• Regularly review, test, and patch the application and its encryption libraries and dependencies to address security vulnerabilities.

3. Secure code example

import UIKit
import Foundation
import Firebase
import Security
import KeychainSwift
import CommonCrypto

// Scenario 1: login credentials stored in the Keychain...

**Login credentials.** The username and password are converted to `Data` and stored using the Keychain (via `KeychainWrapper`), which is a secure storage mechanism provided by iOS, instead of UserDefaults. Even if an attacker gains access to the device, they cannot retrieve the credentials without the encryption key protecting the Keychain. **Data fetched from Firebase.** The fetched data is serialized to JSON and stored using the `KeychainSwift` wrapper around the iOS Keychain instead of UserDefaults, so it is encrypted at rest instead of sitting in plain text. **Credentials.** Instead of encoding the credentials in Base64 and printing them, `saveCredentials(username:password:)`/`loadCredentials()` store and retrieve them from the Keychain via `SecItemAdd`/`SecItemCopyMatching`, so the plain-text credentials never appear in the source code or the console. **Confidential information.** Instead of hex-encoding the string, `encryptAESData` encrypts it with AES (via `CommonCrypto`'s `CCCrypt`) and returns the result as a base64 string purely for safe transport/display — the actual protection comes from the AES encryption, not the encoding. In a real deployment the encryption key and IV must be generated and stored securely rather than hardcoded as shown here.