Reputation: 51
I am using AFnetworking. My application webserver is in TLS 1.2. I want to add Certificate pinning to my iOS app. My code as below:
AFHTTPSessionManager *manager=[[AFHTTPSessionManager manager] initWithBaseURL:serviceURL];
NSSet *certificates = [AFSecurityPolicy certificatesInBundle:[NSBundle mainBundle]];
AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:certificates];
policy.validatesDomainName = YES;
policy.allowInvalidCertificates = YES;
opManager.securityPolicy = policy;
I have my valid server certificate in my bundle and with this code webservices are working fine. But when I tried the same with an incorrect sample certificate, that time also webservices are working. I even tried with no certificates in bundle, that time also, webservices are working fine. Could anyone please explain this? AppTransportSecurity is turned ON in my app.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
</dict>
Upvotes: 2
Views: 1610
Reputation: 197
The following function will do the public key certificate pinning for you:
- (AFHTTPSessionManager*) getSessionManager: (NSString *) serverUrl {
AFHTTPSessionManager * sessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString: serverUrl]];
if ([serverUrl hasPrefix:@"https"]) {
NSString *certificate = nil;
NSString *cerPath = [[NSBundle mainBundle] pathForResource: certificate ofType:@"der"];
if (cerPath != nil) {
NSData *certData = [NSData dataWithContentsOfFile: cerPath];
AFSecurityPolicy* policy = [AFSecurityPolicy policyWithPinningMode: AFSSLPinningModePublicKey];
policy.pinnedCertificates = [NSSet setWithArray: @[certData]];
[policy setValidatesDomainName: YES];
[policy setAllowInvalidCertificates: NO];
sessionManager.securityPolicy = policy;
}
}
return sessionManager;
}
And to call this function use:
AFHTTPSessionManager * sessionManager = [self getSessionManager: @"https://example.com"];
Obtaining the certificate correct data and format is very important. You need to add the following der certificate to your project:
openssl s_client -connect example.com:443 </dev/null |openssl x509 -outform DER -out example.der
Upvotes: 1
Reputation: 51
I found a solution to this issue. Please find below the code I used to replace existing code. It's working as expected.
AFHTTPSessionManager *opManager=[[AFHTTPSessionManager manager] initWithBaseURL:baseUrl];
opManager.requestSerializer = [AFHTTPRequestSerializer serializer];
opManager.responseSerializer = [AFHTTPResponseSerializer serializer];
// SSL Pinning
NSString *certificatePath = [[NSBundle mainBundle] pathForResource:@"xxxxxxxx.com" ofType:@"der"];
NSData *certificateData = [NSData dataWithContentsOfFile:certificatePath];
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
[securityPolicy setAllowInvalidCertificates:YES];
[securityPolicy setPinnedCertificates:@[certificateData]];
[opManager setSecurityPolicy:securityPolicy];
Upvotes: 2