多くの研究と試行錯誤を経て、今では自分自身で答えることができます。また、お役に立てれば幸いです。
実際、私が必要としているのは、CFStream を使用してクライアント SSL 認証を実装することです。だから私はこれらを行う必要があります:
- PKCS #12 ファイルをアプリ バンドルに入れる
- このファイルを次のように読ん
NSData
でくださいpkcsData
- メソッド
SecPKCS12Import
を使用してインポートするpkcsData
- 上記でインポートしたデータから ID と証明書を取得し、証明書配列を生成します
- 配列をキー入力するように設定
kCFStreamSSLCertificates
しkCFStreamPropertySSLSettings
ますCFWriteStreamRef
以下のサンプルコード:
// Read .p12 file
NSString *path = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
NSData *pkcs12data = [[NSData alloc] initWithContentsOfFile:path];
// Import .p12 data
CFArrayRef keyref = NULL;
OSStatus sanityChesk = SecPKCS12Import((__bridge CFDataRef)pkcs12data,
(__bridge CFDictionaryRef)[NSDictionary
dictionaryWithObject:@"123456"
forKey:(__bridge id)kSecImportExportPassphrase],
&keyref);
if (sanityChesk != noErr) {
NSLog(@"Error while importing pkcs12 [%ld]", sanityChesk);
} else
NSLog(@"Success opening p12 certificate.");
// Identity
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(keyref, 0);
SecIdentityRef identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict,
kSecImportItemIdentity);
// Cert
SecCertificateRef cert = NULL;
OSStatus status = SecIdentityCopyCertificate(identityRef, &cert);
if (status)
NSLog(@"SecIdentityCopyCertificate failed.");
// the certificates array, containing the identity then the root certificate
NSArray *myCerts = [[NSArray alloc] initWithObjects:(__bridge id)identityRef, (__bridge id)cert, nil];
//
[SSLOptions setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredRoots];
[SSLOptions setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates];
[SSLOptions setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
[SSLOptions setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCFStreamSSLValidatesCertificateChain];
[SSLOptions setObject:@"test.domain.com:443" forKey:(NSString *)kCFStreamSSLPeerName];
[SSLOptions setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString*)kCFStreamSSLLevel];
[SSLOptions setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString*)kCFStreamPropertySocketSecurityLevel];
[SSLOptions setObject:myCerts forKey:(NSString *)kCFStreamSSLCertificates];
[SSLOptions setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCFStreamSSLIsServer];
[_outputStream setProperty:SSLOptions
forKey:(__bridge id)kCFStreamPropertySSLSettings];
私は SocketRocket を使用しているため、次のコードを自分のフォークに追加しました: https://github.com/nickcheng/SocketRocket