问题
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