7

I want to ssl public key pinning in swift, I read lot of examples how to do that, last think who I can't find is How to compare two public keys in SecKey object format. Example:

let serverPublicKey = SecTrustCopyPublicKey(secTrust) /*return SecKey object from actual SecTrust*/
let clientPublicKey = getLocalPublicKeyFromDer() /*return SecKey from .der local*/

how to compare them? At now I do that and it works:

if(serverPublicKey! as AnyObject).isEqual(clientPublicKey){
  /*Key is the same, pinning OK!*/
}

find it way on gitHub: https://github.com/teamcarma/IOS-AlamofireDomain/blob/master/Source/ServerTrustPolicy.swift

but is cast to AnyObject a good idea? How to work isEqual on casted SecKey? Can any explain me?

ps. Another idea is getting base64 from SecKey - I try and it also works, but it require a KeyChain temp operations and look no profesional.

luky0007
  • 79
  • 1
  • 7
  • Found similar solution here: http://stackoverflow.com/a/29234388/117733 also casting to AnyObject and compare. Seems good to me. Based on the doc here https://developer.apple.com/reference/security/seckey, it is an object. So casting to `AnyObject` should always work. – Zhao Nov 24 '16 at 01:42

4 Answers4

1

Cited from the headers:

"Most SecKeychainItem functions will work on an SecKeyRef."*

You may cast SecKeyRef to a SecKeychainItem. If this is a valid operation (that is, the key is a keychain item), you may apply function

SecKeychainItemCreatePersistentReference

and get a CFData object, filled with attributes and data. Then check with memcpyon the bytes or cast it to a NSData object and check with isEqualToData. Don't forget to release the CFData object.

Edit

On iOS, as far as I known, the only reliable approach is to copy the data (or secret) into the keychain, using a temporary key, so that you can find it again, and then extract the data. It's cumbersome, but if you just implement it in a minimalistic way, it should not take more than 30 lines of code. I have a working example.

I The usual disclaimer: Use this at your own risk, and always be careful with security stuff.

CouchDeveloper
  • 18,174
  • 3
  • 45
  • 67
  • Yes I try somethink to convert to NSData and it worked with keychain, but is adding and deleting on keychain - very ugly for me (basing on last comment on this ticket): http://stackoverflow.com/questions/27758446/how-do-i-encode-an-unmanagedseckey-to-base64-to-send-to-another-server . I didn't know about SecKeychainItemCreatePersistentReference. Why isEqual with casted anyObject works? :) – luky0007 Jan 26 '16 at 08:47
  • @luky0007 You just need to compare the bytes in the `CFData` object. How you accomplish this, doesn't matter. But IF you properly convert the `CFData` to an `NSData` for the sake of ARC, then just use method `isEqualToData`. See also: http://stackoverflow.com/questions/25262542/how-to-convert-unmanagedcfdata-to-nsdata – CouchDeveloper Jan 26 '16 at 08:56
  • That function is not available on iOS. – chedabob Jan 26 '16 at 09:14
  • Yep - I checked it's only for OSX. – luky0007 Jan 26 '16 at 09:59
  • @chedabob @luky0007 Yeah, this is true. Basically, you need to use `SecItemCopyMatching` which queries either the keychain or an array of sec items and returns a matching sec item. You can specify that the returned sec item is represented as a CFData. Unfortunately, doing this "swiftly" is still too cumbersome. I'll try to find a nice solution, later. – CouchDeveloper Jan 26 '16 at 10:04
1

iOS10 added:

CFDataRef _Nullable SecKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error)

so you can now create two Data (NSData) objects, then compare those.

David H
  • 40,852
  • 12
  • 92
  • 138
0

Have a look at this answer for just getting the NSData: Can I get the modulus or exponent from a SecKeyRef object in Swift?

You can then compare the two NSData instances using isEqualToData:

Community
  • 1
  • 1
chedabob
  • 5,835
  • 2
  • 24
  • 44
  • I know that and it works, unfortunattly is crazy walk around - adding to keychain, next deleting from keychain only for convert SecKey to NSData, crazy apple :), why there are no function to convert that? SSL Pining is the basic think to create secure apps... Why if(serverPublicKey! as AnyObject).isEqual(clientPublicKey) works??? – luky0007 Jan 26 '16 at 09:55
-5

I don't have expereince in the domain, but if they are two strings (irrespectiveof their content), you would basically do a simple check:

if(string1 == string2)
{
 //condition logic
}
ksa_coder
  • 1,393
  • 3
  • 15
  • 38