SecKeyCreateFromPublicDataLooking at the source for SecKeyCreatePublicFromPrivate it really seems to resolve down to a call to SecItemExport on the private key, asking for an export format of kSecFormatBSAFE (at least for RSA keys). That's public API, so there's no reason you can't use it.
I'm having trouble with this too. I don't really understand how this is supposed to work. Without specifying some export parameter to the export function, how does it know whether it should export the private key or derive the public key and export that?
Using what loosegoose posted above, I can verify that :
1. I am passing in a PKCS8 PEM encoded 1024 unencrypted RSA private key. Specifiying kSecFormatBSAFE allows me to import the key.
2. When I try to export the item and specify kSecFormatBSAFE, I get a PKCS8 1024 unencrypted RSA private key (the same one byte for byte I passed in). If I specify kSecFormatOpenSSL, I get a PKCS1 1024 RSA Private key.
This all follows what I would expect from this table listed in Apple source:https://slack-files.com/T03BUJQE0-F07404UNM-166ce9f5f0
Which is what I would expect. I asked to export a private key from keychain, and I got it. What I don't understand is in SecKeyCreatePublicFromPrivate, where we are provided a reference to the private key. We call SecKeyCopyPublicBytes, which checks the algorithm ID. I would GUESS it would be defined as kSecRSAAlgorithmID (since it's an RSA key), in which case this is done:
return SecItemExport(key, kSecFormatBSAFE, 0, NULL, publicBytes);
The naming convention of the variables leads me to believe that we are exporting the public key portion of the provided key (which is a private key). The format just specifies that it should be exported (if we expect to be getting a public key) as PKCS1. But how can the export function possibly know that without any export attributes? To me this either returns the full private key into publicBytes, in which case that naming is extremely confusing, or ... I have no idea what else it would do.
When I call SecItemExport with my private key reference (Which should be exactly what the open source does), I get back the private key. When that function returns it calls SecKeyCreateFromPublicData, but from what I can see, it fully believes that it's getting public key data. That method reads the length of publicData, which has a length of the private key. This leads me to believe that the SecItemExport was really intended to spit out the public key and not the private key.
The ONLY thing I can think of that would make it "work" is if the type was set to kSecECDSAAlgorithmID, since it actually parses the ASN.1 encoding and tries to pull out the header and get to the actual public data, ignores the remander of the private key, and returns the public data. But that would be confusing since, EC would lead me to believe this is meant for an eliptic curve key.
I had to write a parser to remove the pkcs8 header information and derive the public key from the private key for iOS, because iOS doesnt have the ability to deal with PKCS8 keys. I'd rather use Apple maintined code rather than my own and was told that OS X had the capability to do such things.