J'utilise SecItemCopyMatching
pour accéder au trousseau iOS. Environ une fois sur cent, je reçois un -34018
code de résultat juste après avoir relancé l'application depuis l'arrière-plan. La documentation déclare:
L'espace d'erreur attribué aux services de trousseau est discontinu: –25240 à –25279 et –25290 à –25329. Keychain Item Services peut également renvoyer des codes de résultat noErr (0) ou paramErr (–50) ou CSSM
Il semble donc que -34018
est un "code de résultat CSSM". J'ai suivi le lien suggéré mais je n'ai pas pu trouver les codes de résultat.
Qu'est-ce que le -34018
code de résultat? Comment puis-je obtenir un accès au trousseau plus fiable?
- (NSData *)getKeychainData:(NSString *)key
{
NSDictionary *query = @{
(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService:SEC_ATTR_SERVICE,
(__bridge id)kSecAttrAccount:key,
(__bridge id)kSecReturnData:@YES
};
CFDataRef result = nil;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
if(status == errSecItemNotFound) {
return nil;
}
if(status == noErr) {
return CFBridgingRelease(result);
} else {
[self logError:[NSString stringWithFormat:@"SecItemCopyMatching status %d", (int)status] :nil];
return nil;
}
}
Je fais juste des recherches sur la même erreur.
L'essentiel est que le service de sécurité Apple utilise pour communiquer avec le porte-clés, dans de rares cas, lorsque l'appareil de l'utilisateur manque de mémoire, se bloque et enlève la capacité de l'application à parler au porte-clés qui se traduit par le terrible -34018.
Cela ne se produit pas uniquement lors de l'exécution de Xcode, comme certains le prétendent.
Il s'agit des données les plus récentes concernant le problème tirées des forums de développeurs Apple par l'un des collaborateurs de Apple:
MISE À JOUR: Nous avons enfin pu reproduire l'erreur -34018 sur iOS 8.3. Il s'agit de la première étape pour identifier la cause première, puis trouver un correctif.
Comme d'habitude, nous ne pouvons pas nous engager sur un calendrier de sortie, mais cela a affecté de nombreux développeurs et nous voulons vraiment que cela soit résolu.
Plus tôt, j'ai suggéré d'ajouter un petit retard dans l'application: didFinishLaunchingWithOptions et applicationDidBecomeActive: avant d'accéder au trousseau comme solution de contournement. Cependant, cela ne semble pas vraiment aider. Cela signifie qu'il n'y a aucune solution de contournement connue à ce moment autre que la relance de l'application.
Le problème semble être lié à la pression de la mémoire, donc peut-être être plus agressif dans la gestion des avertissements de mémoire peut atténuer le problème.
D'un autre membre du personnel Apple:
- L'ingénierie des porte-clés est bien consciente de l'importance de ce problème.
- Le problème principal a été de reproduire l'échec ici chez Apple.
- Nous sommes maintenant en mesure de le faire (en grande partie grâce au travail que vous avez fait pour classer et suivre vos rapports de bogues).
D'un autre membre du personnel Apple le 22 mars 2016 :
OK, voici la dernière. Il s'agit d'un problème complexe avec plusieurs causes possibles: certaines instances du problème sont causées par une signature d'application incorrecte. Vous pouvez facilement distinguer ce cas car le problème est 100% reproductible. Certaines instances du problème sont causées par un bogue dans la façon dont iOS prend en charge le développement d'applications (r. 23 991 853). Le débogage a été compliqué par le fait qu'un autre bogue dans le système d'exploitation (r. 23 770 418) a masqué son effet, ce qui signifie que le problème n'a surgi que lorsque l'appareil était sous pression de mémoire. Nous pensons que ces problèmes ont été résolus dans iOS 9.3. Nous soupçonnons qu'il peut y avoir encore plus de causes de ce problème. Donc, si vous voyez ce problème sur une machine utilisateur (qui n'a pas été discutée par Xcode) qui exécute iOS 9.3 ou version ultérieure, veuillez déposer un rapport de bogue à ce sujet. Essayez d'inclure le journal système de l'appareil dans votre rapport de bogue (je me rends compte que cela peut être délicat lorsque vous traitez avec des appareils clients; une option consiste à demander au client d'installer Apple Configurateur, qui lui permet de visualiser le journal système) . Et si vous signalez un bogue, veuillez publier votre numéro de bogue, juste pour mémoire. Au nom de Apple Je tiens à remercier tout le monde pour les efforts qu'il a déployés pour aider à retrouver ce problème plutôt horrible. Partagez et profitez
Malheureusement, il n'existe aucune solution de contournement connue et le problème n'est toujours pas résolu dans 9.3.2 Beta 1 (13F51a)
Après quelques recherches, j'ai trouvé ceci: http://opensource.Apple.com/source/Security/Security-55471/sec/Security/SecBasePriv.h
Alors -34018
est errSecMissingEntitlement
et le commentaire dit
Internal error when a required entitlement isn't present.
Vous rencontrez cette erreur lors de l'exécution de vos tests unitaires? Si oui, cela pourrait aider: https://stackoverflow.com/a/22305193/1719
Ce problème sur github indique qu'il ne semble se produire que lors du débogage à partir de Xcode: https://github.com/soffes/sskeychain/issues/97 (voir également https: // stackoverflow .com/a/28256591/1719 )
J'espère que cela vous aidera!
Ce code fonctionne pour moi:
static const UInt8 kKeychainItemIdentifier[] = "com.Apple.dts.KeychainUI\0";
- (NSData *)getKeychainData:(NSString *)key
{
NSData *keychainItemID = [NSData dataWithBytes:kKeychainItemIdentifier length:strlen((const char *)kKeychainItemIdentifier)];
NSDictionary *query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: SEC_ATTR_SERVICE,
(__bridge id)kSecAttrAccount: key,
(__bridge id)kSecReturnData: (__bridge id)kCFBooleanTrue,
(__bridge id)kSecAttrGeneric: keychainItemID
};
CFDataRef result = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
if(status == errSecItemNotFound) {
return nil;
}
if(status == noErr) {
return CFBridgingRelease(result);
} else {
[self logError:[NSString stringWithFormat:@"SecItemCopyMatching status %d", (int)status] :nil];
return nil;
}
}
La principale différence avec le code OP est l'ajout d'un attribut générique à la requête. L'identifiant d'élément de trousseau est la valeur par défaut d'Apple. La raison derrière cela vient de différencier les différents éléments de porte-clés possibles les uns des autres. C'est une façon de rendre plus fiable l'accès aux éléments du trousseau. En gros, en d'autres termes, cela garantit que vous accédez au trousseau par défaut d'Apple.