Skip to content

Instantly share code, notes, and snippets.

@jackreichert
Forked from s-aska/Keychain.swift
Last active January 11, 2017 02:43
Show Gist options
  • Save jackreichert/414623731241c95f0e20 to your computer and use it in GitHub Desktop.
Save jackreichert/414623731241c95f0e20 to your computer and use it in GitHub Desktop.
Swift Keychain class ( supported Xcode Version 7.0 beta 4 (7A165t) )
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: AnyObject?
let status = withUnsafeMutablePointer(&dataTypeRef) { SecItemCopyMatching(query, UnsafeMutablePointer($0)) }
if status == errSecSuccess {
if let data = dataTypeRef as! NSData? {
return data
}
}
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)!
}
}
@jackreichert
Copy link
Author

Updated to work with Xcode Version 7.0 beta 4 (7A165t) based on http://stackoverflow.com/a/27721328

@dado3212
Copy link

@jackreichert Thanks so much!

@changyoonpark
Copy link

Thanks!

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