Unable to create Private keys from Data in iOS 16.1

I am using Elliptic Curve keys generated using SecKeyCreateRandomKey from the Security framework for performing Diffe Helman Key exchange in my app. After generating the key pair I am converting the Private key into data using SecKeyCopyExternalRepresentation(<myPrivateKey>,&error) and then store the base64 encoded string of this in the Keystore. To convert the Private key back I am using the following code

 let priKeyData = Data(base64Encoded: priKeyStr)
if(priKeyData != nil) {

       guard let dataPtr = CFDataCreate(kCFAllocatorDefault, UnsafePointer<UInt8>(Array(priKeyData!)), priKeyData!.count)
          else {return (nil) }
guard let priKey = SecKeyCreateWithData(dataPtr as CFData,attributes as CFDictionary,&error)
          else {return (nil)}
}

This works totally fine on iOS version prior 16.1. But in devices with iOS 16.1 the conversion from data to SecKey is failing with the following error:

Swift.Unmanaged<__C.CFErrorRef>(_value: Error Domain=NSOSStatusErrorDomain Code=-50 "EC private key creation from data failed" UserInfo={numberOfErrorsDeep=0, NSDescription=EC private key creation from data failed}))

What could be the reason for this? is there any other way to store SecKey in the Keystore without doing the conversions?

Accepted Reply

When I plug your code into Xcode 14.1 it flags an Initialization of 'UnsafePointer<UInt8>' results in a dangling pointer warning on your CFDataCreate line. For more background on that problem, see The Peril of the Ampersand.

In this case, however, the solution is very direct. You have a Data value and you want a CFData value, so add an as coercion:

guard
    let priKeyData = Data(base64Encoded: priKeyStr),
    let priKey = SecKeyCreateWithData(priKeyData as CFData, attributes as CFDictionary, &error)
else {
    return nil
}
return priKey

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Replies

When I plug your code into Xcode 14.1 it flags an Initialization of 'UnsafePointer<UInt8>' results in a dangling pointer warning on your CFDataCreate line. For more background on that problem, see The Peril of the Ampersand.

In this case, however, the solution is very direct. You have a Data value and you want a CFData value, so add an as coercion:

guard
    let priKeyData = Data(base64Encoded: priKeyStr),
    let priKey = SecKeyCreateWithData(priKeyData as CFData, attributes as CFDictionary, &error)
else {
    return nil
}
return priKey

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

For more background on that problem, see The Peril of the Ampersand.

This is super useful.

Thank you for your quick response and the informative Thread on Ampersand