iOS 초보

ios. ssl. client certificate. 클라이언트 인증서. pinning

돌비 2016. 10. 21. 14:48

* 인증서 : comodo 에서 결제해서 받았음.
_wildcard_도메인.pfx 파일을 확장자를 .p12로 바꿔서 ios 프로젝트에 포함시킨다.
이 인증서의 비밀번호 알고 있어야 한다.

* iOS 소스. NSURLConnection 이용
#import <CommonCrypto/CommonDigest.h>
#define CERTIFICATE_PASSWORD "인증서비밀번호"

/**
 * https 인증처리
 */
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
  //ALog(@"ssl authenticationMethod = [%@]", challenge.protectionSpace.authenticationMethod);
  //ALog(@"ssl previousFailureCount = [%ld]", challenge.previousFailureCount);
  if(challenge.previousFailureCount > 0)
  {
    [[challenge sender] cancelAuthenticationChallenge:challenge];
    return;
  }

  // 1. client certificate
  if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate])
  {
    NSString* p12Path = [[NSBundle mainBundle] pathForResource:@"인증서파일명" ofType:@".p12"];
    NSData* p12Data = [NSData dataWithContentsOfFile:p12Path];

    CFStringRef password = CFSTR(CERTIFICATE_PASSWORD);
    const void* keys[] = { kSecImportExportPassphrase };
    const void* values[] = { password };
    CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    CFArrayRef p12Items;
    OSStatus result = SecPKCS12Import((CFDataRef)p12Data, optionsDictionary, &p12Items);

    if(result != noErr)
    {
      [[challenge sender] cancelAuthenticationChallenge:challenge];
      return;
    }

    CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items, 0);
    SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);

    SecCertificateRef certRef;
    SecIdentityCopyCertificate(identityApp, &certRef);

    SecCertificateRef certArray[1] = { certRef };
    CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);

    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp certificates:(__bridge NSArray*)myCerts persistence:NSURLCredentialPersistencePermanent];
    [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];

    CFRelease(certRef);
    CFRelease(myCerts);
    return;
  }

  // 2. server trust
  if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
  {
    SecTrustResultType result;
    SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
    SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result);
    [challenge.sender useCredential:[NSURLCredential credentialForTrust:serverTrust] forAuthenticationChallenge:challenge];
    return;
  }
}

나머지는 일반적인 통신처리와 동일함


반응형