SecureDefaults is a wrapper over UserDefaults/NSUserDefaults with an extra AES-256 encryption layer

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.5 # 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.4")
  ],
  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
An Objc/Swift Developer
Victor Peschenkov
SwiftyUserDefaults - Modern Swift API for NSUserDefaults

SwiftyUserDefaults makes user defaults enjoyable to use by combining expressive Swifty API with the benefits of static typing. Define your keys in one place, use value types easily, and get extra safety and convenient compile-time checks for free.

Luke 4.7k Dec 27, 2022
Default is a Modern interface to UserDefaults + Codable support

Default is a library that extends what UserDefaults can do by providing extensions for saving custom objects that conform to Codable and also providing a new interface to UserDefaults described below, via the protocol DefaultStorable. You can use only the Codable support extensions or the DefaultStorable protocol extensions or both. (or none, that's cool too)

Nicholas Maccharoli 475 Dec 20, 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 Jan 6, 2023
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 than 70 lines of code to acomplish this.

Nuno Dias 1.4k Dec 26, 2022
A lightweight wrapper over UserDefaults/NSUserDefaults with an additional layer of AES-256 encryption

SecureDefaults for iOS, macOS Requirements • Usage • Installation • Contributing • Acknowledgments • Contributing • Author • License SecureDefaults is

Victor Peschenkov 216 Dec 22, 2022
CCCryptor (AES encryption) wrappers for iOS and Mac in Swift. -- For ObjC, see RNCryptor/RNCryptor-objc

RNCryptor Cross-language AES Encryptor/Decryptor data format. The primary targets are Swift and Objective-C, but implementations are available in C, C

null 3.3k Dec 30, 2022
RSA public/private key generation, RSA, AES encryption/decryption, RSA sign/verify in Swift with CommonCrypto in iOS and OS X

SwCrypt Create public and private RSA keys in DER format let (privateKey, publicKey) = try! CC.RSA.generateKeyPair(2048) Convert them to PEM format l

soyer 695 Dec 8, 2022
CCCryptor (AES encryption) wrappers for iOS and Mac in Swift. -- For ObjC, see RNCryptor/RNCryptor-objc

RNCryptor Cross-language AES Encryptor/Decryptor data format. The primary targets are Swift and Objective-C, but implementations are available in C, C

null 3.3k Jan 7, 2023
ChatSecure is a free and open source encrypted chat client for iOS that supports OTR and OMEMO encryption over XMPP.

ChatSecure ChatSecure is a free and open source XMPP messaging client for iOS that integrates OTR and OMEMO encrypted messaging support, and has optio

ChatSecure 3.1k Dec 31, 2022
Zephyr synchronizes specific keys and/or all of your UserDefaults over iCloud using NSUbiquitousKeyValueStore.

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

Arthur Ariel Sabintsev 845 Jan 6, 2023
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
Light wrapper of UIButton that allows extra customization for tvOS

FocusTvButton Light wrapper of UIButton that allows extra customization for tvOS If you would like to have the same level of customization in tablevie

David Cordero 68 Nov 12, 2022
Light wrapper of UITableViewCell that allows extra customization for tvOS

TvOSCustomizableTableViewCell Light wrapper of UITableViewCell that allows extra customization for tvOS If you would like to have the same level of cu

Zattoo 31 Nov 9, 2022
UICKeyChainStore is a simple wrapper for Keychain on iOS, watchOS, tvOS and macOS. Makes using Keychain APIs as easy as NSUserDefaults.

UICKeyChainStore UICKeyChainStore is a simple wrapper for Keychain that works on iOS and OS X. Makes using Keychain APIs as easy as NSUserDefaults. Lo

Kishikawa Katsumi 3.1k Dec 28, 2022
Heimdall is a wrapper around the Security framework for simple encryption/decryption operations.

Heimdall In Norse mythology, Heimdall is the gatekeeper of Bifröst, the rainbow road connecting Midgard, realm of the humans, to Asgard, the realm of

Henri Normak 393 Nov 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
🛶Shallows is a generic abstraction layer over lightweight data storage and persistence.

Shallows Shallows is a generic abstraction layer over lightweight data storage and persistence. It provides a Storage<Key, Value> type, instances of w

Oleg Dreyman 620 Dec 3, 2022
Reactive WebSockets - A lightweight abstraction layer over Starscream to make it reactive.

RxWebSocket Reactive extensions for websockets. A lightweight abstraction layer over Starscream to make it reactive. Installation RxWebSocket is avail

Flávio Caetano 57 Jul 22, 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
MapTeam - A type-safe, Swift-language layer over SQLite3

SQLite.swift A type-safe, Swift-language layer over SQLite3. SQLite.swift provid

Théotime 0 Jan 18, 2022