SecItemAdd y SecItemCopyMatching devuelve el código de error -34018 (errSecMissingEntitlement)

A veces, cuando ejecuto una aplicación en un dispositivo de Xcode, bash acceder al llavero pero falla debido al error -34018. Esto no coincide con ninguno de los códigos de error de llavero documentados y no se puede reproducir de manera consistente. (sucede tal vez el 30% del tiempo, y no me queda claro por qué sucede). Lo que hace que la depuración de este problema sea muy difícil es la falta total de documentación. ¿Alguna idea de lo que causa esto y cómo solucionarlo? Estoy usando Xcode 5 y estoy ejecutando iOS 7.0.4 en el dispositivo.

Hay un problema abierto sobre esto aquí: https://github.com/soffes/sskeychain/issues/52

EDITAR: Agregar código de acceso de llavero por solicitud

Estoy usando la biblioteca SSKeychain para interactuar con llavero. Aquí está el fragmento.

 #define SERVICE @"default" @implementation SSKeychain (EXT) + (void)setValue:(NSString *)value forKey:(NSString *)key { NSError *error = nil; BOOL success = NO; if (value) { success = [self setPassword:value forService:SERVICE account:key error:&error]; } else { success = [self deletePasswordForService:SERVICE account:key error:&error]; } NSAssert(success, @"Unable to set keychain value %@ for key %@ error %@", value, key, error); if (!success) { LogError(@"Unable to set value to keychain %@", error); } LogTrace(@"Will set keychain account %@. is to nil? %d", key, value == nil); if (value == nil) LogWarn(@"Setting keychain %@ to nil!!!", key); } + (NSString *)valueForKey:(NSString *)key { NSError *error = nil; NSString *value = [self passwordForService:SERVICE account:key error:&error]; if (error && error.code != errSecItemNotFound) { NSAssert(!error, @"Unable to retrieve keychain value for key %@ error %@", key, error); LogError(@"Unable to retrieve keychain value for key %@ error %@", key, error); } return value; } + (BOOL)removeAllValues { LogInfo(@"Completely Reseting Keychain"); return [[self accountsForService:SERVICE] all:^BOOL(NSDictionary *accountInfo) { return [self deletePasswordForService:SERVICE account:accountInfo[@"acct"]]; }]; } @end 

La gran mayoría de las veces está bien. A veces voy a golpear las fallas de aserción donde no puedo ni escribir ni leer desde el llavero, lo que provoca una falla de aserción crítica.

iOS 10 / XCode 8 Fix:

Agregar derechos de KeyChain, ir a la configuración del proyecto-> Capabilities-> Compartir llaves-> Agregar grupos de llaveros + Activar

Una respuesta aquí, de Apple:

ACTUALIZACIÓN: finalmente hemos podido reproducir el error -34018 en iOS 8.3. Este es el primer paso para identificar la causa raíz y luego encontrar una solución.

Como de costumbre, no podemos comprometernos con un plazo de lanzamiento, pero esto ha afectado a muchos desarrolladores y realmente queremos resolverlo.

Anteriormente, sugerí agregar un pequeño retraso en la aplicación: didFinishLaunchingWithOptions y applicationDidBecomeActive: antes de acceder al llavero como solución alternativa. Sin embargo, eso en realidad no parece ayudar. Eso significa que no hay solución conocida en este momento aparte de relanzar la aplicación.

El problema parece estar relacionado con la presión de la memoria, por lo que quizás ser más agresivo en el manejo de las advertencias de memoria puede aliviar el problema

https://forums.developer.apple.com/thread/4743#14441

ACTUALIZAR

OK, aquí está lo último.
Este es un problema complejo con múltiples causas posibles:

  • Algunas instancias del problema son causadas por la firma incorrecta de la aplicación. Puede distinguir fácilmente este caso porque el problema es 100% reproducible.
  • Algunas instancias del problema son causadas por un error en la forma en que iOS admite el desarrollo de aplicaciones (r 23.991.853). Depurar esto se complicó por el hecho de que otro error en el sistema operativo (r 23,770,418) enmascaró su efecto, lo que significa que el problema solo surgió cuando el dispositivo estaba bajo presión de memoria. Creemos que estos problemas se resolvieron en iOS 9.3.
  • Sospechamos que aún puede haber más causas de este problema.

Entonces, si ve este problema en un dispositivo de usuario (uno con el que Xcode no ha hablado) que ejecuta iOS 9.3 o posterior, presente un informe de error al respecto. Intente incluir el registro del sistema del dispositivo en su informe de errores (me doy cuenta de que puede ser complicado cuando se trata de dispositivos del cliente, una opción es pedirle al cliente que instale Apple Configurator, que les permite ver el registro del sistema). Y si archivas un error, publica tu número de error, solo para el registro.

En nombre de Apple, me gustaría agradecer a todos por sus esfuerzos para ayudar a rastrear este problema bastante horrible. Comparte y Disfruta

https://forums.developer.apple.com/thread/4743#126088

Básicamente debe codirigir su carpeta .xcttest agregando lo siguiente como script de ejecución en su objective de prueba.

 codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH" 

Obtuve muchos errores -34018 al probar mi llavero en el dispositivo y esto logró solucionarlo.

Si el problema no existe en su objective de prueba, probablemente esta no sea la solución.

Estoy observando un comportamiento similar después de comstackr y ejecutar mi código en Xcode 6 beta con iOS 8 SDK (funciona correctamente con Xcode 5 / iOS 7). En Xcode 6, en iOS Simulator SecItemCopyMatching siempre devuelve -34018. Comenzó a funcionar después de activar el “Compartir Llaves” en la pestaña Capacidades.

Sin embargo, tengo otro problema. Estoy desarrollando una biblioteca estática, que es utilizada por (entre otros) la aplicación de demostración. La solución anterior funciona para el proyecto de aplicación de demostración, pero cuando bash probar la unidad de mi proyecto de biblioteca estática, tengo exactamente el mismo error. Y el problema es que mi proyecto de biblioteca estática no tiene la pestaña Capacidades (ya que no es la aplicación independiente).

He intentado con la solución publicada aquí por JorgeDeCorte, con la designación de código en el objective de la prueba, pero no funciona para mí.

Después de inspeccionar el código fuente . Me di cuenta de que se puede acceder a las funciones de llavero a través de un daemon de seguridad que se ejecuta en su propio proceso (separado del proceso de la aplicación).

Su aplicación y el proceso securityd ‘hablan’ juntos a través de una tecnología llamada XPC .

Si es necesario, el securityd se inicia mediante el conocido comando launchd de XPC. Probablemente pueda verificar que el daemon se esté ejecutando en la aplicación Monitor de actividades (si se ejecuta en el simulador, por supuesto) y que se haya iniciado su proceso principal.

Supongo que es posible que, por alguna razón desconocida, el daemon de seguridad no se inicie o lo haga demasiado lento y no esté listo cuando intentes usarlo.

Tal vez podrías pensar en prelanzar el daemon.

Me disculpo por no ser más preciso. Espero que pueda ayudarte a dar un paso más en tus investigaciones.

Intente deshabilitar todos los puntos de interrupción al iniciar la aplicación desde Xcode. Puedes habilitarlos luego.

(Ninguna de las soluciones anteriores funcionó para mí)

Acabo de tener el mismo problema en el simulador que ejecuta 7.1 y 8.0. Mientras hacía algunas excavaciones, noté que la aplicación de ejemplo de Apple tenía KeyChain Sharing activada para sus capacidades de destino. Lo prendí para mi aplicación, lo que resultó en la creación de un archivo de derechos que dejé con los valores predeterminados y ahora ya no recibo los errores -34018. Esto no es ideal, pero viviré la opción de compartir KeyChain por ahora.

Me picaron también esto y no tuvieron éxito con ninguna de las otras soluciones. Luego, limpié mis perfiles de provisión en los dispositivos en sí, borrando todos los relacionados con mi aplicación, así como todos los perfiles comodín (este parece ser el punto). Para hacer esto, vaya a la ventana “Dispositivos” en Xcode y haga clic derecho en su teléfono (conectado):

Haga clic en “Mostrar perfiles de provisión” y elimine los relacionados, y especialmente los perfiles de equipo:

incluidos los que tienen el asterisco. Después de la reinstalación de la aplicación, todo volvió a la normalidad.

He solucionado este problema (creo). Tenía un perfil de aprovisionamiento de comodines en mi dispositivo que mostraba que no tenía una identidad de firma válida. También tenía un perfil de aprovisionamiento para mi aplicación que era válido. Cuando eliminé el perfil de comodín, dejé de recibir los errores -34018.

También me aseguré de que la identidad de firma de código y el perfil de aprovisionamiento enumerados en la sección Firma de código de las Configuraciones de comstackción del objective fueran idénticos a los de la aplicación (no el genérico “Desarrollador de iPhone”)

Codesigning un paquete .xctest no es tan fácil como parece en algunos casos. Principalmente, JorgeDeCorte está en lo cierto con su respuesta de que la línea corta dada como una Run Script es suficiente para la mayoría de los desarrolladores.

 codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH" 

Pero cuando tienes múltiples certificados en tu llavero, esto fallará con la siguiente línea

 iPhone Developer: ambiguous (matches "iPhone Developer: Your Name (ABC123DEF45)" and "iPhone Developer: Your Name (123ABC456DE)" 

Una solución para obtener el certificado correcto incluso con múltiples es este pequeño script. Seguro que esto no es lo ideal, pero que yo sepa, no tiene posibilidad de obtener el certificado que Xcode encontró y utiliza para firmar su .app.

 echo "codesign --verify --force --sign \"$CODE_SIGN_IDENTITY\" \"$CODESIGNING_FOLDER_PATH\"" IDENTITIES=`security find-identity -v -s "Code Signing" | grep "iPhone Developer" | awk '{ print $2 }'` for SHA in $IDENTITIES; do codesign --verify --force --sign $SHA "$CODESIGNING_FOLDER_PATH" if [ $? -eq 0 ]; then echo "Matching identity found: $SHA" exit 0 fi done; exit 1 

Obtuve el error -34018 en mi aplicación (iOS 8.4) muy raramente. Después de algunas investigaciones, descubrí que este problema ocurre cuando la aplicación solicita datos de llavero con demasiada frecuencia .
Por ejemplo, en mi situación, se trataba de dos solicitudes de lectura para una clave específica al mismo tiempo desde diferentes módulos de aplicaciones.
Para arreglar eso, acabo de agregar el almacenamiento en caché de este valor en la memoria

Estaba teniendo el mismo problema, de repente, ejecutándose en un dispositivo de prueba con Xcode 6.2, iPhone 6, iOS 8.3. Para que quede claro, esto no se experimentó al ejecutar las pruebas de Xcode, sino al ejecutar la aplicación real en mi dispositivo. En el simulador estaba bien, y funcionando en la propia aplicación había estado perfectamente bien hasta hace poco.

Probé todas las sugerencias que pude encontrar aquí, como eliminar los perfiles de aprovisionamiento en mi dispositivo (eliminé TODOS), habilitando temporalmente la capacidad de Compartir Llaves en mi proyecto (aunque realmente no necesitamos eso), haciendo Seguro que mi cuenta de desarrollo en Xcode se actualizó por completo con todos los certificados y perfiles de aprovisionamiento, etc. Nada ayudó.

Luego cambié temporalmente el nivel de accesibilidad de kSecAttrAccessibleAfterFirstUnlock a kSecAttrAccessibleAlwaysThisDeviceOnly , ejecuté la aplicación y funcionó bien y pude escribir en el llavero. Luego lo cambié de nuevo a kSecAttrAccessibleAfterFirstUnlock , y el problema parece haber desaparecido “permanentemente”.

Acabo de ser mordido por este error en Xcode 8 Beta 3. Encendido de llavero Compartir parece ser la única solución.

Tuve el mismo problema. Se corrigió configurando Compartir Llaves.

(Esta no es una respuesta directa a la pregunta del OP, pero podría ayudar a otros)

Comencé a obtener el error de llavero -34018 consistentemente en el simulador después de actualizar Xcode de la versión 7.3.1 a la 8.0.

Siguiendo este consejo de la respuesta de daidai ,

Algunas instancias del problema son causadas por la firma incorrecta de la aplicación. Puede distinguir fácilmente este caso porque el problema es 100% reproducible.

se descubrió que el Perfil de Aprovisionamiento de alguna manera se había establecido en Ninguno en las secciones de Firma del objective.

Sin embargo, establecer los campos de Perfil de Aprovisionamiento a valores válidos no fue suficiente para resolver el problema en este caso.

La investigación adicional mostró que el derecho de Notificaciones Push también mostró un error. Dijo “Agregar la función Notificaciones Push a su ID de aplicación”. el paso se completó, pero el paso “Agregar el derecho de notificaciones de inserción a su archivo de derechos” no fue completado.

Después de presionar “Solucionar problema” para solucionar el problema de notificación de inserción, se resolvió el error de llavero.

Para este objective en particular, el derecho de “Compartir Llaves” ya se había activado en algún momento anterior. Desactivarlo no ha provocado que el error de llave vuelva a aparecer hasta el momento, por lo que no está claro si es necesario en este caso.

En iOS 9 apagué el Address Sanitizer y comenzó a funcionar en el dispositivo.

La única solución que funcionó para mí fue primero almacenar nil para la clave especificada, y luego almacenar mi nuevo valor con una operación separada. Fallaría debido al error -34018 si intenté sobreescribir el valor existente. Pero siempre que guarde cero primero, el valor actualizado se almacenará con éxito inmediatamente después.

Hoy me encontré con este problema -34018 al ejecutar SecItemDelete API. Lo que hice para solucionar esto es: 1. Después de la solución @ k1th https://stackoverflow.com/a/33085955/889892 2. Ejecute SecItemDelete en el hilo principal (anteriormente se lee desde el hilo principal, así que simplemente alinee esto con eliminar) .

Lo siento, vuelve de nuevo 🙁

Active Compartir llavero en las capacidades de su proyecto, debería resolver el problema. enter image description here