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?

jackreichert
  • 1,979
  • 2
  • 23
  • 36
  • How is publicKey defined? Is it a NSData? – clozach Jan 03 '15 at 19:11
  • Thanks! I've edited my question to give more information. – jackreichert Jan 03 '15 at 19:16
  • 1
    I don't know enough about this to offer an answer, but you might learn something from this blog post: http://netsplit.com/swift-generating-keys-and-encrypting-and-decrypting-text – clozach Jan 03 '15 at 20:30
  • 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. – jackreichert Jan 03 '15 at 20:32
  • [This](http://stackoverflow.com/questions/6410270/send-public-keygenerated-as-seckeyref-in-iphone-to-serverin-java/14140081#14140081) looks like the solution. But I'm still having trouble converting it to swift. – jackreichert Jan 03 '15 at 21:33
  • I found [this](https://github.com/xxxg0001/RSA/blob/9c73eb39cfee60ce6dae7ae9bff3cb06e3752d01/RSA-sample/RSA-sample/RSA.swift) as well. It may be helpful to anyone else trying to work with keypairs. – jackreichert Jan 03 '15 at 22:36

3 Answers3

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
    }
}
ThorstenC
  • 1,264
  • 11
  • 26
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.

Community
  • 1
  • 1
Raphael
  • 9,779
  • 5
  • 63
  • 94
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()
Jere
  • 1
  • 1