2

我目前正在使用 SocketRocket 作为我的 iOS 应用程序的 WebSocket 实现,并希望使用 SR_SSLPinnedCertificates 属性将我的服务器的 CA 固定为受信任的证书。我正在寻找一个加载一个或多个证书以传递到 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);
}
4

2 回答 2

5

使用 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];
于 2014-08-30T01:28:13.220 回答
1

对于 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!")
}
于 2016-08-01T21:39:03.507 回答