secItemCopyMatching renvoie des données nulles

Tout d'abord, j'ai regardé la session de la WWDC 2013 sur la protection des secrets avec le trousseau. Je veux faire un magasin de mot de passe de base. J'ai regardé toute la video, mais j'ai trouvé ce dont j'avais besoin dans les 10 premières minutes de la video. Cela semble simple, mais je ne comprends pas complètement le fonctionnement de l'enencoding et de la récupération des données.

PROBLEME: après secItemCopyMatching, je vérifie mon object NSData pour m'assurer qu'il n'est pas nul avant de le convertir en NSSsortingng. Le problème est, il est toujours nul. Voici comment je sauvegarde l'input ou la mise à jour du trousseau, puis comment je la récupère. Toute aide et explication serait très appréciée.

MISE À JOUR (EDITED): Fruité Geek, merci pour la réponse. J'ai mis à jour mon code ci-dessous en utilisant __bridge. Mon problème se résume maintenant à, est-ce que je stocke et récupère le mot de passe correctement? Ai-je tort ou juste l'un ou l'autre? Mon instance NSData est toujours nulle. Je vérifie les codes de return et mes SecItemAdd et SecItemUpdate (quand l'input de keychaing existe) fonctionnent correctement. Je ne peux pas sembler récupérer la valeur de string des données (mot de passe) stockées pour la comparer avec le code entré par l'user. Appréciez l'aide des gars et des filles. Voici ce que je fais maintenant:

UPDATE # 2: (Édité avec les réponses de Fruity Geek et la version de travail finale Mes modifications incluent seulement les changements au code ci-dessous.)

Définir l'input du trousseau:

NSData *secret = [_backupPassword dataUsingEncoding:NSUTF8SsortingngEncoding]; NSDictionary *query = @{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: twServiceName, (__bridge id)kSecAttrAccount: twAccountName, (__bridge id)kSecValueData: secret, }; OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); if (status == errSecDuplicateItem) { // this item exists in the keychain already, update it query = @{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: twServiceName, (__bridge id)kSecAttrAccount: twAccountName, }; NSDictionary *changes = @{ (__bridge id)kSecValueData: secret, }; status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)changes); } 

Récupérer le mot de passe du trousseau:

 NSDictionary *query = @{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: twServiceName, (__bridge id)kSecAttrAccount: twAccountName, (__bridge id)kSecReturnData: @YES, }; NSData *data = NULL; CFTypeRef dataTypeRef = (__bridge CFTypeRef)data; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataTypeRef); NSData *data = (__bridge NSData *)dataTypeRef; NSSsortingng *passcode = @"none"; if (status == errSecSuccess) { // we found a keychain entry, set the passcode if (data) passcode = [NSSsortingng ssortingngWithUTF8Ssortingng:[data bytes]]; } 

twServiceName et twAccountName sont des strings NSS statiques.

Comme je l'ai dit, je ne fais pas tout ce que je fais avec __bridge ou CFTypeRef. J'ai regardé à travers des docs de pommes, de nombreux messages ici et d'autres sites, mais le trousseau de keys et ces termes sont tout nouveaux pour moi et j'essaie toujours de le comprendre. En espérant que quelqu'un ici puisse signaler mon erreur et m'aider à comprendre. Merci d'avance pour l'aide.

iOS 7 / Xcode 5

Vous ne possédez aucun des objects Foundation de base (vous ne les avez pas créés ou CFBridgingRelease ) et vous ne souhaitez pas les conserver ou les libérer. CFBridgingRelease et CFBridgingRetain sont donc incorrects. Utilisez (__bridge id) place lorsque vous souhaitez (__bridge id) un object Objective-C.

 (__bridge id)kSecAttrService 

Quand devriez-vous utiliser __bridge vs CFBridgingRelease / CFBridgingRetain?

Votre variable de données et dataTypeRef sont deux pointeurs distincts. Seul le paramètre dataTypeRef a été rempli avec des données dans SecItemCopyMatching. Transformez votre CFTypeRef en NSData après qu'il a été rempli par SecItemCopyMatching pour que vos données ne soient pas toujours nulles

 CFTypeRef dataTypeRef = NULL; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataTypeRef); NSData *data = (__bridge NSData *)dataTypeRef; 

Vous devriez regarder de plus près le OSStatus returnné par tous vos appels de fonctions SecItem. Il existe de nombreux codes de return possibles qui ne sont pas couronnés de succès. Dans votre cas, vous êtes en train de détecter un élément dupliqué dans SecItemAdd – puis de le mettre à jour avec le même élément (sans rien faire). Au lieu de cela, vous devriez essayer de le récupérer en utilisant SecItemCopyMatching. Si aucune correspondance n'est trouvée, utilisez SecItemAdd. Si une correspondance a été trouvée, utilisez SecItemUpdate.

L'exemple de code d'Apple est terrible , pas écrit pour ARC et confus, mais il existe. En particulier, la méthode writeToKeychain est ce dont vous avez besoin. https://developer.apple.com/library/ios/documentation/Security/Conceptual/keychainServConcepts/iPhoneTasks/iPhoneTasks.html#//apple_ref/doc/uid/TP30000897-CH208-SW1