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
Keychain - Keychain wrapper with swift

Keychain wrapper. Store a value as a generic password: let account = "an-arbitra

Alejandro Ramirez 0 Mar 14, 2022
Valet lets you securely store data in the iOS, tvOS, or macOS Keychain without knowing a thing about how the Keychain works. It’s easy. We promise.

Valet Valet lets you securely store data in the iOS, tvOS, watchOS, or macOS Keychain without knowing a thing about how the Keychain works. It’s easy.

Square 3.8k Jan 4, 2023
A keychain wrapper that is so easy to use that your cat could use it.

A keychain wrapper that is so easy to use that your cat could use it.

HyperRedink 71 Oct 15, 2022
A Layer-2 framework built over Keychain API which helps in using Keychain in all your Apple devices with easiness and flexibility.

Keychain Manager Keychain Manager is a Layer-2 framework built over Keychain API which helps in using Keychain in all your Apple devices with easiness

Gokul Nair 14 Jan 1, 2023
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 Jan 5, 2023
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 Jan 8, 2023
Modern Swift wrapper for Keychain Services API with the benefits of static typing

SwiftyKeychainKit SwiftyKeychainKit is a simple Swift wrapper for Keychain Services API with the benefits of static typing. Define your keys in one pl

Andriy Slyusar 18 Jan 1, 2023
Example of using TOTP with iCloud Keychain in iOS 15

Installation This example needs Ngrok and Ruby 3.0.3+. Setup project with Makefi

Makeeyaf 0 Dec 31, 2021
A tool to check which keychain items are available to an attacker once an iOS device has been jailbroken

Keychain Dumper Usage All that should be needed to use keychain_dumper is the binary that is checked in to the Keychain-Dumper Git repository. This bi

Patrick Toomey 1.2k 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
Recover lost keychain passwords with swift

brutalkeychain Recover lost keychain passwords using a simple swift script (so c

Charles Edge 9 Sep 12, 2022
Recover lost keychain passwords with swift

brutalkeychain Recover lost keychain passwords using a simple swift script (so c

Charles Edge 4 Dec 24, 2021
Keep track of accessibility settings, leverage high contrast colors, and use scalable fonts to enable users with disabilities to use your app.

Accessibility for iOS, macOS, tvOS, and watchOS ?? What's new in Capable 2.0 ?? Here are the most important changes: ?? New framework architecture and

Christoph Wendt 230 Jan 4, 2023
Generating OTP one-time passwords in Swift.

One Time Password Navigate Installation Swift Package Manager CocoaPods Manually Usage Apps Using Installation Ready to use on iOS 13+, tvOS 13+ & wat

Sparrow Code 15 Nov 11, 2022
A simple wrapper for the iOS Keychain to allow you to use it in a similar fashion to User Defaults. Written in Swift.

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. Prov

Jason 1.5k Jan 8, 2023
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
Swift library that makes easier to serialize the user's preferences (app's settings) with system User Defaults or Property List file on disk.

PersistentStorageSerializable PersistentStorageSerializable is a protocol for automatic serialization and deserialization of Swift class, struct or NS

Ivan Rublev 163 Jun 3, 2021
Keychain - Keychain wrapper with swift

Keychain wrapper. Store a value as a generic password: let account = "an-arbitra

Alejandro Ramirez 0 Mar 14, 2022
Valet lets you securely store data in the iOS, tvOS, or macOS Keychain without knowing a thing about how the Keychain works.

Valet Valet lets you securely store data in the iOS, tvOS, watchOS, or macOS Keychain without knowing a thing about how the Keychain works. It’s easy.

Square 3.8k Jan 4, 2023
Valet lets you securely store data in the iOS, tvOS, or macOS Keychain without knowing a thing about how the Keychain works. It’s easy. We promise.

Valet Valet lets you securely store data in the iOS, tvOS, watchOS, or macOS Keychain without knowing a thing about how the Keychain works. It’s easy.

Square 3.8k Jan 4, 2023