Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save and retrieve value via KeyChain

I'm trying to store an Integer and retrieve it using KeyChain.

This is how I save it:

func SaveNumberOfImagesTaken()     {         let key = "IMAGE_TAKEN"         var taken = 10         let data = NSKeyedArchiver.archivedDataWithRootObject(taken)         let query : [String:AnyObject] = [             kSecClass as String : kSecClassGenericPassword,             kSecAttrAccount as String : key,             kSecValueData as String : data         ]         let status : OSStatus = SecItemAdd(query as CFDictionaryRef, nil)      } 

This is how I try to retrieve it:

func CheckIfKeyChainValueExitss() -> AnyObject? {     var key = "IMAGE_TAKEN"     let query : [String:AnyObject] = [         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 let op = dataTypeRef?.toOpaque() {         let data = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue()         if let string: AnyObject? =  NSKeyedUnarchiver.unarchiveObjectWithData(data) as? AnyObject? {             if key == "IMAGE_TAKEN"             {                 return string as! String!              }             else if string == nil             {                 return nil             }         }     }     return nil  } 

I'm getting the following error:

Could not cast value of type '__NSCFNumber' to 'NSString'

I tried playing with the variables but without success.

like image 815
Roi Mulia Avatar asked Jun 08 '15 21:06

Roi Mulia


People also ask

How does apple keychain work?

With iCloud Keychain, you can keep your passwords and other secure information updated across your devices. iCloud Keychain remembers things, so that you don't have to. It auto-fills your informationā€”like your Safari usernames and passwords, credit cards, and Wi-Fi passwords on any device that you approve.

What is swift keychain?

Keychain: The keychain is a secure and encrypted storage place for sensitive data. You can think of it is a database of sensitive information. Keychain Item: This is a registry in the keychain. Item Class: You can think of a class as a template of information you want to store.

What is stored in iOS keychain?

What is keychain? iOS system has an interesting thing called key chianšŸ”. The keychain is just a data storage for storing all sensitive data, like passwords, certificates etc.

What is keychain service?

android.security.KeyChain. The KeyChain class provides access to private keys and their corresponding certificate chains in credential storage. Applications accessing the KeyChain normally go through these steps: Receive a callback from an X509KeyManager that a private key is requested.


1 Answers

I've update Eric's version for Swift 5:

class KeyChain {      class func save(key: String, data: Data) -> OSStatus {         let query = [             kSecClass as String       : kSecClassGenericPassword as String,             kSecAttrAccount as String : key,             kSecValueData as String   : data ] as [String : Any]          SecItemDelete(query as CFDictionary)          return SecItemAdd(query as CFDictionary, nil)     }      class func load(key: String) -> Data? {         let query = [             kSecClass as String       : kSecClassGenericPassword,             kSecAttrAccount as String : key,             kSecReturnData as String  : kCFBooleanTrue!,             kSecMatchLimit as String  : kSecMatchLimitOne ] as [String : Any]          var dataTypeRef: AnyObject? = nil          let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)          if status == noErr {             return dataTypeRef as! Data?         } else {             return nil         }     }      class func createUniqueID() -> String {         let uuid: CFUUID = CFUUIDCreate(nil)         let cfStr: CFString = CFUUIDCreateString(nil, uuid)          let swiftString: String = cfStr as String         return swiftString     } }  extension Data {      init<T>(from value: T) {         var value = value         self.init(buffer: UnsafeBufferPointer(start: &value, count: 1))     }      func to<T>(type: T.Type) -> T {         return self.withUnsafeBytes { $0.load(as: T.self) }     } } 

I've update Eric's version for Swift 3:

class KeyChain {      class func save(key: String, data: Data) -> OSStatus {         let query = [             kSecClass as String       : kSecClassGenericPassword as String,             kSecAttrAccount as String : key,             kSecValueData as String   : data ] as [String : Any]          SecItemDelete(query as CFDictionary)          return SecItemAdd(query as CFDictionary, nil)     }      class func load(key: String) -> Data? {         let query = [             kSecClass as String       : kSecClassGenericPassword,             kSecAttrAccount as String : key,             kSecReturnData as String  : kCFBooleanTrue,             kSecMatchLimit as String  : kSecMatchLimitOne ] as [String : Any]          var dataTypeRef: AnyObject? = nil          let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)          if status == noErr {             return dataTypeRef as! Data?         } else {             return nil         }     }      class func createUniqueID() -> String {         let uuid: CFUUID = CFUUIDCreate(nil)         let cfStr: CFString = CFUUIDCreateString(nil, uuid)          let swiftString: String = cfStr as String         return swiftString     } }  extension Data {      init<T>(from value: T) {         var value = value         self.init(buffer: UnsafeBufferPointer(start: &value, count: 1))     }      func to<T>(type: T.Type) -> T {         return self.withUnsafeBytes { $0.pointee }     } } 

Example usage:

let int: Int = 555 let data = Data(from: int) let status = KeyChain.save(key: "MyNumber", data: data) print("status: ", status)  if let receivedData = KeyChain.load(key: "MyNumber") {     let result = receivedData.to(type: Int.self)     print("result: ", result) } 
like image 131
Kosuke Ogawa Avatar answered Sep 18 '22 10:09

Kosuke Ogawa