CFDictionaryCreate crashes in Xcode 8 swift 3

不想你离开。 提交于 2019-12-12 06:08:57

问题


I have the following code for retrieving and storing RSAkeydata

fileprivate func retrieveAndStoreRSAKeyData(isPublic: Bool) throws -> CFData {

    var resultCode = noErr
    var result: CFData
    let value = {
        if isPublic {
            let t = self.publicTag
            print(t)
        }
        else
        {
            let s = self.privateTag
            print(s)
        }
    }
    var keyCallbacks = kCFTypeDictionaryKeyCallBacks
    var valueCallbacks = kCFTypeDictionaryValueCallBacks
    let keys = [Unmanaged.passUnretained(kSecClass).toOpaque(), Unmanaged.passUnretained(kSecAttrApplicationTag).toOpaque(), Unmanaged.passUnretained(kSecAttrKeyType).toOpaque(), Unmanaged.passUnretained(kSecReturnData).toOpaque()]
    let values = [Unmanaged.passUnretained(kSecClassKey).toOpaque(), Unmanaged<AnyObject>.passUnretained(value as AnyObject).toOpaque(), Unmanaged.passUnretained(kSecAttrKeyTypeRSA).toOpaque(), Unmanaged.passUnretained(kCFBooleanTrue).toOpaque()]
    let queryKey = CFDictionaryCreate(kCFAllocatorDefault,UnsafeMutablePointer.allocate(capacity: keys.count),UnsafeMutablePointer.allocate(capacity: values.count), 4, &keyCallbacks, &valueCallbacks)

    // Get the key.
    var item: AnyObject?
    resultCode = SecItemCopyMatching(queryKey!, &item)

    if(resultCode != noErr) {

        try generateKeyPair()
        /*
        Recurcively call the retrieval again after keys have been generated
        */
        result = try retrieveAndStoreRSAKeyData(isPublic: isPublic)
    }
    else {

        result = item as! CFData
    }

    return result
}

The CFDictionaryCreate always fails and code crashes in this line in

     let queryKey = CFDictionaryCreate(kCFAllocatorDefault,UnsafeMutablePointer.allocate(capacity: keys.count),UnsafeMutablePointer.allocate(capacity: values.count), 4, &keyCallbacks, &valueCallbacks)

Can someone help me out on this. Thanks in advance


回答1:


to generate a key pair

func generateKeyPair(_ publicTag: String, privateTag: String, keySize: Int)->Bool {
        let privateAttributes = [String(kSecAttrIsPermanent): true,
                                 String(kSecAttrApplicationTag): privateTag] as [String : Any]
        let publicAttributes = [String(kSecAttrIsPermanent): true,
                                String(kSecAttrApplicationTag): publicTag] as [String : Any]

        let pairAttributes = [String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
                              String(kSecAttrKeySizeInBits): keySize,
                              String(kSecPublicKeyAttrs): publicAttributes,
                              String(kSecPrivateKeyAttrs): privateAttributes] as [String : Any]

        var publicRef: SecKey?
        var privateRef: SecKey?
        switch SecKeyGeneratePair(pairAttributes as CFDictionary, &publicRef, &privateRef) {
        case noErr: return true
        default: return false
        }
    }

and few helper functions

func obtainKey(_ tag: String) -> SecKey? {
    var keyRef: AnyObject?
    let query: Dictionary<String, AnyObject> = [
        String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
        String(kSecReturnRef): kCFBooleanTrue as CFBoolean,
        String(kSecClass): kSecClassKey as CFString,
        String(kSecAttrApplicationTag): tag as CFString,
        ]

    let status = SecItemCopyMatching(query as CFDictionary, &keyRef)

    switch status {
    case noErr:
        if let ref = keyRef {
            return (ref as! SecKey)
        }
    default:
        break
    }

    return nil
}

func obtainKeyData(_ tag: String) -> Data? {
    var keyRef: AnyObject?
    let query: Dictionary<String, AnyObject> = [
        String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
        String(kSecReturnData): kCFBooleanTrue as CFBoolean,
        String(kSecClass): kSecClassKey as CFString,
        String(kSecAttrApplicationTag): tag as CFString,
        ]

    let result: Data?

    switch SecItemCopyMatching(query as CFDictionary, &keyRef) {
    case noErr:
        result = keyRef as? Data
    default:
        result = nil
    }

    return result
}

func insertPublicKey(_ publicTag: String, data: Data) -> SecKey? {
    let query: Dictionary<String, AnyObject> = [
        String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
        String(kSecClass): kSecClassKey as CFString,
        String(kSecAttrApplicationTag): publicTag as CFString,
        String(kSecValueData): data as CFData,
        String(kSecReturnPersistentRef): true as CFBoolean]

    var persistentRef: AnyObject?
    let status = SecItemAdd(query as CFDictionary, &persistentRef)

    if status != noErr && status != errSecDuplicateItem {
        return nil
    }

    return obtainKey(publicTag)
}

func deleteKey(_ tag: String) -> Bool {
    let query: Dictionary<String, AnyObject> = [
        String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
        String(kSecClass): kSecClassKey as CFString,
        String(kSecAttrApplicationTag): tag as CFString]

    return SecItemDelete(query as CFDictionary) == noErr
}

func updateKey(_ tag: String, data: Data) -> Bool {
    let query: Dictionary<String, AnyObject> = [
        String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
        String(kSecClass): kSecClassKey as CFString,
        String(kSecAttrApplicationTag): tag as CFString]

    return SecItemUpdate(query as CFDictionary, [String(kSecValueData): data] as CFDictionary) == noErr
}


来源:https://stackoverflow.com/questions/44203001/cfdictionarycreate-crashes-in-xcode-8-swift-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!