2012-03-26 6 views
6

私は、Webアプリケーションと外部サーバーとの間のプロキシとして機能するために、のHTTPSサーバーをiOSアプリケーション内に構築しようとしています。iOS上でHTTPSサーバーを実行するためのSSL ID証明書

私はCFSocketRefのおかげで、あるいはGCDAsyncSocketライブラリを使ってソケットを聞いてHTTPサーバを作ることができました。私はまた、GCDAsyncSocketライブラリと私の方法のおかげで使用して、HTTPSサーバを実行しているMacのアプリを作るために成功してきた 「にSecureSocketを:」接続を確保し、それ以下:

- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket 
{ 
    // (...) 
    // secure the connection 
    [self secureSocket:newSocket]; 
    // (...) 
} 

- (void)secureSocket:(GCDAsyncSocket *)sock 
{ 
    // The root self-signed certificate I have created 
    NSString *certificatePath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"cer"]; 
    NSData *certData = [[NSData alloc] initWithContentsOfFile:certificatePath]; 
    CFDataRef certDataRef = (CFDataRef)certData; 
    SecCertificateRef cert = SecCertificateCreateWithData(NULL, certDataRef); 
    [certData release]; 

    // the "identity" certificate 
    SecIdentityRef identityRef; 
    SecIdentityCreateWithCertificate(NULL, cert, &identityRef); 

    // the certificates array, containing the identity then the root certificate 
    NSArray *certs = [[NSArray alloc] initWithObjects:(id)identityRef, (id)cert, nil]; 

    // the SSL configuration 
    NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:3]; 
    [settings setObject:[NSNull null] forKey:(NSString *)kCFStreamSSLPeerName]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredRoots]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates]; 
    [settings setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCFStreamSSLValidatesCertificateChain]; 
    [settings setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString*)kCFStreamSSLLevel]; 
    [settings setObject:certs forKey:(NSString *)kCFStreamSSLCertificates]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLIsServer]; 

    [sock startTLS:settings]; 
    [certs release]; 
} 

私が使用している証明書が自己であります署名付きサーバーSSL証明書私はKeychain Accessで作成しました。 IDと証明書を含む配列が設定されているシステムを設定する必要があることを理解しています。それは私のMacアプリでうまく動作します。

問題は、iOSアプリケーションのHTTPサーバーでSSLを有効にすることです。 アイデンティティを作成するメソッド「SecIdentityCreateWithCertificate()」はiOSには存在しません。アイデンティティを作成する方法は別の方法ではわかりません。

iOSでSecIdentityRefを作成する方法(SSLサーバー側を有効にする方法)は私のアプリに公開鍵/秘密鍵を保存するのが好きなのですか?どうもありがとうございます。

+0

これはCocoaAsyncSocket v7.4で変更されました。一部の古いオプションキーは使用できなくなり、例外がスローされます。 GCDAsyncSocketManuallyEvaluateTrustを使用し、-socket:didReceiveTrust:delegateで評価してください。私の例をhttps://gist.github.com/hlung/6432966 – Hlung

答えて

4

コメントはコード共有には適していないため、私は別の回答を投稿します。

CFArrayRef keyref = NULL; 
OSStatus sanityChesk = SecPKCS12Import((__bridge CFDataRef)p12Data, 
             (__bridge CFDictionaryRef)[NSDictionary 
                    dictionaryWithObject:password 
                    forKey:(__bridge id)kSecImportExportPassphrase], 
             &keyref); 

if (sanityChesk != noErr) { 
    NSLog(@"Error while importing pkcs12 [%d]", sanityChesk); 
    return nil; 
} 

NSArray *keystore = (__bridge_transfer NSArray *)keyref; 

完全P12コンテンツがストア配列になります。ここでは
は、私は私のPKCS12をインポートするために使用するものです。

+0

ここで私のコードはARCを使用しているため、暗黙の__bridgeキーワードが必要です;) – pmilosev

+0

私は同じことをしていました。あなたのコードで同じ結果が得られます:_keystore_配列が空です。 同じコードでより良い結果が得られたら、証明書を生成したり保存したりすることはできないと思いますか?私がしたことは、Keychain Accessから自己署名付きルート証明書を作成してから、プロジェクトバンドルに.cerファイルと.p12ファイルの両方を保存することです。わかりやすくそれらを使用しようとします。あなたの時間をありがとう、私はあなたの助けに感謝します。 – Laurent

+0

ちょうどそれを動作させるには...あなたのキー/証明書のペア(例えば、アップル社が署名した開発証明書)の一部をエクスポートしようとするとどうですか? – pmilosev

0

PKCS#12ファイルを使用してIDをインポートする必要があるようです。リスト2-2をhttps://developer.apple.com/library/ios/#documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html#//apple_ref/doc/uid/TP40001358-CH208-SW13に記載してください。

+0

で見てきましたが、私はそれを実際に試しましたが、動作させることはできません。正しい質問かもしれません。私は自分のプライベートキー(p12ファイル)をインポートし、Appleのリンクに示すようにextractIdentityAndTrust()関数を使用しましたが、配列の最初の要素にアクセスしようとしているときにこの関数をクラッシュさせる空の_items_配列を常に取得します。それについてのアイデア? – Laurent

+0

'SecPKCS12Import'メソッドを使用した場合、NSDictionaryを含むNSArrayが返されます。辞書のIDはキー 'kSecImportItemIdentity'の下に格納され、証明書チェーン(NSArrayは再び)が 'kSecImportItemCertChain'キーの下に格納されます。その間、私は事前ロードされた証明書を扱っていないので、実行時にIDを作成する方法も探しています。私が何かを見つけたらここに結果を掲載します;) – pmilosev

+0

ありがとう@pmilosev。私の問題は、上記のリンクでAppleが示したように_extractIdentityAndTrust_関数を使用していますが、得られる配列_items_は常に空です: 'NSDictionary dictionaryWithObject:@" myPrivateKeyPassword "forKey:(id)kSecImportExportPassphrase; CFArrayRef items = CFArrayCreate(NULL、0、0、NULL); securityError = SecPKCS12Import(inPKCS12Data、 optionsDictionary、 &items); ' – Laurent

関連する問題