SecItemAdd e SecItemCopyMatching restituiscono il codice di errore -34018 (errSecMissingEntitlement)


116

A volte, quando eseguo un'applicazione sul dispositivo da Xcode, provo ad accedere al portachiavi ma non riesce a causa dell'errore -34018. Questo non corrisponde a nessuno dei codici di errore del portachiavi documentati e non può essere riprodotto in modo coerente. (accade forse il 30% delle volte e non mi è chiaro il motivo per cui accade). Ciò che rende molto difficile il debug di questo problema è la totale mancanza di documentazione. Qualche idea su cosa causa questo e come risolverlo? Sto usando Xcode 5 e sto eseguendo iOS 7.0.4 sul dispositivo.

C'è un problema aperto su questo qui: https://github.com/soffes/sskeychain/issues/52

EDIT: aggiunta del codice di accesso al portachiavi per richiesta

Sto usando la SSKeychainlibreria per l'interfacciamento con il portachiavi. Ecco lo snippet.

#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 stragrande maggioranza delle volte va bene. A volte si verificano errori di asserzione in cui non sono in grado di scrivere o leggere dal portachiavi, causando un errore di asserzione critica.


ho lo stesso problema e non riesco a riprodurlo ... Sto usando la classe KeychainItemWrapper di Apple. A volte si arresta in modo anomalo da Google Analytics con lo stesso messaggio di errore. Sto utilizzando Google Analytics v3.02.
Joey

Inoltre, sembra essere OK nell'app da AppStore. succede solo nella versione di sviluppo dell'app.
Joey

2
Ho crashlytics per la versione dell'app store e sfortunatamente sembra che accada anche nell'app store, anche se meno frequente che su dev: /
Tony

3
Sto pensando di abbandonare il portachiavi perché il fatto che i dati memorizzati nel portachiavi possano essere persi casualmente in questo modo è praticamente un errore fatale per l'applicazione.
Tony

2
Stiamo anche assistendo a questo problema intermittente. Solleviamo un'eccezione quando otteniamo un rc imprevisto da secItemCopyMatching incluso il caso -34018. Abbiamo provato (con riluttanza) ad aggiungere un meccanismo in cui, una volta ottenuto il valore di cui abbiamo bisogno dal portachiavi, lo memorizziamo nella memoria dell'app e quindi lo serviamo da lì senza accesso al portachiavi. Ma ora stiamo assistendo a rare occasioni in cui l'accesso al portachiavi per ottenerlo in primo luogo fallisce con un -34018. Qualcuno ha provato a ritentare l'operazione dopo un -34018?
Chris Markle

Risposte:


45

Correzione iOS 10 / XCode 8:

Aggiungi diritto al portachiavi, vai alle impostazioni del progetto-> Capacità-> Condivisione portachiavi-> Aggiungi gruppi portachiavi + Attiva

Una risposta qui, da Apple:

AGGIORNAMENTO: Finalmente siamo stati in grado di riprodurre l'errore -34018 su iOS 8.3. Questo è il primo passo per identificare la causa principale e quindi trovare una soluzione.

Come al solito, non possiamo impegnarci per un periodo di tempo di rilascio, ma questo ha influenzato molti sviluppatori e vogliamo davvero risolverlo.

In precedenza ho suggerito di aggiungere un piccolo ritardo nell'applicazione: didFinishLaunchingWithOptions e applicationDidBecomeActive: prima di accedere al portachiavi come soluzione alternativa. Tuttavia, ciò non sembra effettivamente aiutare. Ciò significa che al momento non sono disponibili soluzioni alternative oltre al riavvio dell'app.

Il problema sembra essere correlato alla pressione della memoria, quindi forse essere più aggressivi nella gestione degli avvisi di memoria potrebbe alleviare il problema

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

AGGIORNARE

OK, ecco l'ultima.
Questo è un problema complesso con molteplici possibili cause:

  • Alcuni casi del problema sono causati da una firma dell'app errata. Puoi facilmente distinguere questo caso perché il problema è riproducibile al 100%.
  • Alcuni casi del problema sono causati da un bug nel modo in cui iOS supporta lo sviluppo di app (r. 23.991.853). Il debug è stato complicato dal fatto che un altro bug nel sistema operativo (r. 23.770.418) ne mascherava l'effetto, il che significa che il problema si è verificato solo quando il dispositivo era sotto pressione della memoria. Riteniamo che questi problemi siano stati risolti in iOS 9.3.
  • Sospettiamo che possano esserci ancora più cause di questo problema.

Quindi, se vedi questo problema su un dispositivo dell'utente (uno a cui non ha parlato Xcode) che esegue iOS 9.3 o versioni successive, invia una segnalazione di bug al riguardo. Prova a includere il registro di sistema del dispositivo nella tua segnalazione di bug (mi rendo conto che può essere complicato quando si tratta di dispositivi del cliente; un'opzione è chiedere al cliente di installare Apple Configurator, che consente loro di visualizzare il registro di sistema). E se invii un bug, per favore pubblica il tuo numero di bug, solo per la cronaca.

A nome di Apple, vorrei ringraziare tutti per i loro sforzi nell'aiutare a rintracciare questo problema piuttosto orribile. Condividi e divertiti

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


2
Il problema si riproduce ancora su iOS 9.2, iPhone 5S.
DevGansta

1
Sembra che iOS 9.3 dovrebbe risolvere questo problema in base all'ultima risposta di Apple nel thread che hai collegato. @daidai, potresti aggiornare la tua risposta con queste nuove informazioni?
jf

1
@YoonLee lo vedo anche con iOS10, utilizzando anche l'SDK 2.4.8 di AWS. Errore attivato nella riga 54 di AWSClientContext.m. Hai avuto fortuna nel risolverlo?
CharlesA

1
@YoonLee btw, ho appena risolto questo problema usando una delle risposte seguenti: "Condivisione KeyChain attivata per capacità di destinazione"
CharlesA

1
@CharlesA Sì, ho risolto quel giorno. Hai ragione. Sembra che "KeyChain Entitlement turn on" risolva il problema. Sorprendentemente, questo errore non si attiva sempre. Comunque, ora lo accendo.
Yoon Lee

25

Fondamentalmente devi codificare la tua cartella .xcttest aggiungendo quanto segue come script di esecuzione nella destinazione del test.

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

Ho ricevuto molti errori -34018 durante il test del mio portachiavi sul dispositivo e questo è riuscito a risolverlo.

Se il problema non esiste nel target di test, probabilmente non è la soluzione.


Confermato questo risolto nell'ambiente di test. Ho dovuto aggiungere lo script di esecuzione sul target di test effettivo (ad esempio quelli con tutti gli unit test, non il target di build che viene eseguito sul dispositivo). Ha anche confermato che questo era solo un problema sul dispositivo, non sul simulatore.
rubato il

2
Ottengo ": nessuna identità trovata Comando / bin / sh non riuscito con codice di uscita 1" quando lo faccio? Immagino di non avere $ CODE_SIGN_IDENTITY. Qualche idea su come risolverlo?
Daniel Coffman

1
@DanielCoffman, devi andare alle impostazioni di destinazione e in Identità di firma del codice selezionare "iOS Developer" (o qualsiasi altra identità valida). Questo risolve l'errore di build, tuttavia almeno per me non risolve il problema del portachiavi. Ricevo ancora il codice di errore -34018.
Marcin

3
Grazie Marcin. Ho iniziato a ricevere questo errore quando sono passato a xcode 6 beta. Nessun suggerimento in questo thread risolto. Ripristinato xcode 5 e -34018 non si verifica più.
Daniel Coffman

Ho riscontrato anche questo errore per la prima volta da quando uso XCode 6.3.
Vladimír Slavík

13

Dopo aver controllato il codice sorgente . Ho notato che le funzionalità del portachiavi sono accessibili tramite un demone di sicurezza che viene eseguito nel proprio processo (separato dal processo dell'app).

La tua app e il processo securityd "dialogano" insieme attraverso una tecnologia chiamata XPC .

Se necessario, securityd viene avviato tramite il noto comando launchd di XPC. Probabilmente puoi controllare che il demone sia in esecuzione nell'app Activity Monitor (se in esecuzione in Simulator, ovviamente) e che il suo processo genitore sia avviato.

La mia ipotesi è che sia possibile che per qualsiasi motivo sconosciuto il demone di sicurezza non si avvii o lo faccia troppo lentamente e non sia pronto quando si tenta di usarlo.

Forse potresti pensare a come pre-lanciare il demone.

Mi scuso per non essere stato più preciso. Spero che possa aiutarti a fare un ulteriore passo avanti nelle tue indagini.


2
Ho questo problema solo quando la mia app viene riaperta tramite un collegamento profondo con il seguente metodo delegato dell'app: - (BOOL) application: (UIApplication *) application handleOpenURL: (NSURL *) url. Se avvio l'app, la scrittura del portachiavi funziona e se minimizzo e ingrandisco l'app, funziona ancora. È solo quando riapro con il link profondo che si verifica questo problema. Ho MyApp.entitlements configurato nel mio progetto (Condivisione portachiavi nella scheda Capacità) Xcode 7 beta 4.
FranticRock

Il mio caso è simile a quello di Alex, che accade solo quando l'app è collegata in profondità. Altrimenti funziona bene. Forse un contesto non è corretto quando l'app viene aperta da un'altra app.
CodeBrew

12

Sto osservando un comportamento simile dopo aver creato ed eseguito il mio codice in Xcode 6 beta con iOS 8 SDK (funziona correttamente con Xcode 5 / iOS 7). In Xcode 6, in iOS Simulator SecItemCopyMatching restituisce sempre -34018. Ha iniziato a funzionare dopo aver attivato la "Condivisione portachiavi" nella scheda Capacità.

Tuttavia ho un altro problema. Sto sviluppando una libreria statica, che viene utilizzata (tra le altre) dall'applicazione Demo. La soluzione di cui sopra funziona per il progetto dell'applicazione Demo, ma quando provo a testare l'unità del mio progetto di libreria statica, ho esattamente lo stesso errore. E il problema è che il mio progetto di libreria statica non ha la scheda Funzionalità (poiché non è l'applicazione standalone).

Ho provato la soluzione pubblicata qui da JorgeDeCorte, con il codeigning nel target di test, ma per me non funziona.


8
E di nuovo in iOS 8 beta 3 :)
Mustafa

7
E di nuovo in iOS 9.0
Alex Stone

4
E ora di nuovo in iOS 9.2 :-(
Vamos

4
Di nuovo in iOS 10 beta 2
Pranjal Bikash Das

3
E di nuovo in iOS 10 beta 5
Pascal

6

Prova a disabilitare tutti i punti di interruzione all'avvio dell'app da Xcode. Puoi abilitarli in seguito.

(Nessuna delle soluzioni alternative di cui sopra ha funzionato per me)


Strano. Sembra risolvere questo problema anche per me! Ogni volta che ho iniziato a eseguire il debug sul simulatore ho potuto sperimentare il -34018 OSStatus.
midori

4

Ho appena avuto lo stesso problema sul simulatore con 7.1 e 8.0. Mentre scavo, ho notato che l'app di esempio Apple aveva la condivisione KeyChain attivata per le sue capacità di destinazione. L'ho attivato per la mia app che ha portato alla creazione di un file di autorizzazione che ho lasciato con i valori predefiniti e ora non ricevo più errori -34018. Questo non è l'ideale, ma per ora vivrò l'opzione di condivisione KeyChain.


4

La progettazione del codice di un pacchetto .xctest non è così facile come sembra in alcuni casi. Principalmente JorgeDeCorte ha ragione con la sua risposta che la linea breve data come a Run Scriptè sufficiente per la maggior parte degli sviluppatori.

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

Ma quando hai più certificati nel tuo portachiavi, questo fallirà con la seguente riga

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

Una soluzione per ottenere il certificato giusto anche con più certificati è questo breve script. Sicuramente questo non è l'ideale, ma per quanto ne so non hai alcuna possibilità di ottenere il certificato che Xcode ha trovato e utilizza per firmare il tuo .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

4

Anch'io sono stato morso da questo e non ho avuto successo con nessuna delle altre soluzioni alternative. Ho quindi ripulito i miei profili di provisioning sui dispositivi stessi eliminandoli tutti relativi alla mia app e tutti i profili con caratteri jolly (questo sembra essere il punto). Per fare ciò, vai alla finestra "Dispositivi" in Xcode e fai clic con il pulsante destro del mouse sul telefono (connesso):

Fare clic su "Mostra profili di provisioning" ed eliminare quelli correlati, e in particolare i profili del team:

compresi quelli con l'asterisco. Dopo aver reinstallato l'app, tutto è tornato alla normalità.


Questo mi ha aiutato a eseguire l'app da Xcode e continuare il processo di sviluppo.
salabaha

Quando si crea una versione AdHoc è possibile verificare quali PP vengono utilizzati. se vedi XC: profili, cancellali e aggiorna la tua PP!
dogsgod

Posso vedere come questo potrebbe essere un fattore. Che casino lì dentro !! Facendo un po 'di pulizia autunnale
David

3

Ho risolto questo problema (credo). Avevo un profilo di provisioning con caratteri jolly sul mio dispositivo che mostrava che non aveva un'identità di firma valida. Avevo anche un profilo di provisioning valido per la mia app. Quando ho eliminato il profilo con caratteri jolly, ho smesso di ricevere gli errori -34018.

Mi sono anche assicurato che l'identità di firma del codice e il profilo di provisioning elencati nella sezione Firma del codice delle impostazioni di compilazione della destinazione fossero identici a quello dell'app (non quello generico "iPhone Developer")


Simile a questo risolto per me. Imposta la firma del codice a livello di progetto su "iPhone Developer" per il debug e "iPhone Distribution" per il rilascio. Ho quindi rimosso le sostituzioni sull'obiettivo principale in modo che mostrino lo stesso. Prima, il salvataggio nel portachiavi falliva il 100% delle volte. Successivamente, il salvataggio nel portachiavi sembra essere stabile.
jowie

2

Ho ricevuto l' errore -34018 nella mia app (iOS 8.4) molto raramente. Dopo alcune indagini ho scoperto che questo problema si verifica quando l'app richiede i dati dal portachiavi troppo spesso .
Ad esempio, nella mia situazione erano due richieste di lettura per una chiave specifica allo stesso tempo da diversi moduli dell'applicazione.
Per risolvere il problema, ho appena aggiunto la memorizzazione nella cache di questo valore


1

Stavo avendo lo stesso problema, di punto in bianco, in esecuzione su un dispositivo di prova con Xcode 6.2, iPhone 6, iOS 8.3. Per essere chiari, questo non è stato riscontrato durante l'esecuzione dei test Xcode, ma piuttosto durante l'esecuzione dell'app effettiva sul mio dispositivo. Nel simulatore andava bene e in esecuzione sull'app stessa era andato benissimo fino a poco tempo fa.

Ho provato tutti i suggerimenti che ho trovato qui, come rimuovere i profili di provisioning sul mio dispositivo (li ho rimossi TUTTI), abilitare temporaneamente la funzionalità di condivisione del portachiavi nel mio progetto (anche se non ne abbiamo davvero bisogno), rendendo certo il mio account di sviluppo in Xcode è stato completamente aggiornato con tutti i certificati e profili di provisioning, ecc. Niente ha aiutato.

Quindi ho temporaneamente modificato il livello di accessibilità da kSecAttrAccessibleAfterFirstUnlocka kSecAttrAccessibleAlwaysThisDeviceOnly, ho eseguito l'app e ha funzionato bene ed è stato in grado di scrivere sul portachiavi. Poi l'ho cambiato di nuovo in kSecAttrAccessibleAfterFirstUnlocke il problema sembra essere andato "definitivamente".


1

Sono appena stato morso da questo bug su Xcode 8 Beta 3. L'attivazione della condivisione del portachiavi sembra essere l'unica soluzione.


1

Ho avuto lo stesso problema. Risolto il problema impostando la condivisione del portachiavi.


1

(questa non è una risposta diretta alla domanda del PO, ma potrebbe aiutare gli altri)

Ho iniziato a ricevere l'errore del portachiavi -34018 in modo coerente nel simulatore dopo l'aggiornamento di Xcode dalla versione 7.3.1 alla 8.0.

Seguendo questo suggerimento dalla risposta di daidai ,

Alcuni casi del problema sono causati da una firma dell'app errata. Puoi facilmente distinguere questo caso perché il problema è riproducibile al 100%.

è stato scoperto che il profilo di provisioning era stato in qualche modo impostato su Nessuno nelle sezioni Firma della destinazione.

Tuttavia, l'impostazione dei campi del profilo di fornitura su valori validi non era sufficiente per risolvere il problema in questo caso.

Ulteriori indagini hanno mostrato che anche il diritto alle notifiche push mostrava un errore. Diceva "Aggiungi la funzione Notifiche push al tuo ID app". il passaggio è stato completato, ma il passaggio "Aggiungi il diritto per le notifiche push al file dei diritti" non lo era.

Dopo aver premuto "Risolvi problema" per risolvere il problema della notifica push, l'errore del portachiavi è stato risolto.

Per questo particolare target, il diritto "Condivisione portachiavi" era già stato attivato in precedenza. Disattivarlo non ha causato la ricomparsa dell'errore del portachiavi fino ad ora, quindi non è chiaro se sia necessario in questo caso.


0

In iOS 9 ho disattivato Address Sanitizer e ha iniziato a funzionare sul dispositivo.


0

L'unica soluzione che ha funzionato per me è stata prima la memorizzazione di zero per la chiave specificata, quindi la memorizzazione del mio nuovo valore con un'operazione separata. Fallirebbe a causa dell'errore -34018 se tentassi di sovrascrivere il valore esistente. Ma fintanto che ho memorizzato prima zero , il valore aggiornato sarebbe stato memorizzato con successo subito dopo.


0

Ho incontrato questo problema -34018 oggi durante l'esecuzione dell'API SecItemDelete. Quello che ho fatto per risolvere questo problema è: 1. Seguendo la soluzione @ k1th https://stackoverflow.com/a/33085955/889892 2. Esegui SecItemDelete nel thread principale (in precedenza viene letto dal thread principale, quindi allinealo con l'eliminazione) .

Scusa, torna di nuovo :(


0

Attiva la condivisione del portachiavi nelle capacità del tuo progetto, dovrebbe risolvere il problema. inserisci qui la descrizione dell'immagine


0

Cosa ha funzionato per me

  • Attiva la condivisione del portachiavi.
  • Usa il portachiavi il meno possibile e memorizza nella cache i dati in memoria, le preferenze utente, il disco, ecc.
  • Riprova molte volte le operazioni CRUD del portachiavi se queste non sono riuscite.
  • Utilizzare DispatchQueue.sync per archiviare / eliminare / aggiornare i dati.

0

Per me è stato un problema di firma dell'app. Sono semplicemente passato al team di firma corretto in Xcode e l'errore non si è più verificato

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.