ver llavero guardar guardadas descargar cómo cuentas correo contraseñas contraseña como app acceder iphone ios4 keychain

llavero - ver contraseña de correo en iphone



Error al guardar en el llavero con iphone sdk (7)

El llavero es un dolor total. En su lugar, debe usar la biblioteca STUtils de Buzz Andersen como un contenedor. Hará su vida sustancialmente más fácil. Nunca he tenido un problema con eso.

Uso el wraper de Apple para el llavero e intento guardar un ítem en él (corriendo en el simulador, ios 4.1).

No tengo experiencia con el llavero antes.

Me sale este error:

No se pudo agregar el elemento de llavero. Error - 25299

En KeychainItemWrapper.m línea 304:

// No previous item found; add the new one. result = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL); NSAssert( result == noErr, @"Couldn''t add the Keychain Item." );

Así es como salgo:

- (void) saveKey:(NSString *)key value:(NSString *)value { KeychainItemWrapper *keyItem = [[KeychainItemWrapper alloc] initWithIdentifier:key accessGroup:nil]; [keyItem setObject:value forKey:(id)kSecValueData]; [keyItem release]; }

Y estos son los valores que la API intenta guardar:

<CFBasicHash 0x7231f60 [0x320d380]>{type = mutable dict, count = 5, entries => 2 : <CFString 0x2e6eb98 [0x320d380]>{contents = "labl"} = <CFString 0x2fb018 [0x320d380]>{contents = ""} 3 : <CFString 0x2e6efb8 [0x320d380]>{contents = "v_Data"} = <CFString 0x727de60 [0x320d380]>{contents = "dit8"} 4 : <CFString 0x2e6ebc8 [0x320d380]>{contents = "acct"} = <CFString 0x2fb018 [0x320d380]>{contents = ""} 5 : <CFString 0x2e6eb58 [0x320d380]>{contents = "desc"} = <CFString 0x2fb018 [0x320d380]>{contents = ""} 6 : <CFString 0x2e6ebe8 [0x320d380]>{contents = "gena"} = <CFString 0x2ffd08 [0x320d380]>{contents = "userCode"} }


De acuerdo con la documentación , el error -25299 que está recibiendo es "errSecDuplicateItem", lo que significa que el elemento que está tratando de agregar ya existe. Mirando el código vinculado para KeychainItemWrapper, supongo que la llamada SecItemCopyMatching está fallando con un error que no sea errSecItemNotFound (-25300).


Puede almacenar y recuperar fácilmente valores con llavero utilizando SFHFKeychainUtils por Buzz Andersen.

  1. Descargue y copie en su proyecto SFHFKeychainUtils.h y .m
  2. Agregue Security.framework a su carpeta de Framework
  3. Asegúrese de que estos archivos se agreguen a su objetivo
  4. Importar SFHFKeychainUtils.h donde quiera usarlo

Este es un pequeño ejemplo sobre cómo usar esta biblioteca.

// To store data NSError *error = nil; [SFHFKeychainUtils storeUsername:username andPassword:password forServiceName:kStoredData updateExisting:YES error:&error]; // To retrieve data NSString *password = [SFHFKeychainUtils getPasswordForUsername:username andServiceName:kStoredData error:&error]; // To delete data from keychain [SFHFKeychainUtils deleteItemForUsername:username andServiceName:kStoredData error:&error];


Sé que esto es de hace varios meses, pero tuve el mismo problema y fue doloroso, así que pensé en compartirlo. Lo resolví agregando esta línea:

[self.keychainItemWrapper setObject:@"MY_APP_CREDENTIALS" forKey:(id)kSecAttrService]; //@"MY_APP_CREDENTIALS" can be any string.

Encontré esta entrada de blog muy útil: "En términos de la base de datos, podría pensar que es un índice único en los dos atributos kSecAttrAccount, kSecAttrService, que requiere que la combinación de esos dos atributos sea única para cada entrada en el llavero". (desde http://useyourloaf.com/blog/2010/4/28/keychain-duplicate-item-when-adding-password.html ).

Además, en el proyecto de ejemplo de Apple que usa este código, crean una instancia de KeychainItemWrapper en el delegado de la aplicación. No sé si es necesario, pero me gusta seguir sus ejemplos lo más cerca posible:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ //there will be some standard code here. KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MY_APP_CREDENTIALS" accessGroup:nil]; self.keychainWrapper = wrapper; [self.keychainWrapper setObject:@"MYOBJECT" forKey:(id)kSecAttrService]; [wrapper release]; }

Creo que esto es un error en el código del contenedor. La lógica básicamente dice "¿Ya existe esta entrada? No, no. OK, la agregaré. Oops, no puedes agregarla porque ya está allí".

Es posible que también deba configurar kSecAttrAccount; Nunca lo intenté sin establecer también este valor, ya que está destinado a guardar el nombre de usuario que acompaña a la contraseña:

[self.wrapper setObject:txtUserName.text forKey:(id)kSecAttrAccount];


También tuve este problema y lo resolví gracias a la respuesta accepter y al enlace adicional para usar tu pan.

El problema que tenía era interesante, necesitaba guardar solo un valor y decidí guardarlo en el campo kSecValueData . Eso es porque vi otras publicaciones sobre el uso del llavero y comencé mi propia implementación antes de pasar a KeychainItemWrapper. Esto causó el siguiente problema: en el primer dispositivo que estaba probando (iPad 1st gen) recibí un error en writeToKeychain. Cambié el dispositivo (también ipad 1st gen) y funcionó! Volver al primer dispositivo todavía no funcionaba.

Entonces, ese punto supe que previamente había hecho algo mal en el llavero del dispositivo y no pude revertirlo fácilmente. Los códigos de error que obtenía eran: -25300 en SecItemCopyMatching de writeToKeychain (elemento no encontrado) y justo después de -25299 en SecItemAdd. (artículo duplicado)

Con esta pregunta, todo esto tiene sentido: el dispositivo tiene una clave que coincide con cualquier nueva clave, pero KeychainItemWrapper no puede eliminarla, pero la clave no se puede recuperar. Tan pronto como agregué el mismo valor al campo kSecAttrAccount, comenzó a funcionar.

Para resumir, para otros usuarios que tengan este problema, su problema puede parecer diferente, pero preste atención a los detalles. Si tiene -25300 (elemento no encontrado) seguido de -25299 (artículo duplicado); asegúrese de establecer un campo que defina la singularidad de su elemento de llavero. Si no funciona en un dispositivo, pruebe con otro si puede, puede aislar el problema en un dispositivo. Códigos de error de Apple keychain: http://developer.apple.com/library/ios/#documentation/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/uid/TP30000898-CH5g-CJBEABHG (búsqueda de Códigos de resultado)


Para mí, la solución fue crear un KeychainItemWrapper "singleton" y usarlo en toda la aplicación. (En realidad, en mi caso, tenía un diccionario singleton lleno de KeychainItemWrapper -s, porque uso más de uno).

Esto resolvió el problema donde estaba llegando a una ruta de código que decía "¿existe este elemento en el llavero?" Entonces, NSAssert() . ¡Vaya! NSAssert() que estoy tratando de agregar un elemento que ya existe (Error - 25299) "

Aunque no estoy seguro, sospecho que el problema tiene que ver con la sincronización de llavero. He tenido problemas similares con NSUserDefaults , cuando escribo en NSUD, en otro lugar del código, obtengo los standardUserDefaults y leo de ellos, y la actualización aún no se ha realizado (porque aún no lo hice [ud synchronize] , .)

En el código, mi rutina se ve así:

+ (KeychainItemWrapper*) keyChainWrapperForKeyID: (NSString*) keyID { static dispatch_once_t onceToken = 0; static NSMutableDictionary *rfcuKeyChains = nil; dispatch_once(&onceToken, ^{ rfcuKeyChains = [NSMutableDictionary new]; }); KeychainItemWrapper *keychain = nil; @synchronized (rfcuKeyChains) { keychain = [rfcuKeyChains objectForKey: keyID]; if (keychain == nil) { keychain = [[KeychainItemWrapper alloc] initWithIdentifier: keyID accessGroup: nil]; [rfcuKeyChains setObject: keychain forKey: keyID]; } } return keychain; }

Y lo uso así:

KeychainItemWrapper *keychain = [RFCUtils keyChainWrapperForKeyID: keyID]; NSString *firstLaunch = [keychain objectForKey: (__bridge id)(kSecAttrAccount)]; if (firstLaunch == nil) { [keychain setObject: MY_APP_KEY forKey: (__bridge id)(kSecAttrAccount)]; }

(etc., llamadas similares en otros lugares).


Intenté todas las soluciones escuchar arriba, pero nada funcionó para mí. Solo funcionaba en un dispositivo real pero no en el simulador.

Mi solución para ejecutarlo en el simulador fue activar "Compartir el derecho del llavero".

Compartir el derecho de llavero