Certificate Retention in Xcode

I got below code for certificate in Android

CertificatePinner certificatePinner = new CertificatePinner.Builder() .add("publicobject.com", "sha1/DmxUShsZuNiqPQsX2Oi9uv2sCnw=") .add("publicobject.com", "sha1/SXxoaOSEzPC6BgGmxAt/EAcsajw=") .add("publicobject.com", "sha1/blhOM3W9V/bVQhsWAcLYwPU6n24=") .add("publicobject.com", "sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=") .build(); 

How to achieve the same task in iOS using NSURLSession method?

There is a link code here

 - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0); NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate)); NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"MyLocalCertificate" ofType:@"cer"]; NSData *localCertData = [NSData dataWithContentsOfFile:cerPath]; if ([remoteCertificateData isEqualToData:localCertData]) { NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; } else { [[challenge sender] cancelAuthenticationChallenge:challenge]; } 

EDIT PART

I got the solution below, the delegation function is automatically called in NSURLSession, can anyone explain how it will work? ALSO Need to send a multiplier certificate, how do I do this?

  (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { NSString *authMethod = [[challenge protectionSpace] authenticationMethod]; if ([authMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential,credential); } else { SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0); NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate)); NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"MyLocalCertificate" ofType:@"cer"]; NSData *localCertData = [NSData dataWithContentsOfFile:cerPath]; NSURLCredential *credential; if ([remoteCertificateData isEqualToData:localCertData]) { credential = [NSURLCredential credentialForTrust:serverTrust]; [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; } else { [[challenge sender] cancelAuthenticationChallenge:challenge]; } completionHandler(NSURLSessionAuthChallengeUseCredential, credential); NSLog(@"Finished Challenge"); } } 
+6
source share
1 answer

The if block skips the certificate if the authentication method is NSURLAuthenticationMethodServerTrust . I'm not quite sure why you will do this - you will have to look at the source where you received this piece of code and see what these requirements are.

If the authentication method is something else, the else block binds the certificate.

The serverTrust variable serverTrust sent to the SSL transaction state from the server. The main thing here is that it has a chain of certificates that authenticate the server. The next line of certificate sets the certificate of the sheet in the chain, that is, the server certificate.

remoteCertificateData is essentially a large blob representing the information in a certificate. The CFBridgingRelease call CFBridgingRelease necessary for memory management (all CFxxx functions are C / C ++ functions, not Objective-C, and memory management is a bit more complicated than usual).

localCertData is the binary information code in the local copy of the certificate. Note that iOS apps (more or less) are a collection of files, including an executable, as well as various resources, etc. As part of the build process, you must arrange for a copy of the server certificate to be included in the collection ( NSBundle ) of files. The cerPath variable cerPath path to the file for the local copy of the certificate.

Finally, we check if two binary cells are equal. If not, then the certificate from the server is bogus, and we will not continue the request.

I'm not quite sure what you mean by "Need to send a multiplier certificate." Judging by the Java code that you are referencing, I assume that you mean that you want to compare the server certificate with several local certificates. In this case, something (approximately) similar to the following (note: unverified code):

  SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0); NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate)); BOOL match = NO; NSURLCredential *credential; for (NSString *path in [[NSBundle mainBundle] pathsForResourcesOfType:@"cer" inDirectory:@"."]) { NSData *localCertData = [NSData dataWithContentsOfFile:path]; if ([remoteCertificateData isEqualToData:localCertData]) { credential = [NSURLCredential credentialForTrust:serverTrust]; match = YES; break; } } if (match) { [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; } else { [[challenge sender] cancelAuthenticationChallenge:challenge]; } completionHandler(NSURLSessionAuthChallengeUseCredential, credential); NSLog(@"Finished Challenge"); 
+1
source

Source: https://habr.com/ru/post/1013381/


All Articles