A simple wrapper for the iOS Keychain to allow you to use it in a similar fashion to User Defaults. Written in Swift.

Overview

SwiftKeychainWrapper

A simple wrapper for the iOS / tvOS Keychain to allow you to use it in a similar fashion to User Defaults. Written in Swift.

Provides singleton instance that is setup to work for most needs. Use KeychainWrapper.standard to access the singleton instance.

If you need to customize the keychain access to use a custom identifier or access group, you can create your own instance instead of using the singleton instance.

By default, the Keychain Wrapper saves data as a Generic Password type in the iOS Keychain. It saves items such that they can only be accessed when the app is unlocked and open. If you are not familiar with the iOS Keychain usage, this provides a safe default for using the keychain.

Users that want to deviate from this default implementation, now can do so in version 2.0 and up. Each request to save/read a key value now allows you to specify the keychain accessibility for that key.

General Usage

Add a string value to keychain:

let saveSuccessful: Bool = KeychainWrapper.standard.set("Some String", forKey: "myKey")

Retrieve a string value from keychain:

let retrievedString: String? = KeychainWrapper.standard.string(forKey: "myKey")

Remove a string value from keychain:

let removeSuccessful: Bool = KeychainWrapper.standard.removeObject(forKey: "myKey")

Custom Instance

When the Keychain Wrapper is used, all keys are linked to a common identifier for your app, called the service name. By default this uses your main bundle identifier. However, you may also change it, or store multiple items to the keychain under different identifiers.

To share keychain items between your applications, you may specify an access group and use that same access group in each application.

To set a custom service name identifier or access group, you may now create your own instance of the keychain wrapper as follows:

let uniqueServiceName = "customServiceName"
let uniqueAccessGroup = "sharedAccessGroupName"
let customKeychainWrapperInstance = KeychainWrapper(serviceName: uniqueServiceName, accessGroup: uniqueAccessGroup)

The custom instance can then be used in place of the shared instance or static accessors:

let saveSuccessful: Bool = customKeychainWrapperInstance.set("Some String", forKey: "myKey")

let retrievedString: String? = customKeychainWrapperInstance.string(forKey: "myKey")

let removeSuccessful: Bool = customKeychainWrapperInstance.removeObject(forKey: "myKey")

Subscript usage

Keychain can also be accessed with subscript as it is in dictionary. Keys can be predefined and listed in one place for convenience.

Firstly, let's define the key to use later.

extension KeychainWrapper.Key {
    static let myKey: KeychainWrapper.Key = "myKey"
}

And now we can use this key as follows:

KeychainWrapper.standard[.myKey] = "some string"

let myValue: String? = KeychainWrapper.standard[.myKey]

KeychainWrapper.standard.remove(forKey: .myKey)

Accessibility Options

By default, all items saved to keychain can only be accessed when the device is unlocked. To change this accessibility, an optional withAccessibility param can be set on all requests. The enum KeychainItemAccessibilty provides an easy way to select the accessibility level desired:

KeychainWrapper.standard.set("Some String", forKey: "myKey", withAccessibility: .AfterFirstUnlock)

Synchronizable Option

By default, all items saved to keychain are not synchronizable, so they are not synced with the iCloud. To change this, an isSynchronizable bool param can be set on all requests. You need the item to be synchronized with the iCloud if you want to have it on all of your devices:

KeychainWrapper.standard.set("Some String", forKey: "myKey", isSynchronizable: true)

Important: You can't modify value for key if it was previously set with different accessibility option. Remove the value for key and set it with new accessibility option. (Otherwise the value will not change).
For example:

KeychainWrapper.standard.set("String one", forKey: "myKey", withAccessibility: .AfterFirstUnlock)
KeychainWrapper.standard.removeObject(forKey: "myKey")
KeychainWrapper.standard.set("String two", forKey: "myKey", withAccessibility: .Always)

Installation

CocoaPods

You can use CocoaPods to install SwiftKeychainWrapper by adding it to your Podfile:

use_frameworks!
platform :ios, '8.0'

target 'target_name' do
   pod 'SwiftKeychainWrapper'
end

To use the keychain wrapper in your app, import SwiftKeychainWrapper into the file(s) where you want to use it.

import SwiftKeychainWrapper

Carthage

You can use Carthage to install SwiftKeychainWrapper by adding it to your Cartfile.

Swift 3.0:

github "jrendel/SwiftKeychainWrapper" ~> 3.0

Swift 2.3:

github "jrendel/SwiftKeychainWrapper" == 2.1.1

Swift Package Manager

You can use Swift Package Manager to install SwiftKeychainWrapper using Xcode:

  1. Open your project in Xcode

  2. Click "File" -> "Swift Packages" -> "Add Package Dependency..."

  3. Paste the following URL: https://github.com/jrendel/SwiftKeychainWrapper

  4. Click "Next" -> "Next" -> "Finish"

Manually

Download and drop KeychainWrapper.swift and KeychainItemAcessibility.swift into your project.

Release History

  • 4.1 Added conditional logic for CGFloat accessories for when package is used where CGFloat is not available

  • 4.0 Updated with SPM support and other community PRs. Minimum iOS version is now 9.0.

  • 3.4

  • Changed how Swift version is defined for CocoaPods

  • 3.3

  • Updates for Swift 5.0 and Xcode 10.2

  • 3.2

  • Updates for Swift 4.2 and Xcode 10

  • 3.1

    • Updates for Swift 3.1
  • 3.0.1

    • Added a host app for the unit tests to get around the issue with keychain access not working the same on iOS 10 simulators
    • Minor update to readme instructions
  • 3.0

    • Swift 3.0 update. Contains breaking API changes. 2.2.0 and 2.2.1 are now rolled into 3.0
  • 2.2.1 (Removed from Cocoapods)

    • Syntax updates to be more Swift 3 like
  • 2.2 (Removed from Cocoapods)

    • Updated to support Swift 3.0
    • Remove deprecated functions (static access)
  • 2.1

    • Updated to support Swift 2.3
  • 2.0

    • Further changes to more closely align the API with how NSUserDefaults works. Access to the default implementation is now done through a singleton instance. Static accessors have been included that wrap this shared instance to maintain backwards compatibility. These will be removed in the next update
    • Ability to change keychain service name identifier and access group on the shared instance has been deprecated. Users now have the ability to create their own instance of the keychain if they want to customize these.
    • Addtional options have been provided to alter the keychain accessibility for each key value saved.
  • 1.0.11

    • Update for Swift 2.0
  • 1.0.10

    • Update License info. Merged Pull Request with Carthage support.
  • 1.0.8

    • Update for Swift 1.2
  • 1.0.7

    • Determined that once provisioned correctly for access groups, using KeychainWrapper on the simulator with access groups works. So I removed the simulator related check and unit tests previously added.
  • 1.0.6

    • Support for Access Groups

    • SwiftKeychainWrapperExample has been updated to show usage with an Access Group: https://github.com/jrendel/SwiftKeychainWrapperExample

    • Access Groups do not work on the simulator. Apps that are built for the simulator aren't signed, so there's no keychain access group for the simulator to check. This means that all apps can see all keychain items when run on the simulator. Attempting to set an access group will result in a failure when attempting to Add or Update keychain items. Because of this, the Keychain Wrapper detects if it is being using on a simulator and will not set an access group property if one is set. This allows the Keychain Wrapper to still be used on the simulator for development of your app. To properly test Keychain Access Groups, you will need to test on a device.

  • 1.0.5

    • This version converts the project to a proper Swift Framework and adds a podspec file to be compatible with the latest CocoaPods pre-release, which now supports Swift.

    • To see an example of usage with CocoaPods, I've created the repo SwiftKeychainWrapperExample: https://github.com/jrendel/SwiftKeychainWrapperExample

  • 1.0.2

    • Updated for Xcode 6.1

I've been using an Objective-C based wrapper in my own projects for the past couple years. The original library I wrote for myself was based on the following tutorial:

http://www.raywenderlich.com/6475/basic-security-in-ios-5-tutorial-part-1

This is a rewrite of that code in Swift.

Carthage compatible

Comments
  • Add podspec File to use this Library with Cocoapods (branch: swift)

    Add podspec File to use this Library with Cocoapods (branch: swift)

    Hi,

    i added a podspec File to use your Library with Cocoapods (only if you use the swift-branch of Cocoapods like described here http://swiftwala.com/cocoapods-is-ready-for-swift/) But its not workin, i can install your Library with "bundle exec pod install" if defined in my Podfile, but i cant use it because a framework class/module called "KeychainWrapper" allready exists.

    opened by AndreasBoehm 14
  • object(forKey:..) does not work anymore or has a new behaviour in swift 3.

    object(forKey:..) does not work anymore or has a new behaviour in swift 3.

    Hey,

    So I have done some more testing with your updated version and its not saving data anymore.

    It returns a successful bool on the set method but on next launch all data is gone again. So ...object(forKey: ...) doesnt work anymore.

    Have you made any changes because when I upgraded the project to swift 3 myself I did not have that problem.

    Whats going on?

    opened by crashoverride777 11
  • Support SecClass values other than kSecClassGenericPassword

    Support SecClass values other than kSecClassGenericPassword

    Flexibility could be provided by supporting the other possible values (internet password, certificate, key, identity). An enum could be used to wrap the CFString constant values and the KeychainWrapper public methods could either be overloaded or take an optional parameter.

    To take this even further, an "options" type could be used as a parameter to wrap the SecClass and any other useful options, such as whether the device must be unlocked for access and whether TouchID is needed to retrieve the item.

    I've begun implementation of these features in my own fork and can provide samples (or a pull request) if you're open to these ideas.

    opened by jamesmblair 10
  • Set-function returning false?

    Set-function returning false?

    Hi there,

    My code has been working fine until now, suddenly these lines returns false:

    let ops: Bool = KeychainWrapper.defaultKeychainWrapper.set(ops, forKey: "ops")
    let jop: Bool = KeychainWrapper.defaultKeychainWrapper.set(jop, forKey: "jop")
    

    I use cocoapods, and this in the Podfile:

    pod 'SwiftKeychainWrapper', :git => 'https://github.com/jrendel/SwiftKeychainWrapper.git', :branch => 'master'

    Any ideas?

    opened by Dbigshooter 9
  • cocoapods version update

    cocoapods version update

    The current version (2.2.0) has not been updated on cocoapods (https://cocoapods.org/pods/SwiftKeychainWrapper) and cannot be installed using pods for now. Please update the version from 2.0 to 2.2 over there.

    opened by shashankcodes 9
  • Odd bug

    Odd bug

    Haven't fully investigated but there is a rather odd bug with this Wrapper. Some phones will save to keychain using SwiftKeychainWrapper, others will not. There is no correlation between phones or versions, some iPhones 5s's the wrapper works, other it does not. This applies to all devices - 6, 6 plus, 4s.

    To further describe - Saving to keychain in our test group worked for an iPhone 5s on 8.1.3 - on another 5s on 8.1.3 it did not. One iPhone 6 it did not work for (also on 8.1.3), on an iPhone 5 on 8.1.2 it did work.

    Bug is also not related to settings or anything related to settings within said app, it is isolated to SwiftKeychainWrapper.

    opened by jtezanos 9
  • KeychainWrapper with Swift Compiler optimizations

    KeychainWrapper with Swift Compiler optimizations "Fastest"

    When packaging up a release IPA (IE: for testflight) KeychainWrapper.stringForKey() returns a nil value. It passes without error, but the value is blank.

    For instance:

    KeychainWrapper.setString("APPLE", forKey: "FRUIT")
    var fruit = KeychainWrapper.stringForKey("FRUIT")
    var alert:UIAlertView = UIAlertView(title: "FRUIT", message: "\(fruit)", delegate: self, cancelButtonTitle: "Ok")
    alert.show()
    

    Took a lot of searching, but I stumbled across: http://stackoverflow.com/questions/26355630/swift-keychain-and-provisioning-profiles

    Disabling the optimizations for the release target remedied the problem, but I am wondering if there is something that can be done to fix whatever is breaking when optimized away. (Might just have to wait for an apple fix?)

    opened by matthewvermaak 9
  • xCode8 with Swift2.3 returns false

    xCode8 with Swift2.3 returns false

    Hi @jrendel , I have a problem with saving values to Keychain, below is the line I'm using, and it always returns false in xCode8 and Swift2.3 (I can't use Swift 3 at the moment because some other frameworks are not updated) Just to mention, it all worked with xCode7 and Swift2.2 on iOS9.3 simulator, but now I'm using iOS10 simulator, maybe this could be the issue? (downloading 9.3 simulators at the moment)

    let isSaveSuccessfulToken: Bool = KeychainWrapper.defaultKeychainWrapper().setString(token, forKey: "token")

    I'm using Carthage and I tried with the following
    github "jrendel/SwiftKeychainWrapper" github "jrendel/SwiftKeychainWrapper" "master" github "jrendel/SwiftKeychainWrapper" == 2.1.0 github "jrendel/SwiftKeychainWrapper" "Swift2.3"

    all compiled to Swift2.3 using carthage update --platform iOS --toolchain com.apple.dt.toolchain.Swift_2_3 SwiftKeychainWrapper which builds successfully (also used with some other frameworks that work now)

    Tnx

    opened by kristijanexads 8
  • Calling stringForKey sometimes returns nil for keys that previously worked

    Calling stringForKey sometimes returns nil for keys that previously worked

    I'm getting some strange behavior when accessing data. I have a static method that I use to retrieve a stored auth token for an API call. This static method is called a couple times and returns the data I expect. From one of my view controllers though it's returning nil.

    I make the exact same call for the exact same keys. Two calls return data and the last one does not. I'm getting a return status of -34018. I'm not sure what that error code is.

    opened by bedaronco 8
  • add a removeAllKeys or similar

    add a removeAllKeys or similar

    First, congrats for the wrapper. Simple and efficient.

    I just missed out one function: a removeAllKeys() function that would erase all Keychain items. That is very useful to clean the Keychain on the app first run.

    opened by renatosc 7
  • This is a Swift wrapper around the ObjC wrapper, not a Swift re-write

    This is a Swift wrapper around the ObjC wrapper, not a Swift re-write

    How can this be a Swift rewrite when you're still using the main ObjC method inside of it. return KeychainObjcWrapper.dataForDictionary(keychainQueryDictionary)

    opened by lfaoro 7
  • removeAllKeys does not delete any items that were saved with synchronizable as true

    removeAllKeys does not delete any items that were saved with synchronizable as true

    The query dict passed to SecItemDelete in removeAllKeys does not contain any value for the synchronizable attribute, so it actually defaults to false, deleting only those items that are false, and leaving out items that were saved with true. The same also applies with the wipeKeychain method. We should add a value for sync to specify any.

    From the documentation on the sync attribute:

    If the key is not supplied, or has a value of kCFBooleanFalse, then no synchronizable items are added or returned. Use kSecAttrSynchronizableAny to query for both synchronizable and non-synchronizable results.

    opened by MujiP 0
  • Apple SignIn email is not retrieving

    Apple SignIn email is not retrieving

    I had saved apple identifier and its hidden email in Keychain using other utility. Now while trying to fetch using this library, I am able to get apple identifier, but that email address is not retrieving. Used data and string format to fetch and data is also 0 bytes.

    opened by chawda 0
  • Incrementing and saving do not work properly

    Incrementing and saving do not work properly

    I am testing my app on my phone via Xcode 13.3.1.

    I removeAllKeys upon launch, then set a new integer value for a consumable product.

    KeychainWrapper.standard.integer(forKey: productIdentifier) ?? 0

    1. This value is zero (0) when I first read it.
    2. I read it, increment it by one and save it. Then read it again. It reads 2 instead of 1.
    3. If I repeat step 2, I still get 2.

    Rebooting the phone changed nothing.

    Does anybody experience something similar?

    opened by harmancode 1
  • XCTestCase: set NewValue return False

    XCTestCase: set NewValue return False

    Hi, I try save string data on keychain, however, the function set return False.

    Any idea ?

    I post the code:

        public static var tokenSession: String {
            set {
                KeychainWrapper.standard.set(
                    newValue,
                    forKey: "sm_token_session_key",
                    withAccessibility: .always,
                    isSynchronizable: true
                )
            }
            get {
                KeychainWrapper.standard.string(
                    forKey: "sm_token_session_key",
                    withAccessibility: .always,
                    isSynchronizable: true
                ) ?? .empty
            }
        }
    
    opened by javierbc121086 2
  • I've noticed, that if i store something and immediately retrieve from other function, it not manage to return appropriate value.

    I've noticed, that if i store something and immediately retrieve from other function, it not manage to return appropriate value.

    I've noticed, that if i store something and immediately retrieve from other function, it not manage to return appropriate value.

    Originally posted by @NikKovIos in https://github.com/jrendel/SwiftKeychainWrapper/issues/112#issuecomment-421295143

    opened by glock47 0
  • Callback on keychain value change for given key

    Callback on keychain value change for given key

    Hi! Thanks a lot for such a great library!

    I would like to see if there could be an integration with Swift Combine which would allow getting updates to the Keychain reactively as a stream of changes when they happen. What is the feasibility of that?

    Any other way to expose callback when a change happens like KVO, Notification or delegate would also be a great start.

    opened by LeonidKokhnovich 0
Owner
Jason
Jason
A wrapper to make it really easy to deal with iOS, macOS, watchOS and Linux Keychain and store your user's credentials securely.

A wrapper (written only in Swift) to make it really easy to deal with iOS, macOS, watchOS and Linux Keychain and store your user's credentials securely.

Ezequiel Aceto 2 Mar 29, 2022
Simple Swift wrapper for Keychain that works on iOS, watchOS, tvOS and macOS.

KeychainAccess KeychainAccess is a simple Swift wrapper for Keychain that works on iOS and OS X. Makes using Keychain APIs extremely easy and much mor

Kishikawa Katsumi 7.2k Dec 30, 2022
A simple Swift Keychain Wrapper for iOS, watchOS, and OS X.

Latch A simple Swift 2.0 Keychain Wrapper for iOS, watchOS 2, and OS X. Usage A proper example of how to use Latch can be seen in the tests. import La

Danielle 56 Oct 25, 2022
Simple Objective-C wrapper for the keychain that works on Mac and iOS

SAMKeychain SAMKeychain is a simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system Keyc

Sam Soffes 5.4k Dec 29, 2022
A really simple key-value wrapper for keychain.

PlainKeychain A really simple key-value wrapper for keychain. Features ✅ Key-value pairs using kSecClassGenericPassword. ❌ Internet passwords (kSecCla

Benjamin Barnard 0 Nov 27, 2021
KeyClip is yet another Keychain library written in Swift.

KeyClip KeyClip is yet another Keychain library written in Swift. Features Multi Types ( String / NSDictionary / NSData ) Error Handling Settings ( kS

Shinichiro Aska 43 Nov 6, 2022
Helper functions for saving text in Keychain securely for iOS, OS X, tvOS and watchOS.

Helper functions for storing text in Keychain for iOS, macOS, tvOS and WatchOS This is a collection of helper functions for saving text and data in th

Evgenii Neumerzhitckii 2.3k Dec 28, 2022
A powerful, protocol-oriented library for working with the keychain in Swift.

Locksmith A powerful, protocol-oriented library for working with the keychain in Swift. ?? iOS 8.0+ ?? Mac OS X 10.10+ ⌚️ watchOS 2 ?? tvOS ?? I make

Matthew Palmer 2.9k Dec 21, 2022
Generate passwords and save them in Keychain. Made with SwiftUI.

lockd Generate strong passwords and save them in Keychain. Join lockd Beta on TestFlight: https://testflight.apple.com/join/xJ5AlvS3 Features: Generat

Iliane 56 Dec 29, 2022
A wrapper for Apple's Common Crypto library written in Swift.

IDZSwiftCommonCrypto A Swift wrapper for Apple's CommonCrypto library. IDZSwiftCommonCrypto works with both CocoaPods and Cathage. For more details on

idz 472 Dec 12, 2022
To compare the pictures and detect a similar face.

AWS Face Reckognition To compare the pictures and detect a similar face. Project Created & Maintained By MultiQoS Pvt. Ltd. Demo Screen.Recording.2022

MultiQoS 24 Sep 16, 2022
Very simple swift wrapper for Biometric Authentication Services (Touch ID) on iOS.

SimpleTouch Very simple swift wrapper for Biometric Authentication Services (Touch ID) on iOS. Sample Project There is a SimpleTouchDemo target define

Simple Machines 117 Nov 15, 2022
Swift Package for fetching approximate user location without asking for their permission 👺 .

Earendil Swift Package for fetching approximate user location without asking for their permission ?? . Get their country, subregion or continent with

Przemysław Jabłoński 4 Sep 3, 2021
Helper/wrapper for mautrix-imessage for jailbroken devices

Brooklyn This readme is out-of-date. Blame Ethan, he's working on it. Components Rubicon "The die is cast." Crosses Apple's last river between IMCore

Ethan Chaffin 11 Jun 24, 2022
Wrapper class for handling all tasks related to RSA cryptography

RSAWrapper Wrapper class for handling all tasks related to RSA cryptography USAG

null 1 Dec 24, 2021
Swift-cuckoo-collections - Cross-platform Swift dictionaries & sets that use a cuckoo hashing algorithm

CuckooCollections A Swift package for open-addressed sets and dictionaries that

Christopher Richez 0 Aug 2, 2022
Safe and easy to use crypto for iOS and macOS

Swift-Sodium Swift-Sodium provides a safe and easy to use interface to perform common cryptographic operations on macOS, iOS, tvOS and watchOS. It lev

Frank Denis 483 Jan 5, 2023
CoreML-Face-Parsing - how to use face-parsing CoreML model in iOS

CoreML-Face-Parsing The simple sample how to use face-parsing CoreML model in iO

MLBoy 6 Oct 25, 2022
An easy-to-use, open-source two-factor authentication app designed specifically for iOS.

Tofu An easy-to-use, open-source two-factor authentication app designed specifically for iOS. Tofu generates one-time passwords to help you protect yo

Calle Luks 380 Jan 8, 2023