16

私は、2 人のユーザー間のモバイル決済を容易にする iOS5 アプリケーションに取り組んでいます。支払いプロセスの一環として、送信者と受信者はサーバーと通信する必要があります。サーバーは、接続時に認証チャレンジが開始されたときに、両方の当事者が ID を提示することを要求します。

現在、コードで次の 2 つの方法を利用して、証明書プロセスをハードコーディングしています。

NSURLConnection デリゲートdidReceiveAuthenticationChallenge

(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:    (NSURLAuthenticationChallenge *)challenge
{
NSLog(@"Authentication challenge");

// Load Certificate
NSString *path = [[NSBundle mainBundle] pathForResource:@"PKCS12" ofType:@"p12"];
NSData *p12data = [NSData dataWithContentsOfFile:path];
CFDataRef inP12data = (__bridge CFDataRef)p12data;

SecIdentityRef myIdentity;
SecTrustRef myTrust;
extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);

SecCertificateRef myCertificate;
SecIdentityCopyCertificate(myIdentity, &myCertificate);
const void *certs[] = { myCertificate };
CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);

NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistencePermanent];

[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}

C メソッドの extractIdentityAndTrust

OSStatus extractIdentityAndTrust(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust)
{
OSStatus securityError = errSecSuccess;

CFStringRef password = CFSTR("password");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };

CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);

CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
securityError = SecPKCS12Import(inP12data, options, &items);

if (securityError == 0) {
    CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
    const void *tempIdentity = NULL;
    tempIdentity = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
    *identity = (SecIdentityRef)tempIdentity;
    const void *tempTrust = NULL;
    tempTrust = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
    *trust = (SecTrustRef)tempTrust;
}

if (options) {
    CFRelease(options);
}

return securityError;
}

このコードを何度もテストし、成功しました。今、私は先に進み、適切な ID を保存して、アプリのキーチェーンから取得できるようにしようとしています。私の目的は、ユーザーが P12 ファイルを iTunes ファイル共有または Dropbox 経由でインポートしてキーチェーンに保存できるようにすることです。

永続的なキーチェーン参照の取得と使用に関する Apple のドキュメントを調べましたが、ID をインポートする方法がわかりませんでした。彼らのコードは、宣言されていない変数/参照 (具体的には

&persistent_ref

変数)。誰かがそれを解読するのを助けることができれば、それは大歓迎です.

TL;DR: P12 ファイルの内容を iOS5 アプリのキーチェーンに保存し、後で取得して NSURLConnection didReceiveAuthenticationChallenge メソッドに渡すにはどうすればよいですか?

4

2 に答える 2

7

次のコードでうまくいくはずです:

NSMutableDictionary *secIdentityParams = [[NSMutableDictionary alloc] init];
[secIdentityParams setObject:(id)myIdentity forKey:(id)kSecValueRef];
OSStatus status = SecItemAdd((CFDictionaryRef) secIdentityParams, NULL);

検索または作成するキーと値のペアのディクショナリを渡すことにより、キーチェーンを操作します。各キーは、検索オプションまたはキーチェーン内のアイテムの属性を表します。キーは事前定義された定数であり、保存するデータのタイプに応じて使用する必要があります。これらのキーは、Appleの開発者向けドキュメントに記載されています。

Appleのソースコードには確かにpersistentRefの割り当てが欠けていると思います。メソッドの先頭にそのような宣言を追加する必要があります。

NSData *persistentRef = nil; 

永続参照の使用は必須ではないことに注意してください。上記のコードは問題なく動作するはずです。Appleがよく説明しているように:

プログラムの呼び出し間で永続的な参照が有効であり、ディスクに保存できるため、永続的な参照を使用して、繰り返し必要になるキーチェーンアイテムを簡単に見つけることができます。

ソースhttps ://developer.apple.com/library/ios/#documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html#//apple_ref/doc/uid/TP40001358-CH208-DontLinkElementID_10

于 2012-10-10T08:14:47.117 に答える