3

アプリのドキュメント フォルダーに、1 つの証明書と 1 つの秘密キーを含む PKCS12 ファイルがあります。Apple のドキュメント (https://developer.apple.com/library/ios/#documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks. html#//apple_ref/doc/uid/TP40001358-CH208-DontLinkElementID_10)

私が今やろうとしているのは、後で使用できるように、この ID をキーチェーンに保存することです。私は iOS キーチェーンに関するさまざまなものを読みましたが、それが実際にどのように機能するかを理解するのに苦労しています。

Apple のコードは、persistent_ref を使用してキーチェーンに格納されている ID を取得しているようです。しかし、これが何なのかよくわかりません...メモリ参照のような単純な参照ですか?その場合、デバイスを再起動するとどうなりますか?

これについてこれ以上多くの情報を見つけることができませんでした kSecAttr 属性を使用して、別の方法で実行しようとしました。現在のコードは、キーチェーンに Identity を追加するために正常に機能します。

NSMutableDictionary * dictionary = [[[NSMutableDictionary alloc] init] autorelease];  

[dictionary setObject:@"LABEL" forKey:kSecAttrLabel];

[dictionary setObject:(id)newIdentity forKey:(id)kSecValueRef];

OSStatus status = SecItemAdd((CFDictionaryRef)dictionary, NULL);

しかし、もう一度追加しようとすると、-25299 エラーが表示されますが、これは既に存在するため「問題ありません」。私はこのような更新でそれを処理しようとしました:

NSMutableDictionary *searchDictionary = [[[NSMutableDictionary alloc] init] autorelease];
[searchDictionary setObject:@"LABEL" forKey:kSecAttrLabel];
[searchDictionary setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
[searchDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef];

NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init];
[updateDictionary setObject:(id)newIdentity forKey:(id)kSecValueRef];

OSStatus status = SecItemUpdate((CFDictionaryRef)searchDictionary,(CFDictionaryRef)updateDictionary);

このコードでは、無効なパラメーターがあるため、明らかに-50ステータスエラーが発生します...どれですか? なんで ?キーチェーンを正しく更新するにはどうすればよいですか?

編集:提案されているように、既存の要素を追加する前に削除しようとしましたが、同じステータス コード (-50) で立ち往生しています。以下は私が試したコードです:

NSMutableDictionary *searchDictionary = [self setupSearchDirectoryForIdentifier:identifier];
OSStatus status = SecItemDelete((CFDictionaryRef)searchDictionary);
NSAssert(status == noErr, @"Problem deleting current keychain item." );

setupSearchDirectoryForIdentifier は、私のアイテムのラベルで NSDictionnary を作成するだけです:

- (NSMutableDictionary *)setupSearchDirectoryForIdentifier:(NSString *)identifier {

    // Setup dictionary to access keychain.
    NSMutableDictionary *searchDictionary = [[[NSMutableDictionary alloc] init] autorelease];  

    [searchDictionary setObject:identifier forKey:kSecAttrLabel];

    return searchDictionary; 
}

ありがとうございました

PS:私はXcode 4.2 / iPad 5.1.1で開発しています

4

2 に答える 2

4

これが古い投稿であっても、(SSL クライアント認証に使用される) キーチェーンの ID を扱うときに最近同様の問題を思いついたので、これのサポートとして (XCode 5.0.1 で) 私自身の経験を提供しています。まだ非常に混乱しているようです。

SecItemAddは、非常に少数のキーで使用する必要があります。kSecValueRef (ID 付き) はもちろん必須で、オプションで kSecAttrLabel です。他のいくつかのキー (kSecClass など) を使用すると、サイレント エラーが発生しました。つまり、エラーは報告されませんでしたが、ID は追加されませんでした。これは非常に混乱しました。

そのような ID でSecItemUpdateを使用することもできませんでした。すべての試行で -50 エラーが発生しました。

既存の ID を更新できるようにするために、SecItemDelete を使用して既存の ID を削除し、SecItemAddで追加しました。ここでも紛らわしいのは、SecItemDelete の呼び出しで -25300 エラーが返されたが (errSecItemNotFound)、後で (SecItemAdd を使用して) エラーなしで ID を追加できたため、ID が実際に削除されたため無視できたことです。

于 2014-01-30T15:14:08.063 に答える
3

SecIdentityRefs、SecKeyRefs および同様のSec...Ref値は、キーチェーン アイテムの一時的な表現です。アプリケーションが終了するか、保持カウントがゼロになると無効になります。永続ストレージに直接保存することはできません。

一方、永続的な参照は、CFDataRef後で特定のキーチェーン アイテムを取得するために使用できる部分です。ファイル、NSUserDefaults、または好きな場所に保存できます。アプリ終了時や端末再起動時には無効になりません。(ただし、キーチェーン自体が削除された場合 (つまり、デバイスが復元された場合)、それが参照する項目が削除された場合、または項目の識別属性の 1 つが変更された場合、永続的な参照は無効になる可能性があります。)

Apple のサンプル コードでは、SecItemAddの 2 番目の引数を使用して、キーチェーンに追加するアイテムへの永続的な参照を取得します。これは、おそらく に保存されNSUserDefaultsます。永続的な参照が与えられると、アプリは後で使用できるSecItemCopyMatchingに変換するためにSecIdentityRef使用できます。

永続的な参照を使用したくない場合は、使用する必要がないことに注意してください。必要に応じて、ラベルやその他の識別属性に基づいてキーチェーン アイテムを取得することもできます。

SecItemUpdateSecIdentityRefaは実際のキーチェーン アイテムではないため、おそらく失敗します。公開鍵とそれに関連付けられた秘密鍵が両方ともキーチェーンにある場合に構築されるのは、疑似アイテムにすぎません。そのため、更新してもあまり意味がありません。属性を所有していません。そのすべてのプロパティは、関連するSecCertificateRef(証明書) およびSecKeyRef(秘密鍵) から継承されます。ID の代わりにこれらの項目を更新するとうまくいくはずです。(ただし、単純にアイテムを正しく作成する方が簡単です。属性とその値を の最初のパラメーターに追加することで、任意の属性を初期化できます。) または、キーチェーンに再度追加する前にSecItemAddID ( ) を削除することもできます。SecItemDelete

于 2012-10-24T00:18:57.680 に答える