TLS on iPhone

2010.03.24 17:22 from programming
아이폰 응용프로그램으로부터 서버와 네트워크 통신하는 내용을 암호화 하기 위해 TLS(Transport Layer Security)를 쓰는 방법을 정리합니다. 

HTTPS

HTTP통신의 경우에는 NSURLRequest를 사용할때 https 스킴을 사용하면 자체적으로 HTTPS를 사용하므로, 별다른 설정 없이 보안설정이 가능합니다. 일반 HTTP통신과 동일한 방식으로 NSURLConnection 객체를 활용하여 HTTPS를 사용할 수 있습니다.

서버측에서 비공인 인증서(eg. self-signed certificate)를 경우에는, 아래의 delegate method를 구현해서 처리 가능합니다.

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace;
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;

TLS socket

하지만, HTTP통신이 아닌, 일반 소켓 통신의 경우 얘기가 조금 다릅니다. NSStream 객체로 만들어 소켓통신을 할 수 있습니다만, SSL통신을 하기위한 옵션이 있습니다. NSStream을 만들고 스트림을 open하기 전에 아래의 속성을 설정하고 나서, 스트림을 열면, 열리자 마자 TLS handshaking을 진행합니다. 

[stream setProperty:NSStreamSocketSecurityLevelTLSv1 forKey:NSStreamSocketSecurityLevelKey];

하지만, 이경우에 비공인 인증서는 사용할 수 없습니다. 어떻게 하면 비공인 서버인증서로 TLS통신을 할 수 있을까 조금 더 자료를 찾아본 결과, CoreFoundation쪽을 직접 건드리는 방법이 있었습니다. CFReadStream과 CFWriteStream에 속성을 설정할 수 있는 함수가 있고, 아래의 코드처럼 kCFStreamSSLValidatesCertificateChain속성을 NO로 설정해서, 서버인증서 검증과정을 생략할 수 있습니다.

NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
 [NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
  kCFStreamSocketSecurityLevelTLSv1, kCFStreamSSLLevel,
 nil];
CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);

위의 설정후에 CFReadStream과 CFWriteStream을 각각 NSInputStream과 NSOutputStream으로 바꾸어 사용하면, open후 TLS handshaking이 진행된 채로 데이터를 주고 받을 수 있습니다.

 
Posted by hatemogi 트랙백 0 : 댓글 0

티스토리 툴바