A lightweight wrapper over UserDefaults/NSUserDefaults with an additional layer of AES-256 encryption

Overview

SecureDefaults for iOS, macOS

Build Status Platform Version Carthage compatible Swift Package Manager compatible License

RequirementsUsageInstallationContributingAcknowledgmentsContributingAuthorLicense

SecureDefaults is a wrapper over UserDefaults/NSUserDefaults with an extra AES-256 encryption layer (key size has 256-bit length). It encludes:

  • AES-256 encryption
  • Password stretching with PBKDF2
  • Encrypt-then-hash HMAC
  • Password salting
  • Random IV

The design and strength of all key lengths of the AES algorithm (i.e., 128, 192 and 256) are sufficient to protect classified information up to the SECRET level. TOP SECRET information will require use of either the 192 or 256 key lengths. The implementation of AES in products intended to protect national security systems and/or information must be reviewed and certified by NSA prior to their acquisition and use. [1]

Motivation

  • Avoiding the following behavior https://stackoverflow.com/questions/4747404/delete-keychain-items-when-an-app-is-uninstalled. (Yes, there is still a key, but there is no data)
  • Avoiding additional thinking about there is a good place to store a particular value. (choice between Keychain and UserDefaults)
  • Improving a situation with security on the iOS platform. Many apps I've seen didn't use Keychain. They store all sensitive data in UserDefaults (access tokens, passwords, etc)... At least, this can help to make such apps a bit more secured without pain. Perhaps, if this framework is almost the same as UserDefaults, maybe developers will start using it?
  • It doesn't look good to keep many simple keys in Keychain.

Requirements

  • iOS 8.0+
  • macOS 10.11+
  • Xcode 10.1+
  • Swift 4.2+

Usage

It is pretty simple to use SecureDefaults instead of UserDefaults/NSUserDefaults. In most cases, it is the same thing that is UserDefaults. You just need to set a password to make it work.

Replace the following code:

UserDefaults.standard

by this one:

let defaults = SecureDefaults.shared
// Ensures that a password was not set before. Otherwise, if 
// you set a password one more time, it will re-generate a key. 
// That means that we lose old data as well.
if !defaults.isKeyCreated {
    defaults.password = NSUUID().uuidString // Or any password you wish
}

To use the app and keychain groups:

let defaults = SecureDefaults(suitName: "app.group") // Set a shared app group
defaults.keychainAccessGroup = "keychain.group" // Set a shrared keychain group 
if !defaults.isKeyCreated {
    defaults.password = NSUUID().uuidString // Or any password you wish
}

SecureDefaults is not able to catch that any particular data is encrypted, to obtain a raw value, use the following method:

public func rawObject(forKey defaultName: String) -> Any?

Installation

CocoaPods

SecureDefaults is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'SecureDefaults', '1.0.5' # Swift 5.0
pod 'SecureDefaults', '1.0.0' # Swift 4.2

Carthage

Add this to Cartfile

github "vpeschenkov/SecureDefaults" == 1.0.6 # Swift 5.0
github "vpeschenkov/SecureDefaults" == 1.0.0 # Swift 4.2
$ carthage update

Swift Package Manager

Create a Package.swift file.

// swift-tools-version:4.2

import PackageDescription

let package = Package(
  name: "YourProject",
  dependencies: [
    .package(url: "https://github.com/vpeschenkov/SecureDefaults", "1.0.6")
  ],
  targets: [
    .target(name: "YourProject", dependencies: ["SecureDefaults"])
  ]
)
$ swift build

Contributing

  • If you need help or you'd like to ask a general question, open an issue.
  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Acknowledgments

A big thanks to the following individuals:

Author

Victor Peschenkov, [email protected]

License

SecureDefaults is available under the MIT license. See the LICENSE file for more info.

Comments
  • Fix force type casting crash

    Fix force type casting crash

    Fix force type casting crash

    Summary

    Reading from SecureDefaults resolved crash by optional type casting to Data type

    Requirements

    • [x] I've read and agree to the Code of Conduct.
    • [x] I've written tests to cover the new code and functionality included in this PR.
    opened by usmanjaved1321 2
  • Unable to install via carthage

    Unable to install via carthage

    Description

    When installing via carthage update, I receive the following error message:

    Dependency "SecureDefaults" has no shared framework schemes

    Totally could be something on my end, but I've tried installing this on a fairly vanilla project w/ Carthage and am receiving this error. Any guidance/hints as to what could be going wrong would be appreciated! 🙏

    Requirements (place an x in each of the [ ])

    • [x] I've read and agree to the Code of Conduct.
    • [x] I've read and understood the Contributing guidelines and have done my best effort to follow them.
    • [x] I've searched for any related issues and avoided creating a duplicate issue.

    Bug Report

    Filling out the following details about bugs will help us solve your issue sooner.

    Steps to reproduce:

    1. Add github "vpeschenkov/SecureDefaults" == 1.0.3 to my Cartfile
    2. Run carthage update

    Expected result:

    The framework is downloaded and built.

    Actual result:

    Error message:

    Dependency "SecureDefaults" has no shared framework schemes

    opened by bcongdon 2
  • Persistence Data Question

    Persistence Data Question

    If someone was to delete the app off of their device. If they reinstalled the application would these key value pairs still exist and able to be retrieved?

    opened by willm132 1
  • Removed UnsafePointer warning

    Removed UnsafePointer warning

    Summary

    Describe the goal of this PR. Mention any related Issue numbers.

    Requirements (place an x in each [ ])

    • [ ] I've read and agree to the Code of Conduct.
    • [ ] I've written tests to cover the new code and functionality included in this PR.
    opened by khush004 1
  • AES256 Encryption Missing

    AES256 Encryption Missing

    Description

    Checking into the ~Library/Containers/myapp/Data/Library/Preferences/myappbundleid.plist file (the UserDefaults storage space) of my app, I see an unencrypted value, even though I used SecureDefaults. This kind of defeats the purpose of a secure alternative to stock UserDefaults.

    Requirements (place an x in each of the [ ])

    • [X] I've read and agree to the Code of Conduct.
    • [X] I've read and understood the Contributing guidelines and have done my best effort to follow them.
    • [X] I've searched for any related issues and avoided creating a duplicate issue.

    Bug Report

    Filling out the following details about bugs will help us solve your issue sooner.

    Reproducible in:

    SecureDefaults version: 1.0.6

    iOS version: 15.3.1, 15.3, 15.2 (Tested Versions)

    Steps to reproduce:

    1. Store a value with SecureDefaults.standard.set("This value will be unencrypted.", forKey: "mykey")
    2. If tested natively on Mac, go to ~/Library/Containers/, choose your app subdirectory and go to Data/Library/Preferences and open the .plist file with the app bundle ID as its name.
    3. Check your key and its value, which will be shown in plain text, unencrypted.

    Expected result:

    An encrypted, unreadable and secure value.

    Actual result:

    A completely readable and unencrypted value that could be normally set by UserDefaults.

    Attachments:

    Demo Project Demo App SecureDefaults.zip

    opened by Terabyte1385 1
  • Fix: Fatal Error: `try!`

    Fix: Fatal Error: `try!`

    Summary

    This PR is to address a fatal issue : fatal error: 'try!' expression unexpectedly raised an error

    Requirements (place an x in each [ ])

    • [x] I've read and agree to the Code of Conduct.
    • [x] I've written tests to cover the new code and functionality included in this PR.
    opened by MalcolmnDEV 1
  • Update readme

    Update readme

    fix a simple typo

    Summary

    Describe the goal of this PR. Mention any related Issue numbers.

    Requirements (place an x in each [ ])

    • [ x] I've read and agree to the Code of Conduct.
    • [ ] I've written tests to cover the new code and functionality included in this PR.
    opened by stephenfeather 1
  • fix typo.

    fix typo.

    Summary

    Describe the goal of this PR. Mention any related Issue numbers.

    Requirements (place an x in each [ ])

    • [x] I've read and agree to the Code of Conduct.
    • [ ] I've written tests to cover the new code and functionality included in this PR.
    duplicate 
    opened by SURYAKANTSHARMA 1
  • Typo mistake  README.md

    Typo mistake README.md

    Summary

    Describe the goal of this PR. Mention any related Issue numbers.

    Requirements (place an x in each [ ])

    • [x] I've read and agree to the Code of Conduct.
    • [x] I've written tests to cover the new code and functionality included in this PR.
    opened by sairamkotha 1
  • Crash: Force type cast to Data

    Crash: Force type cast to Data

    Description

    Application crashing if the object against some key is not of Data type, due to force type casting.

    Requirements

    • [x] I've read and agree to the Code of Conduct.
    • [x] I've read and understood the Contributing guidelines and have done my best effort to follow them.
    • [x] I've searched for any related issues and avoided creating a duplicate issue.

    Bug Report

    private func secretObject(forKey defaultName: String) -> Any?

    Above method is to read some object from UserDefaults and its forcefully type casting objects to Data type. If some older version of App or some other component has stored some other data type object in UserDefaults with same key, then application is crashing.

    Reproducible in:

    SecureDefaults version: 1.0.7

    iOS version: 15.5

    Steps to reproduce:

    1. Store some object in UserDefaults other than Data type
    2. Read the object using SecureDefaults using same key
    3. Application will crashing, as its force type casting to Data type

    Expected result:

    If object fetched from UserDefaults is not of Data type return that object as it is, and return nil if nothing found, although the method is returning Any?

    Actual result:

    If fetched object is not of Data type application crashes

    What actually happened

    Attachments:

    Screenshot 2022-09-28 at 4 44 49 PM
    opened by usmanjaved1321 0
  • Update schemes

    Update schemes

    Summary

    Close #4

    Requirements (place an x in each [ ])

    • [x] I've read and agree to the Code of Conduct.
    • [x] I've written tests to cover the new code and functionality included in this PR.
    opened by vpeschenkov 0
  • NSKeyedArichiver error

    NSKeyedArichiver error

    Description

    Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x600002592800' terminating with uncaught exception of type NSException

    Requirements (place an x in each of the [ ])

    • [x] I've read and agree to the Code of Conduct.
    • [x] I've read and understood the Contributing guidelines and have done my best effort to follow them.
    • [x] I've searched for any related issues and avoided creating a duplicate issue.

    Bug Report

    The reason of the crash is the following function: private func setSecret (_ value: Any?, forKey defaultName: String) { if let value = value { let data = NSKeyedArchiver.archivedData (withRootObject: value) super.set (try? encrypter?.encrypt (data), forKey: defaultName) return } super.set (nil, forKey: defaultName) }

    Only NSCoding conforming objects can be stored in NSKeyedArchive as far as I know.

    Reproducible in:

    SecureDefaults version: 1.0.7

    iOS version: 15.5

    Steps to reproduce:

    1. set value with type that is not available for obj-c
    2. get crash

    Expected result:

    It should save the value

    Actual result:

    crash

    opened by thegalkin 0
Releases(1.1.0)
Owner
Victor Peschenkov
----
Victor Peschenkov
Effortlessly synchronize UserDefaults over iCloud.

Zephyr ??️ Effortlessly sync UserDefaults over iCloud About Zephyr synchronizes specific keys and/or all of your UserDefaults over iCloud using NSUbiq

Arthur Ariel Sabintsev 841 Dec 23, 2022
⚙️ A tiny property wrapper for UserDefaults. Only 60 lines of code.

⚙️ A tiny property wrapper for UserDefaults. Only 60 lines of code. import Persistent extension UserDefaults { // Optional property @Per

Mezhevikin Alexey 6 Sep 28, 2022
SQLite.swift - A type-safe, Swift-language layer over SQLite3.

SQLite.swift provides compile-time confidence in SQL statement syntax and intent.

Stephen Celis 8.7k Jan 3, 2023
Modern Swift API for NSUserDefaults

SwiftyUserDefaults Modern Swift API for NSUserDefaults SwiftyUserDefaults makes user defaults enjoyable to use by combining expressive Swifty API with

Luke 4.7k Jan 9, 2023
TypedDefaults is a utility library to type-safely use NSUserDefaults.

TypedDefaults TypedDefaults is a utility library to type-safely use NSUserDefaults. Motivation The talk Keep Calm and Type Erase On by Gwendolyn Westo

Kazunobu Tasaka 110 Feb 6, 2022
📕A single value proxy for NSUserDefaults, with clean API.

OneStore A single value proxy for NSUserDefaults, with clean API. With OneStore… Create one proxy(an OneStore object) for each NSUserDefaults value. M

Muukii 27 May 12, 2022
Modern Swift API for NSUserDefaults

SwiftyUserDefaults Modern Swift API for NSUserDefaults SwiftyUserDefaults makes user defaults enjoyable to use by combining expressive Swifty API with

Luke 4.7k Jan 9, 2023
Save NSObject into NSUserDefaults in one-line, auto class mapping

Akaibu What is it ? Archive any class in just ONE-LINE of code. Automatically map class's properties under the hood. Drop in replacement of NSObject S

Roy Tang 16 Jun 21, 2021
NSUserDefaults with Wings!

#Palau: NSUserDefaults with Wings! Features | Included Types | Installation | Validators and Defaults | Custom Types | DidSet Callback | ------- Featu

symentis GmbH 387 Jun 29, 2022
A Swift wrapper for system shell over posix_spawn with search path and env support.

AuxiliaryExecute A Swift wrapper for system shell over posix_spawn with search path and env support. Usage import AuxiliaryExecute AuxiliaryExecute.l

Lakr Aream 11 Sep 13, 2022
Prephirences is a Swift library that provides useful protocols and convenience methods to manage application preferences, configurations and app-state. UserDefaults

Prephirences - Preϕrences Prephirences is a Swift library that provides useful protocols and convenience methods to manage application preferences, co

Eric Marchand 557 Nov 22, 2022
Simple, Strongly Typed UserDefaults for iOS, macOS and tvOS

简体中文 DefaultsKit leverages Swift 4's powerful Codable capabilities to provide a Simple and Strongly Typed wrapper on top of UserDefaults. It uses less

Nuno Dias 1.4k Dec 26, 2022
Modern interface to UserDefaults + Codable support

Default Modern interface to UserDefaults + Codable support What is Default? Default is a library that extends what UserDefaults can do by providing ex

Nicholas Maccharoli 475 Dec 20, 2022
Why not use UserDefaults to store Codable objects 😉

tl;dr You love Swift's Codable protocol and use it everywhere, who doesn't! Here is an easy and very light way to store and retrieve -reasonable amoun

Omar Albeik 452 Oct 17, 2022
Swifty and modern UserDefaults

Defaults Swifty and modern UserDefaults Store key-value pairs persistently across launches of your app. It uses NSUserDefaults underneath but exposes

Sindre Sorhus 1.3k Dec 31, 2022
🔍 Browse and edit UserDefaults on your app

UserDefaults-Browser Browse and edit UserDefaults on your app. (SwiftUI or UIKit) Browse Edit (as JSON) Edit (Date) Export Note: We recommend to use S

Yusuke Hosonuma 25 Nov 3, 2022
Nora is a Firebase abstraction layer for FirebaseDatabase and FirebaseStorage

Nora is a Firebase abstraction layer for working with FirebaseDatabase and FirebaseStorage. Stop spending all that time cleaning up your view controll

Steven Deutsch 273 Oct 15, 2022
Analytics layer abstraction, abstract analytics reporters and collect domain-driven analytic events.

?? Tentacles Current State: Work in Progress Documentation & Tests(100% completed, but needs refactoring and structuring) started but not done yet, im

Patrick 3 Dec 2, 2022
A stand-alone Swift wrapper around the mongo-c client library, enabling access to MongoDB servers.

This package is deprecated in favour of the official Mongo Swift Driver. We advise users to switch to that pack

PerfectlySoft Inc. 54 Jul 9, 2022