Skip to content

Instantly share code, notes, and snippets.

@edwardmp
Created May 22, 2015 16:06
Show Gist options
  • Select an option

  • Save edwardmp/df8517aa9f1752e73353 to your computer and use it in GitHub Desktop.

Select an option

Save edwardmp/df8517aa9f1752e73353 to your computer and use it in GitHub Desktop.
Using NSURLSession with SSL public key pinning
/*
1. Adhere to the NSURLSessionDelegate delegate
2. Initialize NSURLSession and specify self as delegate (e.g. [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue: [NSOperationQueue mainQueue]];)
3. Add the method below to your class
4. Change the certificate resource name
*/
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"myCertName" ofType:@"cer"];
NSData *localCertData = [NSData dataWithContentsOfFile:cerPath];
if ([remoteCertificateData isEqualToData:localCertData])
{
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
}
else
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
}
}
@nicpro85

Copy link
Copy Markdown

So the myCertName.cer file in the bundle is the same file on apache server?

@NicosKaralis

Copy link
Copy Markdown

If you bundle the server certificate on the app, what do you do when the certificate expires? Do you need to send an update to fix it? And if you send an update before the certificate expires what happens to the app version that uses the old cert? Will it be unable to work?

@vijaytholpadi

Copy link
Copy Markdown

@NicosKaralis This is the very reason why AFSSLPinningModePublicKey is used instead of AFSSLPinningModeCertificate
Read more here: http://stackoverflow.com/a/16606296

@edwardmp

edwardmp commented Aug 2, 2016

Copy link
Copy Markdown
Author

@NicosKaralis @vijaytholpadi
Correct, if you use the same private key to create a new certificate it should have the same public key, hence this should not give any problem.

@KimiChiu

Copy link
Copy Markdown

I'm using Tomcat as my server.
The remoteCertificateData is not equal to my localCertData.
But it's working when I'm using the same localCertData on Android.
What's the difference?
What is the file should I use on iOS?

@sasisg

sasisg commented Jun 13, 2018

Copy link
Copy Markdown

Any reply to the below

I'm using Tomcat as my server.
The remoteCertificateData is not equal to my localCertData.
But it's working when I'm using the same localCertData on Android.
What's the difference?
What is the file should I use on iOS?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment