SocketRocket和iOS证书固定

我目前使用SocketRocket作为我的iOS应用程序的WebSocket实现,并希望将我的服务器的CA作为具有SR_SSLPinnedCertificates属性的可信证书进行绑定。 我正在寻找加载一个或多个证书传递到SocketRocket的一个很好的例子。 我有下面的代码工作,但我不知道这是正确的,或者如果有一个更直接的方法。

CFArrayRef keyref = NULL; NSString *path = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"p12"]; NSData *data = [[NSData alloc] initWithContentsOfFile:path]; OSStatus status = SecPKCS12Import((__bridge CFDataRef)data, (__bridge CFDictionaryRef)[NSDictionary dictionaryWithObject:@"eftl_key_pass" forKey:(__bridge id)kSecImportExportPassphrase], &keyref); if (status == noErr) { CFDictionaryRef identityDict = CFArrayGetValueAtIndex(keyref, 0); SecIdentityRef identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity); SecCertificateRef certRef = NULL; SecIdentityCopyCertificate(identityRef, &certRef); } 

使用SocketRocket的证书是这样完成的:

首先,我们需要从NSURLRequest而不是从NSURL初始化SocketRocket。

 NSURL *url = [[NSURL alloc] initWithString:@"wss://path-to-socket:1234"]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; 

然后,我们设置证书。 证书必须采用二进制DER格式,而不是base64编码的PEM。 证书文件应该在你的主包中。

 NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"myOwnCertificate" ofType:@"cer"]; NSData *certData = [[NSData alloc] initWithContentsOfFile:cerPath]; CFDataRef certDataRef = (__bridge CFDataRef)certData; SecCertificateRef certRef = SecCertificateCreateWithData(NULL, certDataRef); id certificate = (__bridge id)certRef; 

然后,我们将请求的固定证书设置为一个包含我们之前设置的证书的数组。

 [request setSR_SSLPinnedCertificates:@[certificate]]; 

现在我们可以完成套接字。

 SRWebSocket *socket = [[SRWebSocket alloc] initWithURLRequest:request]; [socket open]; 

对于Swift中的代码:

 if let pinnedCertificatePath = NSBundle.mainBundle().pathForResource("subdomain.yourwebsite.com", ofType: "der"), let pinnedCertificateData = NSData(contentsOfFile: pinnedCertificatePath), let cert = SecCertificateCreateWithData(nil, pinnedCertificateData) { request.SR_SSLPinnedCertificates = [cert] // make the websocket call! let ws = SRWebSocket(URLRequest: request) // configure the websocket ws.open() } else { NSLog("Failed to open websocket, could not find pinned certificate!") }