9

I am developing an iOS app using swift 3.

I need to export an SecKey (which is the user RSA publickey reference) to a string (e.g base64) in order to share it through a generated QRCode.

It also has to work the other way since the other user that scans the QRCode, will be able to rebuild a SecKey reference from the string extracted from the QRCode.

I found few tutorials but I don't understand exactly what I need to extract from the SecKey reference, and I don't know how to convert it to a String.

Scaraux
  • 3,841
  • 4
  • 40
  • 80
  • Can you get the SecKey` as `Data`? Once you have `Data`, getting a base64 string is easy. – rmaddy Apr 27 '17 at 23:55
  • Do you really need to use that tricky `SecKey` class of yours? After reading [this detailed question](http://stackoverflow.com/questions/34408825/can-i-get-the-modulus-or-exponent-from-a-seckeyref-object-in-swift/43225656#43225656) I don't think there is an easy hack around this :-( – Paulo Mattos Apr 27 '17 at 23:55
  • @PauloMattos unfortunately, yes. The cryptographic libraries I am using require a SecKey object, as I am generating those keys from the app. – Scaraux Apr 28 '17 at 00:26

1 Answers1

22

Export Key (iOS 10 only)

var error:Unmanaged<CFError>?
if let cfdata = SecKeyCopyExternalRepresentation(publicKey!, &error) {
   let data:Data = cfdata as Data
   let b64Key = data.base64EncodedString()
}

See https://stackoverflow.com/a/30662270/5276890 and https://stackoverflow.com/a/27935528/5276890 for longer ways which probably support iOS < 10.

Reimport Key

guard let data2 = Data.init(base64Encoded: b64Key) else {
   return
}

let keyDict:[NSObject:NSObject] = [
   kSecAttrKeyType: kSecAttrKeyTypeRSA,
   kSecAttrKeyClass: kSecAttrKeyClassPublic,
   kSecAttrKeySizeInBits: NSNumber(value: 512),
   kSecReturnPersistentRef: true as NSObject
]

guard let publicKey = SecKeyCreateWithData(data2 as CFData, keyDict as CFDictionary, nil) else {
    return
}

Note: This generates a base64 key and not a certificate. A lot of code samples online deal with how to generate a public key from a certificate using SecCertificateCreateWithData

Also: 512 bit is fast to generate but worthless. Pick a longer and secure value once you're satisfied with the results.

I got valid results back when importing the key I generated and exported, so I assume it works, but I did not try to encrypt and decrypt with it.

Community
  • 1
  • 1
Roy Falk
  • 1,685
  • 3
  • 19
  • 45
  • I'm going to try that tomorrow. On the reimport, is `cfdata` the base64 string ? – Scaraux Apr 28 '17 at 08:20
  • oops. Sorry. I was lazy and didn't bother generating Data from String and CFData from Data. Can you handle that? Otherwise I'll try and add the code later today. – Roy Falk Apr 28 '17 at 08:25
  • Never mind. I've just edited the code. Damn the 5 minute limit on comments! – Roy Falk Apr 28 '17 at 08:31
  • Thank you, it works for exporting public key string, and I reuse it for exporting private key as well. – Medhi Apr 15 '20 at 13:08
  • There is also the official documentation by Apple for converting between `SecKey` and `Data`: https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_as_data – Nickkk Apr 21 '23 at 12:58
  • @Nickkk this question is six years old. As the one who answered the question, I don't recall this documentation existing back then. Also, swift was rapidly evolving back then. IIRC, Swift 2 was very different from 3. Things only slowed down in versions 4 and 5. – Roy Falk Apr 29 '23 at 05:50