Secure your UserDefaults & NSUserDefaults with encryption.
iOS 10+ (tested)
macOS 10.10 (tested)
tv0S 10+ (untested)
watchOS 3+ (untested)
Developers use the UserDefaults mechanism to store default values for their apps. Generally, when you have sensitive information - storing in the UserDefaults is inherently insecure.
One option is to use the Keychain ; using the keychain for app settings can be a bit hacky (say vs. a password or some simple data you want to store).
secure_defaults offers a way to get the benefits of both approaches - storing your app settings (including sensitive ones) in your suite in the UserDefaults, and encrypting the data while doing so!
Using Asymmetric Encryption , secure_defaults creates an asymmetric key using one of the supported key types to encrypt your data, however, it uses a function in the Security.framework that produces a symmetric key and encrypts with that (for performance reasons, especially when working with blobs of data).
Supports:
RSA Encryption
ECDSA Encryption
ECDSA Encryption with the Secure Enclave (if available)
Leveraging Swift 4 's Codable protocol - create your object graph (all conforming to Codable), have your root object conform to a PreferenceDomainType and secure_defaults handles the rest.
There is even a nuke() function to wipe out all the keys data (if you need to).
add to your Package.swift:
dependencies: [
.Package(url: "https://github.com/dcilia/secure-defaults", majorVersion: 1, minor: 0)
])Add to your Cartfile
github "dcilia/secure-defaults"in your Podfile:
pod 'secure-defaults', :git=> 'https://github.com/dcilia/secure-defaults'Using secure_defaults is comprised of the following steps:
Step 1: Create your object conforming to PreferenceDomainType, and call register()
Step 2: Create a provider object, RSAEncryption / ECEncryption (for ECDSA secure enclave, set usesSecureEnclave to true)
Step 3: Call the encrypt / decrypt functions
Step 4: Save your data using the save() function.
Here is an example:
import secure_defaults
class Prefs : Codable {
var name : String = "Luke"
var last = "Skywalker"
var lastOpen = Date()
var isUser = true
}
extension Prefs : PreferenceDomainType {
static var key: String {
return "settings"
}
static var name: String {
return "Test Key Can Delete"
}
static var tag: String {
return "preferences.com.tags"
}
}
let p = Prefs()
p.register()
///RSA Provider Encryption Example:
let provider = RSAEncryption<Prefs>()
do {
let val = try provider.encrypt(input: p)
p.save(encryptedPayload: val)
}
catch {
print(error.localizedDescription)
}
var payload = Prefs.encryptedPayload()
do {
let result = try provider.decrypt(input: payload)
}
catch {
print(error.localizedDescription)
}That's it, you have just encrypted your app settings into a suite on the UserDefaults!