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

116

A veces, cuando ejecuto una aplicación en el dispositivo desde Xcode, intento acceder al llavero pero falla debido al error -34018. Esto no coincide con ninguno de los códigos de error del llavero documentados y no se puede reproducir de forma coherente. (sucede tal vez el 30% de las veces, y no tengo claro por qué sucede). Lo que dificulta la depuración de este problema es la falta total de documentación. ¿Alguna idea de qué causa esto y cómo solucionarlo? Estoy usando Xcode 5 y ejecuto 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 al llavero por solicitud

Estoy usando la SSKeychainbiblioteca para interactuar con el 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 encuentro fallas de afirmación en las que no puedo escribir o leer desde el llavero, lo que provoca una falla crítica de afirmación.

Tony
fuente
Tengo el mismo problema y no puedo reproducirlo ... Estoy usando la clase KeychainItemWrapper de Apple. A veces se bloquea desde Google Analytics con el mismo mensaje de error. Estoy usando Google Analytics v3.02.
Joey
Además, parece estar bien en la aplicación de AppStore. ocurre solo en la aplicación de la versión de desarrollo.
Joey
2
Tengo crashlytics para la versión de la tienda de aplicaciones y, desafortunadamente, parece suceder también en la tienda de aplicaciones, aunque con menos frecuencia que en dev: /
Tony
3
Estoy pensando en alejarme del llavero porque el hecho de que los datos almacenados en el llavero se puedan perder aleatoriamente de esta manera es un error fatal para la aplicación.
Tony
2
También estamos viendo este problema intermitente. Generamos una excepción cuando obtenemos un rc inesperado de secItemCopyMatching, incluido el caso -34018. Intentamos (a regañadientes) agregar un mecanismo donde, una vez que obtenemos el valor que necesitamos del llavero, lo almacenamos en la memoria de la aplicación y luego lo servimos desde allí sin acceso al llavero. Pero ahora estamos viendo raras ocasiones en las que el acceso de un llavero para obtenerlo en primer lugar falla con un -34018. ¿Alguien ha intentado volver a intentar la operación después de un -34018?
Chris Markle

Respuestas:

45

Corrección de iOS 10 / XCode 8:

Agregue el derecho de llavero, vaya a la configuración del proyecto-> Capacidades-> Compartir llaveros-> 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. Sin embargo, eso en realidad no parece ayudar. Eso significa que no hay una solución alternativa conocida en este momento aparte de reiniciar 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 la memoria pueda aliviar el problema.

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

ACTUALIZAR

Bien, aquí tienes la última.
Este es un problema complejo con múltiples causas posibles:

  • Algunas instancias del problema se deben a una 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). La depuración se complicó por el hecho de que otro error en el sistema operativo (r. 23,770,418) enmascaraba 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 puede haber aún más causas de este problema.

Por lo tanto, si ve este problema en un dispositivo de usuario (uno con el que Xcode no ha hablado) que ejecuta iOS 9.3 o posterior, envíe 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, lo que le permite ver el registro del sistema). Y si presenta un error, publique su número de error, solo para el registro.

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

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

daidai
fuente
2
El problema aún se reproduce en iOS 9.2, iPhone 5S.
DevGansta
1
Parece que iOS 9.3 debería resolver este problema de acuerdo con la última respuesta de Apple en el hilo que vinculó. @daidai, ¿podría actualizar su respuesta con esta nueva información?
jf
1
@YoonLee también estoy viendo esto con iOS10, también usando el SDK 2.4.8 de AWS. Error desencadenado en AWSClientContext.m línea 54. ¿Tuviste suerte resolviendo esto?
CharlesA
1
@YoonLee por cierto, acabo de resolver esto usando una de las respuestas a continuación: 'KeyChain Sharing activado para las capacidades objetivo'
CharlesA
1
@CharlesA Sí, lo resolví ese día. Tienes razón. Parece que 'KeyChain Entitlement enciende' soluciona el problema. Sorprendentemente, este error no siempre se activa. De todos modos, ahora estoy encendiendo esto.
Yoon Lee
25

Básicamente, debe codificar su carpeta .xcttest agregando lo siguiente como un script de ejecución en su objetivo 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 objetivo de prueba, probablemente esta no sea la solución.

JorgeDeCorte
fuente
Confirmado que esto lo arregló en el entorno de prueba. Tuve que agregar el script de ejecución en el objetivo de prueba real (por ejemplo, los que tienen todas las pruebas unitarias, no el objetivo de compilación que se ejecuta en el dispositivo). También confirmó que esto era solo un problema en el dispositivo, no en el simulador.
Fui robado el
2
Recibo ": no se encontró identidad. Comando / bin / sh falló con el código de salida 1" cuando hago esto? Supongo que no tengo un $ CODE_SIGN_IDENTITY. ¿Alguna idea de cómo soluciono esto?
Daniel Coffman
1
@DanielCoffman, debe ir a la configuración de destino y en Identidad de firma de código, seleccione "Desarrollador de iOS" (o cualquier otra identidad válida). Esto corrige el error de compilación, sin embargo, al menos para mí, no soluciona el problema del llavero. Sigo recibiendo el código de error -34018.
Marcin
3
Gracias Marcin. Comencé a recibir este error cuando cambié a xcode 6 beta. No se resolvió ninguna sugerencia en este hilo. Revertido a xcode 5 y -34018 ya no ocurre.
Daniel Coffman
También experimento este error por primera vez desde que utilizo XCode 6.3.
Vladimír Slavík
13

Después de inspeccionar el código fuente . He notado que se accede a las funciones del llavero a través de un demonio de seguridad que se ejecuta en su propio proceso (separado del proceso de la aplicación).

Su aplicación y el proceso de seguridad 'dialogan' 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 demonio se esté ejecutando en la aplicación Activity Monitor (si se ejecuta en Simulator, por supuesto) y que su proceso principal se haya iniciado.

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

Quizás podría pensar en cómo prelanzar el demonio.

Pido disculpas por no ser más preciso. Espero que pueda ayudarlo a avanzar un poco más en sus investigaciones.

Vincent Zgueb
fuente
2
Recibo este problema solo cuando mi aplicación se vuelve a abrir a través de un enlace profundo con el siguiente método de delegado de la aplicación: - (BOOL) aplicación: (UIApplication *) application handleOpenURL: (NSURL *) url. Si acabo de iniciar la aplicación, la escritura de llaveros funciona, y si minimizo y maximizo la aplicación, todavía funciona. Es solo cuando vuelvo a abrir con el enlace profundo que ocurre este problema. Tengo MyApp.entitlements configurados en mi proyecto (Keychain Sharing en la pestaña Capabilities) Xcode 7 beta 4.
FranticRock
Mi caso es similar al de Alex, que solo ocurre cuando la aplicación tiene vínculos profundos. De lo contrario, funciona bien. Quizás algún contexto no sea el adecuado cuando la aplicación se abre desde otra aplicación.
CodeBrew
12

Observo un comportamiento similar después de compilar 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 "Compartir llaveros" 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 la aplicación de demostración, pero cuando trato de realizar una prueba unitaria en 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).

Probé la solución publicada aquí por JorgeDeCorte, con firma de código en el objetivo de prueba, pero no me funciona.

Marcin
fuente
8
Y de vuelta en iOS 8 beta 3 :)
Mustafa
7
Y de vuelta en iOS 9.0
Alex Stone
4
Y ahora de vuelta en iOS 9.2 :-(
Vamos
4
De vuelta en iOS 10 beta 2
Pranjal Bikash Das
3
Y de vuelta en iOS 10 beta 5
Pascal
6

Intente deshabilitar todos los puntos de interrupción al iniciar la aplicación desde Xcode. Puede habilitarlos después.

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

HeTzi
fuente
Extraño. ¡Parece que también me solucionó este problema! Cada vez que comencé a depurar en el simulador, podía experimentar el -34018 OSStatus.
midori
4

Acabo de tener el mismo problema en el simulador que ejecuta 7.1 y 8.0. Mientras investigaba un poco, noté que la aplicación de muestra de Apple tenía KeyChain Sharing activado para sus capacidades de destino. Lo encendí 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 más errores -34018. Esto no es ideal, pero viviré la opción de compartir KeyChain por ahora.

Laurent
fuente
4

Diseñar con código un paquete .xctest no es tan fácil como parece en algunos casos. Principalmente, JorgeDeCorte tiene razón con su respuesta de que la línea corta dada como a Run Scriptes suficiente para la mayoría de los desarrolladores.

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

Pero cuando tenga varios certificados en su 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 varios es este breve script. Seguro que esto no es ideal, pero que yo sepa, no tiene la oportunidad de obtener el certificado que Xcode encontró y usa 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
Patrik
fuente
4

Esto también me mordió y no tuve éxito con ninguna de las otras soluciones. Luego limpié mis perfiles de aprovisionamiento en los dispositivos eliminando todos ellos 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 aprovisionamiento" y elimine los relacionados, y especialmente los perfiles del equipo:

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

k1th
fuente
Esto me ayudó a ejecutar la aplicación desde Xcode y continuar con el proceso de desarrollo.
Salabaha
Al crear una versión AdHoc, puede comprobar qué PP se utilizan. si ve algún perfil XC:, elimínelos y actualice su PP!
dogsgod
Puedo ver cómo esto podría ser un factor. ¡Qué desastre ahí! Limpieza de otoño
David
3

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 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 de firma de código de la configuración de compilación del destino fueran idénticos a los de la aplicación (no al genérico de "desarrollador de iPhone")

Dave Hirsch
fuente
Similar a esto me lo arregló. Establezca la firma de código a nivel de proyecto en "Desarrollador de iPhone" para depuración y "Distribución de iPhone" para lanzamiento. Luego eliminé las anulaciones en el objetivo principal para que muestren lo mismo. Antes, el ahorro en el llavero fallaba el 100% del tiempo. Luego, el ahorro en el llavero parece ser estable.
jowie
2

Me estaba -34.018 error en mi aplicación (iOS 8.4) en muy raras ocasiones. Después de investigar un poco, descubrí que este problema ocurre cuando la aplicación solicita datos del llavero con demasiada frecuencia .
Por ejemplo, en mi situación, fueron dos solicitudes de lectura para una clave específica al mismo tiempo desde diferentes módulos de aplicación.
Para solucionarlo, acabo de agregar el almacenamiento en caché de este valor en la memoria

somedev
fuente
1

Estaba teniendo el mismo problema, de la nada, ejecutándome en un dispositivo de prueba con Xcode 6.2, iPhone 6, iOS 8.3. Para ser claros, 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 ejecutándose 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), habilitar temporalmente la capacidad de compartir llaveros en mi proyecto (aunque realmente no lo necesitamos), haciendo Seguro que mi cuenta de desarrollo en Xcode se actualizó totalmente con todos los certificados y perfiles de aprovisionamiento, etc. Nada ayudó.

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

Mason G. Zhwiti
fuente
1

Acabo de ser picado por este error en Xcode 8 Beta 3. Activar Keychain Sharing parece ser la única solución.

XCool
fuente
1

Tuve el mismo problema. Se solucionó configurando Keychain Sharing.

lumenela
fuente
1

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

Comenzó a recibir el error de llavero -34018 de manera consistente en el simulador después de actualizar Xcode de la versión 7.3.1 a 8.0.

Siguiendo este consejo de la respuesta de daidai ,

Algunas instancias del problema se deben a una 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 se había establecido de alguna manera en Ninguno en las secciones Firma del destino.

Sin embargo, establecer los campos del perfil de aprovisionamiento en valores válidos no fue suficiente para resolver el problema en este caso.

Una investigación adicional mostró que el derecho a las notificaciones automáticas también mostraba un error. Decía "Agregar la función de notificaciones automáticas a su ID de aplicación". se completó el paso, pero el paso "Agregar el derecho de notificaciones automáticas a su archivo de derechos" no lo fue.

Después de presionar "Solucionar problema" para solucionar el problema de las notificaciones push, se resolvió el error del llavero.

Para este objetivo en particular, el derecho "Uso compartido de llaveros" ya se había activado en algún momento anterior. Apagarlo no ha provocado que el error del llavero vuelva a aparecer hasta ahora, por lo que no está claro si es necesario en este caso.

jk7
fuente
0

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

pulse4life
fuente
0

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

FranticRock
fuente
0

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

Lo siento, vuelve de nuevo :(

Senry
fuente
0

Active el uso compartido de llaveros en las capacidades de su proyecto, debería resolver el problema. ingrese la descripción de la imagen aquí

Rizwan Ahmed
fuente
0

Que funciono para mi

  • Activa Compartir llaveros.
  • Use el llavero lo menos posible y almacene los datos en la memoria, las preferencias de usuario, el disco, etc.
  • Vuelva a intentar muchas veces las operaciones CRUD del llavero si fallaron.
  • Utilice DispatchQueue.sync para almacenar / eliminar / actualizar los datos.
rockdaswift
fuente
0

Para mí fue un problema de firma de aplicaciones. Simplemente cambié al equipo de firma correcto en Xcode y el error ya no se produjo

Adam Smith
fuente