Skip to content

Instantly share code, notes, and snippets.

@s-aska
Last active September 16, 2022 03:37
Show Gist options
  • Star 48 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save s-aska/e7ad24175fb7b04f78e7 to your computer and use it in GitHub Desktop.
Save s-aska/e7ad24175fb7b04f78e7 to your computer and use it in GitHub Desktop.
Swift Keychain class ( supported Xcode 6.0.1 )
import UIKit
import Security
class Keychain {
class func save(key: String, data: NSData) -> Bool {
let query = [
kSecClass as String : kSecClassGenericPassword as String,
kSecAttrAccount as String : key,
kSecValueData as String : data ]
SecItemDelete(query as CFDictionaryRef)
let status: OSStatus = SecItemAdd(query as CFDictionaryRef, nil)
return status == noErr
}
class func load(key: String) -> NSData? {
let query = [
kSecClass as String : kSecClassGenericPassword,
kSecAttrAccount as String : key,
kSecReturnData as String : kCFBooleanTrue,
kSecMatchLimit as String : kSecMatchLimitOne ]
var dataTypeRef :Unmanaged<AnyObject>?
let status: OSStatus = SecItemCopyMatching(query, &dataTypeRef)
if status == noErr {
return (dataTypeRef!.takeRetainedValue() as NSData)
} else {
return nil
}
}
class func delete(key: String) -> Bool {
let query = [
kSecClass as String : kSecClassGenericPassword,
kSecAttrAccount as String : key ]
let status: OSStatus = SecItemDelete(query as CFDictionaryRef)
return status == noErr
}
class func clear() -> Bool {
let query = [ kSecClass as String : kSecClassGenericPassword ]
let status: OSStatus = SecItemDelete(query as CFDictionaryRef)
return status == noErr
}
}
import UIKit
import XCTest
class KeychainTests: XCTestCase {
override func setUp() {
super.setUp()
Keychain.clear()
}
override func tearDown() {
Keychain.clear()
super.tearDown()
}
func testSaveLoad() {
let key1 = "testSaveLoadKey1"
let key2 = "testSaveLoadKey2"
let saveData = "data".dataValue
XCTAssertTrue(Keychain.load(key1) == nil)
XCTAssertTrue(Keychain.load(key2) == nil)
XCTAssertTrue(Keychain.save(key1, data: saveData))
XCTAssertTrue(Keychain.load(key1) != nil)
XCTAssertTrue(Keychain.load(key2) == nil)
let loadData = Keychain.load(key1)!
XCTAssertEqual(loadData.stringValue, saveData.stringValue)
}
func testDelete() {
let key1 = "testDeleteKey1"
let key2 = "testDeleteKey2"
let saveData = "testDeleteData".dataValue
XCTAssertTrue(Keychain.save(key1, data: saveData))
XCTAssertTrue(Keychain.save(key2, data: saveData))
XCTAssertTrue(Keychain.load(key1) != nil)
XCTAssertTrue(Keychain.load(key2) != nil)
XCTAssertTrue(Keychain.delete(key1))
XCTAssertTrue(Keychain.load(key1) == nil)
XCTAssertTrue(Keychain.load(key2) != nil)
}
func testClear() {
let key = "testClearKey"
let data = "testClearData".dataValue
Keychain.save(key, data: data)
XCTAssertTrue(Keychain.load(key) != nil)
Keychain.clear()
XCTAssertTrue(Keychain.load(key) == nil)
}
}
extension String {
public var dataValue: NSData {
return dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
}
}
extension NSData {
public var stringValue: String {
return NSString(data: self, encoding: NSUTF8StringEncoding)!
}
}
@deniskr
Copy link

deniskr commented Dec 3, 2014

I have developed a Swift wrapper over the entire C Keychain API. See if it can be useful for you: https://github.com/deniskr/KeychainSwiftAPI

@bsikander
Copy link

Does this class work correctly ? I have a User model and I would like to store it inside keychain.

@evgenyneu
Copy link

Thank you so much. Created a repository and a demo app, with some modifications.

https://github.com/exchangegroup/keychain-swift

@whenov
Copy link

whenov commented May 29, 2015

Neatest version!

@jackreichert
Copy link

I updated it to work with Xcode Version 7.0 beta 4 (7A165t) https://gist.github.com/jackreichert/414623731241c95f0e20

@seckincengiz
Copy link

XCode 8.1 Beta and IOS 10.1 ready swift3 version is here : https://gist.github.com/seckinburakcengiz/e4e2da2a712d30e39752e76afe300ca8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment