A powerful, protocol-oriented library for working with the keychain in Swift.

Related tags

Keychain Locksmith
Overview

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 Rocket, an app that gives you Slack-style emoji everywhere on your Mac.

 

Details

How is Locksmith different to other keychain wrappers?

  • Locksmith’s API is both super-simple and deeply powerful
  • Provides access to all of the keychain’s metadata with strongly typed results
  • Add functionality to your existing types for free
  • Useful enums and Swift-native types

Want to read more about Locksmith’s design? I wrote a blog post on protocol oriented programming in Swift.

Installation

Version Carthage compatible Build Status

  • Locksmith 4.0 and greater is Swift 4 compatible. See the swift-3.1 branch for compatibility with older versions of Swift.

CocoaPods

Locksmith is available through CocoaPods.

pod 'Locksmith'

Carthage

Locksmith is available through Carthage.

github "matthewpalmer/Locksmith"

Quick start

Setup

  1. Choose your target project
  2. Select Capabilties
  3. Enable Keychain Sharing

Xcode then automatically creates a .entitlements file and you are ready to use Locksmith!

Save data

try Locksmith.saveData(["some key": "some value"], forUserAccount: "myUserAccount")

Load data

let dictionary = Locksmith.loadDataForUserAccount("myUserAccount")

Update data

  • as well as replacing existing data, this writes data to the keychain if it does not exist already
try Locksmith.updateData(["some key": "another value"], forUserAccount: "myUserAccount")

Delete data

try Locksmith.deleteDataForUserAccount("myUserAccount")

Power to the protocols

Locksmith has been designed with Swift 2, protocols, and protocol extensions in mind.

Why do this? Because you can add existing functionality to your types with only the slightest changes!

Say we have a Twitter account

struct TwitterAccount {
  let username: String
  let password: String
}

and we want to save it to the keychain as a generic password. All we need to do is conform to the right protocols in Locksmith and we get that functionality for free.

struct TwitterAccount: CreateableSecureStorable, GenericPasswordSecureStorable {
  let username: String
  let password: String

  // Required by GenericPasswordSecureStorable
  let service = "Twitter"
  var account: String { return username }

  // Required by CreateableSecureStorable
  var data: [String: AnyObject] {
    return ["password": password]
  }
}

Now we get the ability to save our account in the keychain.

let account = TwitterAccount(username: "_matthewpalmer", password: "my_password")
try account.createInSecureStore()

Creating, reading, and deleting each have their own protocols: CreateableSecureStorable, ReadableSecureStorable, and DeleteableSecureStorable. And the best part?

You can conform to all three protocols on the same type!

struct TwitterAccount: ReadableSecureStorable,
                       CreateableSecureStorable,
                       DeleteableSecureStorable,
                       GenericPasswordSecureStorable {
  let username: String
  let password: String

  let service = "Twitter"
  var account: String { return username }
  var data: [String: AnyObject] {
    return ["password": password]
  }
}

let account = TwitterAccount(username: "_matthewpalmer", password: "my_password")

// CreateableSecureStorable lets us create the account in the keychain
try account.createInSecureStore()

// ReadableSecureStorable lets us read the account from the keychain
let result = account.readFromSecureStore()

// DeleteableSecureStorable lets us delete the account from the keychain
try account.deleteFromSecureStore()

So. cool.

The details

By declaring that your type adopts these protocols—which is what we did above with struct TwitterAccount: CreateableSecureStorable, ...—you get a bunch of functionality for free.

I like to think about protocols with extensions in terms of “what you get,” “what you’ve gotta do,” and “what’s optional.” Most of the stuff under ‘optional’ should only be implemented if you want to change existing functionality.

CreateableSecureStorable

What you get

// Saves a type to the keychain
func createInSecureStore() throws

Required

// The data to save to the keychain
var data: [String: AnyObject] { get }

Optional

// Perform the request in this closure
var performCreateRequestClosure: PerformRequestClosureType { get }

ReadableSecureStorable

What you get

// Read from the keychain
func readFromSecureStore() -> SecureStorableResultType?

Required

Nothing!

Optional

// Perform the request in this closure
var performReadRequestClosure: PerformRequestClosureType { get }

DeleteableSecureStorable

What you get

// Read from the keychain
func deleteFromSecureStore() throws

Required

Nothing!

Optional

// Perform the request in this closure
var performDeleteRequestClosure: PerformRequestClosureType { get }

Powerful support for the Cocoa Keychain

Many wrappers around the keychain have only support certain parts of the API. This is because there are so many options and variations on the way you can query the keychain that it’s almost impossible to abstract effectively.

Locksmith tries to include as much of the keychain as possible, using protocols and protocol extensions to minimize the complexity. You can mix-and-match your generic passwords with your read requests while staying completely type-safe.

Please refer to the Keychain Services Reference for full information on what each of the attributes mean and what they can do.

Certificates, keys, and identities are possible—it’s just a matter of translating the kSec... constants!

GenericPasswordSecureStorable

Generic passwords are probably the most common use-case of the keychain, and are great for storing usernames and passwords.

Properties listed under ‘Required’ have to be implemented by any types that conform; those listed under ‘Optional’ can be implemented to add additional information to what is saved or read if desired.

One thing to note: if you implement an optional property, its type annotation must match the type specified in the protocol exactly. If you implement description: String? it can’t be declared as var description: String.

Required

var account: String { get }
var service: String { get }

Optional

var comment: String? { get }
var creator: UInt? { get }
var description: String? { get }
var generic: NSData? { get }
var isInvisible: Bool? { get }
var isNegative: Bool? { get }
var label: String? { get }
var type: UInt? { get }

InternetPasswordSecureStorable

Types that conform to InternetPasswordSecureStorable typically come from web services and have certain associated metadata.

Required

var account: String { get }
var authenticationType: LocksmithInternetAuthenticationType { get }
var internetProtocol: LocksmithInternetProtocol { get }
var port: String { get }
var server: String { get }

Optional

var comment: String? { get }
var creator: UInt? { get }
var description: String? { get }
var isInvisible: Bool? { get }
var isNegative: Bool? { get }
var path: String? { get }
var securityDomain: String? { get }
var type: UInt? { get }

Result types

By adopting a protocol-oriented design from the ground up, Locksmith can provide access to the result of your keychain queries with type annotations included—store an NSDate, get an NSDate back with no type-casting!

Let’s start with an example: the Twitter account from before, except it’s now an InternetPasswordSecureStorable, which lets us store a bit more metadata.

struct TwitterAccount: InternetPasswordSecureStorable,
                       ReadableSecureStorable,
                       CreateableSecureStorable {
  let username: String
  let password: String

  var account: String { return username }
  var data: [String: AnyObject] {
    return ["password": password]
  }

  let server = "com.twitter"
  let port = 80
  let internetProtocol = .HTTPS
  let authenticationType = .HTTPBasic
  let path: String? = "/api/2.0/"
}

let account = TwitterAccount(username: "_matthewpalmer", password: "my_password")

// Save all this to the keychain
account.createInSecureStore()

// Now let’s get it back
let result: InternetPasswordSecureStorableResultType = account.readFromSecureStore()

result?.port // Gives us an Int directly!
result?.internetProtocol // Gives us a LocksmithInternetProtocol enum case directly!
result?.data // Gives us a [String: AnyObject] of what was saved
// and so on...

This is awesome. No more typecasting.

GenericPasswordSecureStorableResultType

Everything listed here can be set on a type conforming to GenericPasswordSecureStorable, and gotten back from the result returned from readFromSecureStore() on that type.

var account: String { get }
var service: String { get }
var comment: String? { get }
var creator: UInt? { get }
var description: String? { get }
var data: [String: AnyObject]? { get }
var generic: NSData? { get }
var isInvisible: Bool? { get }
var isNegative: Bool? { get }
var label: String? { get }
var type: UInt? { get }

InternetPasswordSecureStorableResultType

Everything listed here can be set on a type conforming to InternetPasswordSecureStorable, and gotten back from the result returned from readFromSecureStore() on that type.

var account: String { get }
var authenticationType: LocksmithInternetAuthenticationType { get }
var internetProtocol: LocksmithInternetProtocol { get }
var port: Int { get }
var server: String { get }
var comment: String? { get }
var creator: UInt? { get }
var data: [String: AnyObject]? { get }
var description: String? { get }
var isInvisible: Bool? { get }
var isNegative: Bool? { get }
var path: String? { get }
var securityDomain: String? { get }
var type: UInt? { get }

Enumerations

Locksmith provides a bunch of handy enums for configuring your requests, so you can say kSecGoodByeStringConstants.

LocksmithAccessibleOption

LocksmithAccessibleOption configures when an item can be accessed—you might require that stuff is available when the device is unlocked, after a passcode has been entered, etc.

public enum LocksmithAccessibleOption {
  case AfterFirstUnlock
  case AfterFirstUnlockThisDeviceOnly
  case Always
  case AlwaysThisDeviceOnly
  case WhenPasscodeSetThisDeviceOnly
  case WhenUnlocked
  case WhenUnlockedThisDeviceOnly
}

LocksmithError

LocksmithError provides Swift-friendly translations of common keychain error codes. These are thrown from methods throughout the library. Apple’s documentation provides more information on these errors.

public enum LocksmithError: ErrorType {
  case Allocate
  case AuthFailed
  case Decode
  case Duplicate
  case InteractionNotAllowed
  case NoError
  case NotAvailable
  case NotFound
  case Param
  case RequestNotSet
  case TypeNotFound
  case UnableToClear
  case Undefined
  case Unimplemented
}

LocksmithInternetAuthenticationType

LocksmithInternetAuthenticationType lets you pick out the type of authentication you want to store alongside your .InternetPasswords—anything from .MSN to .HTTPDigest. Apple’s documentation provides more information on these values.

public enum LocksmithInternetAuthenticationType {
  case Default
  case DPA
  case HTMLForm
  case HTTPBasic
  case HTTPDigest
  case MSN
  case NTLM
  case RPA
}

LocksmithInternetProtocol

LocksmithInternetProtocol is used with .InternetPassword to choose which protocol was used for the interaction with the web service, including .HTTP, .SMB, and a whole bunch more. Apple’s documentation provides more information on these values.

public enum {
  case AFP
  case AppleTalk
  case DAAP
  case EPPC
  case FTP
  case FTPAccount
  case FTPProxy
  case FTPS
  case HTTP
  case HTTPProxy
  case HTTPS
  case HTTPSProxy
  case IMAP
  case IMAPS
  case IPP
  case IRC
  case IRCS
  case LDAP
  case NNTP
  case NNTPS, LDAPS
  case POP3
  case POP3S
  case RTSP
  case RTSPProxy
  case SMB
  case SMTP
  case SOCKS
  case SSH
  case Telnet
  case TelnetS
}

Author

Matthew Palmer, [email protected]

License

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

Comments
  • Swift 3.0 beta 6 compatibility

    Swift 3.0 beta 6 compatibility

    This Pull request is an alternative to JeromeTan's Pull Request. Instead of casting types to AnyObject the dictionaries now take the proper form [String: Any] as it is expected by CoreFoundation.

    Tests work fine on maxOS, iOS is crashing due to a problem in simulator.

    opened by pascalfribi 23
  • Sometimes Can't Load from Keychain

    Sometimes Can't Load from Keychain

    I've got another weird one, but first - I've got a commit that adds some stuff to show the logging in the app. I wasn't sure if you'd want it, so I didn't do a PR, but let me know if you'd like me to do that.

    Anyway, I've got four devices I'm testing with:

    • iPhone 6
    • iPhone 5S
    • iPhone 5
    • iPad 4

    When I run the Locksmith app in the simulator or build it directly to these devices everything works perfectly. Then, when I archive the app and distribute it though HockeyApp, things get weird.

    The iPad and 5 also work normally, but then on both the 6 and 5S, loading doesn't work. I tap save, then I tap load and get nothing.

    I've got the iOS Console app up and I'm not seeing anything there and the performRequest method isn't returning an error, so I don't know what's going on.

    This is what was happening to me with the code I wrote myself and is why I got interested in Locksmith in the first place. I'm new to iOS development, so I assumed I was doing something wrong, but now I'm seeing this behavior with the Locksmith code too, so I thought I'd open an issue on it.

    One thing that I'm wondering about is how TouchID could possibly play into this. One of the hardware differences between the devices that are behaving and those that aren't is that TouchID sensor - maybe that matters?

    I don't know, seems like a longshot. Have you been able to get this app to work on a device where you haven't just built it directly from Xcode? I don't know if you use HockeyApp or TestFlight or something else, but I'd be very interested to know if it's working for you.

    Thanks! Jon

    opened by jonallured 15
  • 52+ errors... XCode 8

    52+ errors... XCode 8

    Finally updating a new project to Swift 3.0... but having trouble with LockSmith:

    I tried downloading the 3.0 branch code and replacing the files... but still seems like a lot of broken stuff. I feel like I must be doing something wrong on my end. Or did some stuff change last minute that is breaking the last 3.0 changes?

    image

    opened by mdridley 14
  • Support Xcode 7 beta 6 via Carthage

    Support Xcode 7 beta 6 via Carthage

    Crashes at runtime

    dyld: lazy symbol binding failed: Symbol not found: _TFSs24withUnsafeMutablePointeru0_rFTRq_FGVSs20UnsafeMutablePointerq__q0__q0 Referenced from: /Users/mdellagi/Library/Developer/CoreSimulator/Devices/5EEB8704-4DA7-4D43-B767-658CDD7C2E33/data/Containers/Bundle/Application/C589F01D-F6DB-4CB1-A69D-A28AA8013FE1/meinmd.app/Frameworks/Locksmith.framework/Locksmith Expected in: /Users/mdellagi/Library/Developer/CoreSimulator/Devices/5EEB8704-4DA7-4D43-B767-658CDD7C2E33/data/Containers/Bundle/Application/C589F01D-F6DB-4CB1-A69D-A28AA8013FE1/meinmd.app/Frameworks/libswiftCore.dylib

    dyld: Symbol not found: _TFSs24withUnsafeMutablePointeru0_rFTRq_FGVSs20UnsafeMutablePointerq__q0__q0 Referenced from: /Users/mdellagi/Library/Developer/CoreSimulator/Devices/5EEB8704-4DA7-4D43-B767-658CDD7C2E33/data/Containers/Bundle/Application/C589F01D-F6DB-4CB1-A69D-A28AA8013FE1/meinmd.app/Frameworks/Locksmith.framework/Locksmith Expected in: /Users/mdellagi/Library/Developer/CoreSimulator/Devices/5EEB8704-4DA7-4D43-B767-658CDD7C2E33/data/Containers/Bundle/Application/C589F01D-F6DB-4CB1-A69D-A28AA8013FE1/meinmd.app/Frameworks/libswiftCore.dylib

    switch type {
            case .Create:
                status = withUnsafeMutablePointer(&result) { SecItemAdd(requestReference, UnsafeMutablePointer($0)) }
            case .Read:
                status = withUnsafeMutablePointer(&result) { SecItemCopyMatching(requestReference, UnsafeMutablePointer($0)) }
            case .Delete:
                status = SecItemDelete(requestReference)
            case .Update:
                status =  Locksmith.performUpdate(requestReference, result: &result)
    }
    
    opened by prefect42 12
  • Crash on Save

    Crash on Save

    I cloned down the repo, built the app and then pressed save - crashed and burned with:

    Thread 1: EXC_BAD_ACCESS (code = 1, address=0x1)

    I doubt that's very helpful, but I'm not sure what else to do to troubleshoot this. I did stop the app and run it again, then I got another error:

    Keychain request failed. Code: -25299. Message: The item already exists.

    In both cases, we're stopping on this line:

    if let data: NSData = result?.takeRetainedValue() as? NSData {
    

    That's in Locksmith.swift line 40.

    opened by jonallured 12
  • Swift 3 Support

    Swift 3 Support

    In order for an app to migrate to Swift 3, every one of it's libraries needs to use it as well. I talked to some of the engineers at WWDC, and they were very adamant that Swift 2.3 was a temporary stop gap to give people more time to migrate to 3, but not a longterm solution. It's my opinion that Swift frameworks should maintain branches for each major version of Swift (i.e. swift-2.2, swift-2.3 and swift-3.0) so that apps can target the version they are using specifically.

    I've already submitted a pull request for Swift 2.3, but I recommend you create a swift-2.3 branch and close that request so that I can create a new one directed at that branch.

    I have a branch with the library converted to Swift 3 building, but there is a test that is failing. I'm not familiar enough with the framework to understand why it's failing though. Additionally, I haven't adopted any of the new style guidelines introduce with Swift 3. Perhaps we could create a swift-3.0 branch, merge that into it, and go from there to get a fully working and migrated version for 3.0.

    opened by davbeck 11
  • Fix library for proper Compiler-Level Optimization Setting (Release Build Crash Fix)

    Fix library for proper Compiler-Level Optimization Setting (Release Build Crash Fix)

    I recently submitted my app to the store not realizing this library requires the optimization level of the compiler to be set to 'None' or it crashes on launch for release build. As a result, it was rejected by Apple due to crashing on start up. I have since changed it to 'None' and now the app runs fine on release build, but reading Apple's documentation it states specifically the following for Compiler-Level Optimization of type None:

     None - The compiler does not attempt to optimize code. Use this option during development when you are focused on solving logic errors and need a fast compile time. Do not use this option for shipping your executable.
    

    The Do not use this option for shipping your executable concerns me a bit for releasing a non-optimized build to the App Store. Is there any possibility of fixing this library to not require this setting?

    opened by Appmazo 11
  • Swift 3.0 and Xcode 8 GM support

    Swift 3.0 and Xcode 8 GM support

    Forked from @pascalfribi's PR https://github.com/matthewpalmer/Locksmith/pull/140. Added a Test Host target with Keychain Sharing capabilities.

    Also, added @aaronpearce's suggestion to change old[String(kSecReturnData)] = true to old[String(kSecReturnData)] = kCFBooleanTrue in asReadableSecureStoragePropertyDictionary.

    Tests are passing in my machine, running Xcode 8 GM.

    opened by fedetrim 7
  • Cannot update an existing record in the keychain

    Cannot update an existing record in the keychain

    This isn't actually a pull request, as (a) there's a lot of code duplication in the tests, and (b) the tests currently fail! But it was the easiest way that occurred to me of bundling up the code I have currently that's failing.

    It naïvely appears to be a recurrence of the very first issue in this project, but I have absolutely no experience in debugging Swift so I couldn't say.

    For a Secret Work Project, we need an app that logs into our web service, and we need to remember those login details. So GenericPasswordSecureStorable looked like the easiest way of implementing this, albeit with a constant account value as we'd only ever store one set of user details.

    As you'll hopefully see when running the tests, the C, R and D part of CRUD work fine; but when I try to update the details, I get an exception. And I get that whether I update the original object or I try to store a new one (which is good - if it had varied between which object was trying to store stuff that would have been the stuff of nightmares).

    I'm new to Swift (normally I'm a Perl programmer), so some of the code might be unidiomatic, and hopefully the fix is to say "why on Earth are you doing that‽", update the documentation, and tell me not to be such a fool. But in case it actually is an issue in the guts of something horrible, you have a test method to run now.

    opened by skington 7
  • Read data from keychain using protocols after app killed from memory

    Read data from keychain using protocols after app killed from memory

    I have been using Locksmith for a few months now with great luck, library is wonderful and has worked great so far!

    I am upgrading apps to Swift 2.0, so upgrading this library is part of this process. I upgraded the code into my apps project and read the README to get an idea of how the API has changed.

    I used to use the methods: LockSmith.saveData(), LockSmith.loadDataForUserAccount(), etc. but now I see you added support for protocols...


    So I was looking through the docs for protocols and saw this code:

    let account = TwitterAccount(username: "_matthewpalmer", password: "my_password")
    try account.createInSecureStore()
    

    and I am able to read the data I need with:

    let result = account.readFromSecureStore()
    result.username // => "_matthewpalmer"
    result.password // => "my_password"
    

    Looks great. Now, what I am having issues with, what if I create an instance of my TwitterAccount struct, save it to keychain, then I kill the app from memory? The variable account that is required in order to read the data from keychain will be cleared and no longer available for me to use. Then I just cannot create a new TwitterAccount struct because it requires me knowing "username" and "password" but I am not going to force my user to give me this data every time the app is launched.

    In previous versions of LockSmith, "service name" was used in order to read data for my specific app. I see this is gone, so how am I able to read my TwitterAccount username and password after the app has been killed and removed from memory such as powering down the user device?

    opened by levibostian 7
  • Keychain enumeration

    Keychain enumeration

    Unfinished — Do Not Merge

    This PR addresses https://github.com/matthewpalmer/Locksmith/issues/45.

    This code…

    • Adds a static array of security classes
    • Implements each(userAccount:, itemHandler) by iterating through the classes and calling the handler when appropriate
    • Deprecates .Many and replaces it with .All
    • Makes userAccount optional

    This enables two types of iteration possible. One with a user account:

    Locksmith.each("[email protected]") { result in
        print(result)
    }
    

    And one without:

    Locksmith.each() { result in
        print(result)
    }
    

    SecItemCopyMatching will return an array, not a dictionary, if kSecMatchLimit != 1. But performRequest(_:) only handles a single dictionary return value at the moment. So I think that will need to be updated as well.

    Still to do:

    • Test on an app with real-world data
    • Handle arrays in performRequest(_:)

    Bonus points:

    • In the Swift 2.0 branch, use SequenceType and CollectionType protocols to make an enumerable type. This would enable developers to filter results, get counts, iterate in reverse, etc.

    @matthewpalmer I'm adding you as a collaborator on my fork so you can push directly to this branch if you want. Anyone else interested, let me know.

    opened by getaaron 7
  • Warning: Project Abandoned

    Warning: Project Abandoned

    This project is still in Swift 3, and all attempts to provide updates have been blocked. Check out this link for an active replacement

    https://github.com/kishikawakatsumi/KeychainAccess

    opened by neodave 1
  • Updated for Swift 5.0

    Updated for Swift 5.0

    • Bumped minimum deployment target for OSX to 10.11 since NSKeyedArchiver.archivedData(withRootObject: data) is only #available on iOS 10.11 or higher.
    • Updated .travis.yml file for Xcode 10.2
    • Fixes https://github.com/matthewpalmer/Locksmith/issues/207
    opened by stephanheilner 4
Releases(2.0.8)
Owner
Matthew Palmer
Matthew Palmer
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
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
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
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
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
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
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
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
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
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 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
React.js like Mixin. More powerful Protocol-Oriented Programming.

Mixin ?? Why? Swift is Protocol-Oriented Programming, and it's more powerful by default implementations of extensions of protocols. You can mixin meth

Wan-Huang Yang 45 Dec 28, 2021
Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. (Pure Swift, Supports Linux)

SwiftFoundation Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. Goals Provide a cross-platform in

null 620 Oct 11, 2022
Eugene Kazaev 713 Dec 25, 2022
A resource based, protocol oriented networking library designed for pure-SwiftUI applications.

Monarch ?? - WIP A resource based, protocol oriented networking library designed for pure-SwiftUI applications. Features: Async/Await Resource Based P

Emilio Pelaez Romero 4 Oct 17, 2022
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