Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding item to keychain using Swift

I'm trying to add an item to the iOS keychain using Swift but can't figure out how to type cast properly. From WWDC 2013 session 709, given the following Objective-C code:

NSData *secret = [@"top secret" dataWithEncoding:NSUTF8StringEncoding];
NSDictionary *query = @{
    (id)kSecClass: (id)kSecClassGenericPassword,
    (id)kSecAttrService: @"myservice",
    (id)kSecAttrAccount: @"account name here",
    (id)kSecValueData: secret,
};

OSStatus = SecItemAdd((CFDictionaryRef)query, NULL);

Attempting to do it in Swift as follows:

var secret: NSData = "Top Secret".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
var query: NSDictionary = [
    kSecClass: kSecClassGenericPassword,
    kSecAttrService: "MyService",
    kSecAttrAccount: "Some account",
    kSecValueData: secret
]

yields the error "Cannot convert the expression's type 'Dictionary' to 'DictionaryLiteralConvertible'.

Another approach I took was to use Swift and the - setObject:forKey: method on a Dictionary to add kSecClassGenericPassword with the key kSecClass.

In Objective-C:

NSMutableDictionary *searchDictionary = [NSMutableDictionary dictionary];
[searchDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];

In the Objective-C code, the CFTypeRef of the various keychain item class keys are bridged over using id. In the Swift documentation it's mentioned that Swift imports id as AnyObject. However when I attempted to downcast kSecClass as AnyObject for the method, I get the error that "Type 'AnyObject' does not conform to NSCopying.

Any help, whether it's a direct answer or some guidance about how to interact with Core Foundation types would be appreciated.

EDIT 2

This solution is no longer valid as of Xcode 6 Beta 2. If you are using Beta 1 the code below may work.

var secret: NSData = "Top Secret".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
let query = NSDictionary(objects: [kSecClassGenericPassword, "MyService", "Some account", secret], forKeys: [kSecClass,kSecAttrService, kSecAttrAccount, kSecValueData])

OSStatus status = SecItemAdd(query as CFDictionaryRef, NULL)

To use Keychain Item Attribute keys as dictionary keys you have to unwrap them by using either takeRetainedValue or takeUnretainedValue (as appropriate). Then you can cast them to NSCopying. This is because they are CFTypeRefs in the header, which aren't all copyable.

As of Xcode 6 Beta 2 however, this causes Xcode to crash.

like image 404
Pasan Premaratne Avatar asked Jun 09 '14 03:06

Pasan Premaratne


People also ask

What is stored in iOS keychain?

What information does iCloud Keychain store? iCloud Keychain stores credit card numbers and expiration dates—without storing or autofilling the security code—and passwords and usernames, Wi-Fi passwords, Internet accounts, and more.

What is keychain wrapper?

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.


2 Answers

You simply need to downcast the literal:

let dict = ["hi": "Pasan"] as NSDictionary

Now dict is an NSDictionary. To make a mutable one, it's very similar to Objective-C:

let mDict = dict.mutableCopy() as NSMutableDictionary
mDict["hola"] = "Ben"
like image 58
Sam Soffes Avatar answered Nov 15 '22 20:11

Sam Soffes


In the xcode 6.0.1 you must do this!!

let kSecClassValue = NSString(format: kSecClass)
let kSecAttrAccountValue = NSString(format: kSecAttrAccount)
let kSecValueDataValue = NSString(format: kSecValueData)
let kSecClassGenericPasswordValue = NSString(format: kSecClassGenericPassword)
let kSecAttrServiceValue = NSString(format: kSecAttrService)
let kSecMatchLimitValue = NSString(format: kSecMatchLimit)
let kSecReturnDataValue = NSString(format: kSecReturnData)
let kSecMatchLimitOneValue = NSString(format: kSecMatchLimitOne)
like image 38
Beslan Tularov Avatar answered Nov 15 '22 21:11

Beslan Tularov