I am currently working on an application that uses mutual authentication to communicate with the REST interface. Since I am very new to this topic, I studied a few examples - and now I have some questions. I hope that I can bring all the pieces of knowledge together to better understand the whole process.
The process should look like this:
- I received an exported server certificate containing the serverβs public key and added it to the application package (which is later used for SSL connection).
- The first request, which represents the beginning of two-way authentication, is a Mail request, which also contains a certificate signing request for a client certificate (which is required to communicate with the secure part of the REST interface). CSR is dynamically generated in code through the openSSL lib.
- The server response returns a signed certificate that is used to authenticate the client. This certificate is encoded in DER and Base64.
The code that I use to perform SSL encryption for the first request is as follows: The SSL screenshot works as expected.
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"server-cert" ofType:@"cer"]; SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0); NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate)); NSData *localCertificateData = [NSData dataWithContentsOfFile:cerPath]; if ([remoteCertificateData isEqualToData:localCertificateData]) { NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; [[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:[challenge protectionSpace]]; NSLog(@"Certificate Pinning Succeeded"); } else { [[challenge sender] cancelAuthenticationChallenge:challenge]; NSLog(@"Certificate Pinning Failed"); } }
But how do I handle the returned certificate from the server? As far as I know, I should use the following delegate methods of NSURLConnection - and provide this certificate somehow to the server (for further requests).
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace: (NSURLProtectionSpace *)protectionSpace { if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSLog(@"Wants to Authenticate Server Trust"); return YES; } if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodClientCertificate]) { NSLog(@"Wants to Authenticate Client Certificate"); return YES; } return NO; }
and
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
Now my question. I saw several examples using the PKCS12 format (which requires a private key and a certification authority) instead of a DER encoded certificate to authenticate itself to the server. But how to use my signed certificate, which is in DER format in `didReceiveAuthenticationChallenge for further requests? There is also an Android application that uses the same process for mutual authorization and does not need a PKCS12 certificate.
I would be glad to some hints. thanks.
source share