I am trying to use iOS security framework to securely communicate with my server. I have a certificate file from which I am able to get a public key reference. This is what I doing.
NSString *certPath = [[NSBundle mainBundle] p开发者_如何学GoathForResource:@"supportwarriors.com" ofType:@"cer"];
SecCertificateRef myCertificate = nil;
NSData *certificateData = [[NSData alloc] initWithContentsOfFile:certPath];
myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certificateData);
//got certificate ref..Now get public key secKeyRef reference from certificate..
SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
SecTrustRef myTrust;
OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);
SecTrustResultType trustResult;
if (status == noErr) {
status = SecTrustEvaluate(myTrust, &trustResult);
}
publicKey = SecTrustCopyPublicKey(myTrust);
Above piece of code works perfectly on iPhone and I have tested that. I am able to securely communicate with my server. But when I try to run my app on iPad (in 2x mode) the above code getting crashed. After debug, I found out that secTrustCreateWithCertificate is crashing and the crash log is given below.. Certificate I used is same for both iPad and iPhone...The function above secCertificateCreateWithData returning a certificate reference and is not nil...So that is not the cause of crash..What am I doing wrong.
*** -[NSCFType count]: unrecognized selector sent to instance 0x14af24
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFType count]: unrecognized selector sent to instance 0x14af24'
The documentation for SecTrustCreateWithCertificates
claims that you can pass either a single certificate OR an array. The exception you're receiving states that -[NSCFType count]: unrecognized selector sent to instance
. What's happening in iOS 3.2 is that SecTrustCreateWithCertificates
is treating the input value like a CFArray without checking first to see if it's a singular SecCertificateRef
.
To get around this, you can do something similar to the following code:
SecCertificateRef certs[1] = { certificate };
CFArrayRef array = CFArrayCreate(NULL, (const void **) certs, 1, NULL);
if(SecTrustCreateWithCertificates(array, x509Policy, &trustChain) == errSecSuccess)
just remember to CFRelease(array)
at the appropriate scope.
精彩评论