Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@edwardmp
Created May 22, 2015 16:06
Show Gist options
  • Star 31 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save edwardmp/df8517aa9f1752e73353 to your computer and use it in GitHub Desktop.
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

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

@NicosKaralis
Copy link

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

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

@edwardmp
Copy link
Author

edwardmp commented Aug 2, 2016

@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

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
Copy link

sasisg commented Jun 13, 2018

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