Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you set the keychain's access to be kSecAttrAccessibleAfterFirstUnlock in Swift?

Tags:

ios

swift

Googled but can't find anything on how to set this attribute for the keychain in swift. There's a few bits and pieces about it with Obj-C, but trying to find a correspondence between Swift usage of the keychain and Obj-C is bloddy impossible almost.

I've got some existing code (from the Realm Swift documentation) to set an encryption key, but want to set the access from the default to kSecAttrAccessibleAfterFirstUnlock.

class func getKey() -> NSData {
    let keychainIdentifier = "Realm.EncryptionKey"
    let keychainIdentifierData = keychainIdentifier.data(using: String.Encoding.utf8, allowLossyConversion: false)!

    // First check in the keychain for an existing key
    var query: [NSString: AnyObject] = [
        kSecClass: kSecClassKey,
        kSecAttrApplicationTag: keychainIdentifierData as AnyObject,
        kSecAttrKeySizeInBits: 512 as AnyObject,
        kSecReturnData: true as AnyObject
    ]


    var dataTypeRef: AnyObject?
    var status = withUnsafeMutablePointer(to: &dataTypeRef) { SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0)) }
    if status == errSecSuccess {
        return dataTypeRef as! NSData
    }

    // No pre-existing key from this application, so generate a new one
    let keyData = NSMutableData(length: 64)!
    let result = SecRandomCopyBytes(kSecRandomDefault, 64, keyData.mutableBytes.bindMemory(to: UInt8.self, capacity: 64))
    assert(result == 0, "Failed to get random bytes")

    // Store the key in the keychain
    query = [
        kSecClass: kSecClassKey,
        kSecAttrApplicationTag: keychainIdentifierData as AnyObject,
        kSecAttrKeySizeInBits: 512 as AnyObject,
        kSecValueData: keyData
    ]

    status = SecItemAdd(query as CFDictionary, nil)

    return keyData
}
like image 691
Gruntcakes Avatar asked Feb 07 '17 23:02

Gruntcakes


1 Answers

Add kSecAttrAccessible: kSecAttrAccessibleAfterFirstUnlock to the query dictionary you use to add the key.

If you want to update the accessibility status after its already been added, you need to specify the kSecValueData and kSecAttrAccessible keys in the dictionary you pass to SecItemUpdate.

like image 124
Dave Weston Avatar answered Nov 07 '22 04:11

Dave Weston