Can I use dynamically created SecClassIdentity object from SecIdentityCreateWithCertificate for TLS challenge?

If I have a valid x509 certificate on MacOS that has paired public key, can I use it to dynamically create SecClassIdentity object for TLS challenge as below?

The server that we sent the TLS request to was able to recognize the challenge request and returned HTTP code 200.

SecClassCertificate Cert = [I have a valid cert here] 
 NSArray *certs = [NSArray arrayWithObjects:(__bridge id)Cert, nil];
     
    SecIdentityRef newBornIdentity = nil;
    SecIdentityCreateWithCertificate(nil, Cert, &newBornIdentity);
    if (newBornIdentity)
    {
      NSURLCredential *cred = [NSURLCredential credentialWithIdentity:newBornIdentity
                                certificates:certs
                                persistence:NSURLCredentialPersistenceForSession];
      completionHandler(NSURLSessionAuthChallengeUseCredential,cred);
    }


If I have a valid x509 certificate on macOS that has paired public key, can I use it to dynamically create [SecIdentity] object for TLS challenge as below?

Did you mean private key in the above?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Hi @eskimo Thank you for your quick response. Yep I meant private key.
Nonetheless, can I generate Identity dynamically from such a cert using "SecIdentityCreateWithCertificate" and use that Identity for NSURLCredential credentialWithidentity?

Thank you,
Peter

Yep I meant private key.

OK. Does that mean you have a SecKey object for this private key? If so, where did that come from?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
This is what we did
1) First generate asymmetric RSA public and private keypair using SecKeyGeneratePair
2) Read private key data genearted from 1) using SecKeyCopyExternalRepresentation
3) Generate PKCS Certificate signing request using OpenSSL
4) Send to the server
5) Server returns signed x509 certificate
6) We write this x509 certificate into keychain :)


Once we have done all of that above, we currently retrieve a list of all identity objects and perform linear search to find the identity that we're interested in by looking at the issuer name using below code


   NSDictionary *getQuery = @{ (id)kSecClass: (id)kSecClassIdentity,
                (id)kSecReturnAttributes:(__bridge id)(kCFBooleanTrue),
                (id)kSecMatchLimit : (__bridge id)kSecMatchLimitAll,
                (id)kSecReturnRef: (__bridge id)(kCFBooleanTrue),
                };

  status = SecItemCopyMatching((__bridge CFDictionaryRef)getQuery, (CFTypeRef *)&identityArr);

Then uses this filtered identity for NSURLCredential - credentialWithIdentitiy API,
but I thought it would also be equally valid to simply generate Identity object using
SecIdentityCreateWithCertificate API and use it instead :)


I was wondering if you could help to confirm whether it is valid for me to use
1) SecIdentityCreateWithCertificate to generate Identity dynamically from x509 cert from above, and then use it with
NSURLCredential credentialWithidentity?

2) additionally, would it also be ok to use such a dynamically generated identity with SecIdentitySetPreferred ?


Thanks,
Peter




First generate asymmetric RSA public and private keypair using
SecKeyGeneratePair

Just to be clear, you’re setting kSecAttrIsPermanent in order to put these in the keychain, right?

ps You don’t need to add the public key to the keychain (and in some cases it can cause problems) so I recommend that you use the new routine, SecKeyCreateRandomKey, which only creates the private key, and then use SecKeyCopyPublicKey to get its public key.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Aha I see!
Thank you so much for letting me know, eskimo! :) That sounds like a better practice indeed. we actually don't use public keys at all. Yep we do set kSecAttrIsPermanent.


However, on MacOS, I was still wondering if I can use SecIdentityCreateWithCertificate on a x509 cert generated using above steps to dynamically create a Identity reference object, and then use it for

1)
NSURLCredential credentialWithidentity API for TLS challenge

2) Also with SecIdentitySetPreferred?

I'd really appreciate your response on these two questions also, although I really appreciate your answers on the proper way to use private keys as well :) :)

Yep we do set kSecAttrIsPermanent.

Cool. Given that, SecIdentityCreateWithCertificate is an excellent fit for your requirements.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Thank you so much, eskimo! Really appreciate your help.

In the future we might migrate from RSA to ECC (secure enclave storage) for our private keys and wanted to ask a couple of follow up questions

1) Will SecKeyCopyPublicKey always produce the same public key also for secure enclave ECC generated private key?

2) Could you provide some of the examples on the issues that you mentioned that could happen if we store public key in the keychain
(You mentioned above: ps You don’t need to add the public key to the keychain (and in some cases it can cause problems)
question 2) is just for my learning :) :)

Thank you again, eskimo!!


Will SecKeyCopyPublicKey always produce the same public key also for
secure enclave ECC generated private key?

I don’t really understand what you mean by “the same” here. However, I can confirm that SecKeyCopyPublicKey will produce a public key for a private key even if that private key is an ECC key protected by the SE.

Could you provide some of the examples on the issues that you
mentioned that could happen if we store public key in the keychain

There’s a bug in SecKeyGeneratePair that causes it to mark both keys as private (r. 15615260). This causes trouble later on when you import the certificate and form an identity, because the identity formation code looks for the matching private key and, on occasion, finds the public key. Needless to say, that doesn’t end well.

The good news here is that the workaround, don’t only store the private key by switching to SecKeyCreateRandomKey, is also the best solution because:
  • SecKeyCreateRandomKey is a nicer API.

  • SecKeyCopyPublicKey lets you easily get the public key.

  • You don’t waste space in the keychain (OK, so it’s a trivial amount of space but still…).

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Thank you, eskimo!

1) I don’t really understand what you mean by “the same” here. 
Sorry for the confusion. what I meant was will there always be a 1-1 mapping between ECC private key and the public key retrieved from it through SecKeyCopyPublicKey? will it be the same object with the same data? - sorry I am not too familiar with ECC.

2) The good news here is that the workaround, don’t store the private key by switching to SecKeyCreateRandomKey, is also the best solution because:
Just to confirm - you meant "don't store the public key" here right?

Thank you! :)

what I meant was will there always be a 1-1 mapping between ECC
private key and the public key retrieved from it through
SecKeyCopyPublicKey? will it be the same object with the same data?

The concept of object equality is a tricky one. You may not get exactly the same object back but the object will always represent the same public key. For example, if you call SecKeyCopyExternalRepresentation on it you’ll always get the same bytes.

you meant "don't store the public key" here right?

D’oh! I’ve edited the post to fix this.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Can I use dynamically created SecClassIdentity object from SecIdentityCreateWithCertificate for TLS challenge?
 
 
Q