Mike
Mike

Reputation: 629

SecKeyCreateSignature give Bad Access with privateKey

I am recieving Bad Access when trying to create a signature with xcode SecKeyCreateSignature.

This flows with biometric enrollment in a webview. When the user hits the enrollment page the device sends to the webview the device Id and a public key.

To generate the key I have...

private let tag = "com.CustomTagName.private",
    deviceId = UIDevice.current.identifierForVendor!.uuidString,

    privateKeyAttr: [NSObject: NSObject] = [
        kSecAttrIsPermanent:true as NSObject,
        kSecAttrApplicationTag: "com.CustomTagName.private".data(using: .utf8)! as NSObject,
        kSecClass: kSecClassKey,
        kSecAttrType: kSecAttrKeyTypeRSA,
        kSecAttrKeySizeInBits : 2048 as NSObject,
        kSecReturnData: kCFBooleanTrue
    ],
    privateKey : SecKey?,
    privateKeyStr = ""
;

...

private func generateKeys() throws {
    var err: Unmanaged<CFError>?
    
    do {
        guard let prk = SecKeyCreateRandomKey(privateKeyAttr as CFDictionary, &err) else {
            throw err!.takeRetainedValue() as Error
        }

        // After creating a random private key It appears we have to unwrap it...?
        guard let unWrappedKey = SecKeyCopyExternalRepresentation(prk, &err) as Data? else {
            throw err!.takeRetainedValue() as Error
        }

        self.privateKeyStr = unWrappedKey.base64EncodedString()
        self.privateKey = prk;

    } catch {

    }
}

From here I use

let publicKey = SecKeyCopyPublicKey(self.privateKey!);

If I was going to call SecKeyCreateSignature the I have no issue. But I dont call the signature until the user needs to login. So I retrieve the key using...

let message = "HereIAm";
let statusPrivateKey = SecItemCopyMatching(privateKeyAttr as CFDictionary, &resultPrivateKey)

if statusPrivateKey != noErr || resultPrivateKey == nil{
    fatalError("Error getting private key")
}

self.privateKey = resultPrivateKey as! SecKey?;
self.privateKeyStr = (privateKey as! Data).base64EncodedString()

// Bad Access Error Here \\
guard let signFingerPrint = SecKeyCreateSignature(privateKey!, SecKeyAlgorithm.rsaSignatureMessagePKCS1v15SHA512, message.data(using: .utf8)! as CFData, &err) else {
    fatalError("Signing error")
}

I do notice that the SecKey does not need to be unwrapped with SecKeyCopyExternalRepresentation.

I dont understand the difference in the to Sec Keys when the data is the same.

How do I retrieve the private key to that I can create the signature off it?

Upvotes: 4

Views: 970

Answers (1)

Mike
Mike

Reputation: 629

I found the answer... kinda, In my privateAttrs I have

kSecReturnData: kCFBooleanTrue

and should be

kSecReturnRef: kCFBooleanTrue

Im my case I was returning Data as the type but I needed to return the type of the original reference.

Upvotes: 3

Related Questions