How do I encode an unmanaged<SecKey> to base64 to send to another server?
Asked Answered
P

3

3

I'm trying to use key pair encryption to validate identity between my app and my PHP server. To do this I need to send the public key over to the server after I generate it in my app.

if let pubKey = NSData(base64EncodedData: publicKey, options: NSDataBase64DecodingOptions.allZeros)! {
    println(pubKey)
}

publicKey is of type Unmanaged<SecKey>.

The error I'm getting in the above code is: Extra argument 'base64EncodedData' in call

How would I do this? Is there a better way?

Edit: This is how the keypair is generated:

var publicKeyPtr, privateKeyPtr: Unmanaged<SecKey>?
let parameters = [
    String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
    String(kSecAttrKeySizeInBits): 2048
]
let result = SecKeyGeneratePair(parameters, &publicKeyPtr, &privateKeyPtr)
let publicKey = publicKeyPtr!.takeRetainedValue()
let privateKey = privateKeyPtr!.takeRetainedValue()
let blockSize = SecKeyGetBlockSize(publicKey)

Edit 2: So the issue is that SecKey is not NSData, so my question here should be: How do I convert a publicKey:SecKey to NSData?

Piercy answered 3/1, 2015 at 19:0 Comment(6)
How is publicKey defined? Is it a NSData?Yetah
Thanks! I've edited my question to give more information.Piercy
I don't know enough about this to offer an answer, but you might learn something from this blog post: netsplit.com/…Yetah
Thank you! I'm actually almost there. Will post my answer as soon as I figure out the last piece of the puzzle... (edit) Nope, I don't. But I will update as soon as I do have something.Piercy
This looks like the solution. But I'm still having trouble converting it to swift.Piercy
I found this as well. It may be helpful to anyone else trying to work with keypairs.Piercy
G
6

It seems that you can temporary store the key to keychain and then get it back and convert it to data:

func convertSecKeyToBase64(inputKey: SecKey) ->String? {
    // First Temp add to keychain
    let tempTag = "de.a-bundle-id.temp"
    let addParameters :[String:AnyObject] = [
        String(kSecClass): kSecClassKey,
        String(kSecAttrApplicationTag): tempTag,
        String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
        String(kSecValueRef): inputKey,
        String(kSecReturnData):kCFBooleanTrue
    ]

    var keyPtr: Unmanaged<AnyObject>?
    let result = SecItemAdd(addParameters, &keyPtr)
    switch result {
    case noErr:
        let data = keyPtr!.takeRetainedValue() as! NSData

        // Remove from Keychain again:
        SecItemDelete(addParameters)
        let encodingParameter = NSDataBase64EncodingOptions(rawValue: 0)
        return data.base64EncodedStringWithOptions(encodingParameter)

    case errSecDuplicateItem:
        println("Duplicate Item")
        SecItemDelete(addParameters)
        return nil

    case errSecItemNotFound:
        println("Not found!")
        return nil

    default:
        println("Error: \(result)")
        return nil
    }
}
Gondolier answered 5/6, 2015 at 8:52 Comment(0)
S
0

While the fact is barely documented, you can pull out everything you need (that is, modulus and exponent) from the SecKey using SecKeyCopyAttributes.

See here for the details.

Schizomycete answered 7/4, 2017 at 16:42 Comment(0)
I
0

Swift 4 method to get base64 string from SecKey, publicKey :)

guard let publicKeyData = SecKeyCopyExternalRepresentation(publicKey!, nil) else {
            NSLog("\tError obtaining export of public key.")
            return ""
        }
        let publicKeyNSData = NSData(data: publicKeyData as Data)
        let publicKeyBase64Str = publicKeyNSData.base64EncodedString()
Imperforate answered 14/10, 2019 at 3:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.