SecItemAdd e SecItemCopyMatching retornam o código de erro -34018 (errSecMissingEntitlement)

116

Às vezes, quando executo um aplicativo no dispositivo do Xcode, eu tentava acessar o keychain, mas falhava devido ao erro -34018. Isso não corresponde a nenhum dos códigos de erro de chaveiro documentados e não pode ser reproduzido de forma consistente. (acontece talvez 30% das vezes, e não está claro para mim por que acontece). O que torna a depuração desse problema muito difícil é a total falta de documentação. Alguma ideia do que causa isso e como consertar? Estou usando o Xcode 5 e executando o iOS 7.0.4 no dispositivo.

Há um problema em aberto sobre isso aqui: https://github.com/soffes/sskeychain/issues/52

EDIT: Adicionando código de acesso de chaveiro por solicitação

Estou usando a SSKeychainbiblioteca para fazer interface com as chaves. Aqui está o trecho.

#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

Na maioria das vezes, está tudo bem. Às vezes, encontro falhas de asserção em que não consigo escrever ou ler do keychain, causando uma falha crítica de asserção.

Tony
fonte
eu tenho o mesmo problema e não consigo reproduzi-lo ... Estou usando a classe KeychainItemWrapper da Apple. Às vezes, ele falha no Google Analytics com a mesma mensagem de erro. Estou usando o Google Analytics v3.02.
Joey
Além disso, parece estar OK no aplicativo da AppStore. isso acontece apenas na versão de desenvolvimento do aplicativo.
Joey
2
Tenho crashlytics para a versão da app store e, infelizmente, parece acontecer na app store também, embora menos frequente do que no dev: /
Tony
3
Estou pensando em mudar de chaveiro porque o fato de que os dados armazenados no chaveiro podem ser perdidos aleatoriamente dessa forma é praticamente um erro fatal para o aplicativo.
Tony
2
Também estamos vendo esse problema intermitente. Geramos uma exceção quando obtemos um rc inesperado de secItemCopyMatching incluindo o caso -34018. Tentamos (relutantemente) adicionar um mecanismo onde, uma vez que obtemos o valor que precisamos do keychain, armazenamos em cache na memória do aplicativo e, em seguida, servimos de lá sem acesso ao keychain. Mas agora estamos vendo raras ocasiões em que o acesso de um chaveiro para obtê-lo falha com um -34018. Alguém tentou repetir a operação após um -34018?
Chris Markle de

Respostas:

45

Correção para iOS 10 / XCode 8:

Adicione o direito KeyChain, vá para as configurações do projeto-> Recursos-> Compartilhamento das Chaves-> Adicionar Grupos das Chaves + Ativar

Uma resposta aqui, da Apple:

ATUALIZAÇÃO: finalmente conseguimos reproduzir o erro -34018 no iOS 8.3. Esta é a primeira etapa para identificar a causa raiz e, em seguida, encontrar uma solução.

Como de costume, não podemos nos comprometer com um prazo de lançamento, mas isso afetou muitos desenvolvedores e realmente queremos resolver isso.

Anteriormente, sugeri adicionar um pequeno atraso no aplicativo: didFinishLaunchingWithOptions e applicationDidBecomeActive: antes de acessar o keychain como uma solução alternativa. No entanto, isso não parece realmente ajudar. Isso significa que não há nenhuma solução alternativa conhecida no momento, exceto reiniciar o aplicativo.

O problema parece estar relacionado à pressão da memória, portanto, talvez ser mais agressivo no tratamento dos avisos de memória pode aliviar o problema

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

ATUALIZAR

OK, aqui estão as últimas.
Este é um problema complexo com várias causas possíveis:

  • Algumas instâncias do problema são causadas por assinatura incorreta do app. Você pode facilmente distinguir este caso porque o problema é 100% reproduzível.
  • Algumas instâncias do problema são causadas por um bug no modo como o iOS oferece suporte ao desenvolvimento de aplicativos (r. 23.991.853). A depuração foi complicada pelo fato de que outro bug no sistema operacional (r. 23.770.418) mascarou seu efeito, significando que o problema só surgiu quando o dispositivo estava sob pressão de memória. Acreditamos que esses problemas foram resolvidos no iOS 9.3.
  • Suspeitamos que pode haver ainda mais causas para esse problema.

Portanto, se você vir este problema em um dispositivo de usuário (um que não foi falado pelo Xcode) que está executando o iOS 9.3 ou posterior, envie um relatório de bug sobre isso. Tente incluir o log do sistema do dispositivo em seu relatório de bug (sei que pode ser complicado ao lidar com dispositivos do cliente; uma opção é pedir ao cliente para instalar o Apple Configurator, que permite que ele visualize o log do sistema). E se você registrar um bug, poste o número do bug, apenas para registro.

Em nome da Apple, gostaria de agradecer a todos por seus esforços em ajudar a rastrear esse problema horrível. compartilhe e curta

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

Daidai
fonte
2
O problema ainda se reproduz no iOS 9.2, iPhone 5S.
DevGansta de
1
Parece que o iOS 9.3 deve resolver esse problema de acordo com a resposta mais recente da Apple no tópico que você vinculou. @daidai, você poderia atualizar sua resposta com essas novas informações?
jf
1
@YoonLee também estou vendo isso no iOS10 - também usando o SDK 2.4.8 da AWS. Erro acionado na linha AWSClientContext.m 54. Teve sorte em resolver isso?
CharlesA
1
@YoonLee btw, acabei de resolver isso usando uma das respostas abaixo: 'Compartilhamento de KeyChain ativado para recursos de destino'
CharlesA
1
@CharlesA Sim, resolvi naquele dia. Você está certo. Parece que a opção 'Ativar KeyChain Entitlement' corrige o problema. Surpreendentemente, esse erro nem sempre é acionado. De qualquer forma, agora estou ligando isso.
Yoon Lee
25

Basicamente, você deve codificar sua pasta .xcttest adicionando o seguinte como um script de execução em seu destino de teste.

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

Eu recebi muitos erros -34018 ao testar meu chaveiro no dispositivo e isso conseguiu consertar.

Se o problema não existir no seu alvo de teste, provavelmente esta não é a solução.

JorgeDeCorte
fonte
Confirmado, isso corrigiu no ambiente de teste. Tive que adicionar o script de execução no destino de teste real (por exemplo, aqueles com todos os testes de unidade, não o destino de compilação que é executado no dispositivo). Também confirmou que este era apenas um problema no dispositivo, não no simulador.
iwasrobbed de
2
Recebo ": nenhuma identidade encontrada Command / bin / sh falhou com o código de saída 1" quando faço isso? Supondo que não tenho um $ CODE_SIGN_IDENTITY. Alguma ideia de como eu conserto isso?
Daniel Coffman
1
@DanielCoffman, você deve ir para as configurações de destino e em Identidade de assinatura de código selecionar "Desenvolvedor iOS" (ou qualquer outra identidade válida). Isso corrige o erro de compilação, mas pelo menos para mim não corrige o problema das Chaves. Ainda recebo o código de erro -34018.
Marcin
3
Obrigado Marcin. Comecei a receber este erro quando mudei para o xcode 6 beta. Nenhuma sugestão neste tópico foi resolvida. Revertido para xcode 5 e -34018 não ocorre mais.
Daniel Coffman
Também experimentei esse erro pela primeira vez desde que uso o XCode 6.3.
Vladimír Slavík
13

Depois de inspecionar o código-fonte . Percebi que os recursos das chaves são acessados ​​por meio de um daemon de segurança que é executado em seu próprio processo (separado do processo do aplicativo).

Seu aplicativo e o processo de segurança 'conversam' através de uma tecnologia chamada XPC .

Se necessário, o securityd é iniciado por meio do conhecido comando launchd do XPC. Provavelmente, você pode verificar se o daemon está em execução no aplicativo Activity Monitor (se estiver em execução no simulador, é claro) e se seu processo pai foi iniciado.

Meu palpite aqui é que é possível que, por algum motivo desconhecido, o daemon de segurança falhe ao iniciar ou faça isso muito lentamente e não esteja pronto quando você tentar usá-lo.

Talvez você possa pensar em como pré-lançar o daemon.

Peço desculpas por não ser mais preciso. Espero que possa ajudá-lo a ir mais longe em suas investigações.

Vincent Zgueb
fonte
2
Eu recebo esse problema apenas quando meu aplicativo é reaberto por meio de um link direto com o seguinte método de delegado de aplicativo: - (BOOL) aplicativo: (UIApplication *) aplicativo handleOpenURL: (NSURL *) url. Se eu apenas iniciar o aplicativo, a escrita do keychain funciona, e se eu minimizar e maximizar o aplicativo, ele ainda funciona. É apenas quando eu reabrir com o link direto que esse problema ocorre. Tenho MyApp.entitlements configurados em meu projeto (Keychain Sharing na guia Capabilities) Xcode 7 beta 4.
FranticRock
Meu caso é semelhante ao de Alex, o que só acontece quando o aplicativo tem um link direto. Caso contrário, ele funciona bem. Talvez algum contexto não esteja certo quando o aplicativo é aberto a partir de outro aplicativo.
CodeBrew
12

Estou observando um comportamento semelhante depois de criar e executar meu código no Xcode 6 beta com iOS 8 SDK (está funcionando corretamente com o Xcode 5 / iOS 7). No Xcode 6, no iOS Simulator SecItemCopyMatching sempre retorna -34018. Ele começou a funcionar depois de ativar o “Compartilhamento de Chaves” na guia Capacidades.

No entanto, tenho outro problema. Estou desenvolvendo biblioteca estática, que é usada por (entre outros) aplicativo Demo. A solução acima funciona para o projeto de aplicativo Demo, mas quando tento fazer o teste de unidade do meu projeto de biblioteca estática, recebo exatamente o mesmo erro. E o problema é que meu projeto de biblioteca estática não tem a guia Capacidades (já que não é o aplicativo independente).

Já experimentei a solução postada aqui pelo JorgeDeCorte, com codesigning no alvo de teste, mas não funciona para mim.

Marcin
fonte
8
E de volta ao iOS 8 beta 3 :)
Mustafa
7
E de volta ao iOS 9.0
Alex Stone,
4
E agora de volta ao iOS 9.2 :-(
Vamos
4
De volta ao iOS 10 beta 2
Pranjal Bikash Das
3
E de volta ao iOS 10 beta 5
Pascal
6

Tente desativar todos os pontos de interrupção ao iniciar o aplicativo do Xcode. Você pode habilitá-los depois.

(Nenhuma das soluções alternativas acima funcionou para mim)

HeTzi
fonte
Estranho. Parece corrigir esse problema para mim também! Toda vez que eu comecei a depurar no simulador, pude experimentar o -34018 OSStatus.
midori,
4

Acabei de ter o mesmo problema no simulador executando 7.1 e 8.0. Enquanto fazia algumas pesquisas, percebi que o aplicativo de amostra da Apple tinha o Compartilhamento de KeyChain ativado para seus recursos de destino. Eu o ativei para meu aplicativo, o que resultou na criação de um arquivo de direitos que deixei com os valores padrão e agora não estou recebendo mais erros -34018. Isso não é o ideal, mas vou usar a opção de compartilhamento KeyChain por enquanto.

Laurent
fonte
4

Codificar um pacote .xctest não é tão fácil quanto parece em alguns casos. Principalmente JorgeDeCorte está certo em sua resposta de que a linha curta fornecida como um Run Scripté suficiente para a maioria dos desenvolvedores.

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

Mas quando você tem vários certificados em suas chaves, isso irá falhar com a seguinte linha

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

Uma solução para obter o certificado certo mesmo com vários é este pequeno script. Com certeza isso não é o ideal, mas pelo meu conhecimento você não tem chance de obter o certificado que o Xcode encontrou e usa para assinar seu .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
fonte
4

Eu fui mordido por isso também e não tive sucesso com nenhuma das outras soluções alternativas. Em seguida, limpei meus perfis de provisionamento nos próprios dispositivos, excluindo todos eles relacionados ao meu aplicativo, bem como todos os perfis curinga (este parece ser o ponto). Para fazer isso, vá para a janela "Dispositivos" no Xcode e clique com o botão direito em seu telefone (conectado):

Clique em "Mostrar perfis de aprovisionamento" e exclua os relacionados, principalmente os perfis da equipe:

incluindo aqueles com o asterisco. Após a reinstalação do app, tudo voltou ao normal.

k1
fonte
Isso me ajudou a executar o aplicativo do Xcode e continuar o processo de desenvolvimento.
salabaha
Ao construir uma versão AdHoc, você pode verificar quais PPs são usados. se você vir qualquer perfil XC: exclua-os e atualize seu PP!
dogsgod,
Posso ver como isso pode ser um fator. Que bagunça aí !! Fazendo uma limpeza de queda
David
3

Eu resolvi esse problema (eu acho). Eu tinha um perfil de provisionamento curinga em meu dispositivo que mostrava que ele não tinha uma identidade de assinatura válida. Eu também tinha um perfil de provisionamento válido para meu aplicativo. Quando excluí o perfil curinga, parei de receber os erros -34018.

Também me certifiquei de que a identidade de assinatura de código e o perfil de provisionamento listado na seção de assinatura de código das Configurações de compilação do destino eram idênticos ao do aplicativo (não o genérico "desenvolvedor de iPhone")

Dave Hirsch
fonte
Semelhante a isso consertou para mim. Defina a assinatura de código de nível de projeto como "iPhone Developer" para Debug e "iPhone Distribution" para lançamento. Em seguida, removi as substituições no alvo principal para que mostrassem o mesmo. Antes, salvar o chaveiro falhava 100% do tempo. Depois disso, o salvamento no chaveiro parece estar estável.
jowie de
2

Eu estava recebendo o erro -34018 em meu aplicativo (iOS 8.4) muito raramente. Após alguma investigação, descobri que esse problema ocorre quando o aplicativo solicita dados do keychain com muita frequência .
Por exemplo, na minha situação, foram duas solicitações de leitura para uma chave específica ao mesmo tempo de diferentes módulos de aplicativo.
Para corrigir isso, acabei de adicionar esse valor em cache na memória

algum dia
fonte
1

Eu estava tendo o mesmo problema, do nada, rodando em um dispositivo de teste com Xcode 6.2, iPhone 6, iOS 8.3. Para ficar claro, isso não aconteceu durante a execução de testes do Xcode, mas sim durante a execução do aplicativo real no meu dispositivo. No simulador estava tudo bem, e rodando no próprio aplicativo estava perfeitamente bem até recentemente.

Tentei todas as sugestões que encontrei aqui, como remover os perfis de provisionamento do meu dispositivo (removi TODOS), ativar temporariamente o recurso de compartilhamento das chaves em meu projeto (embora não precisemos realmente disso), tornando Certifique-se de que minha conta de desenvolvimento no Xcode foi totalmente atualizada com todos os certificados e perfis de provisionamento, etc. Nada ajudou.

Em seguida, alterei temporariamente o nível de acessibilidade de kSecAttrAccessibleAfterFirstUnlockpara kSecAttrAccessibleAlwaysThisDeviceOnly, executei o aplicativo e ele funcionou bem e foi possível gravar no Keychain. Então mudei de volta para kSecAttrAccessibleAfterFirstUnlocke o problema parece ter desaparecido "permanentemente".

Mason G. Zhwiti
fonte
1

Acabei de ser mordido por esse bug no Xcode 8 Beta 3. Ativar o compartilhamento de chaves parece ser a única solução.

XCool
fonte
1

Eu tive o mesmo problema. Corrigido ao configurar o compartilhamento de chaveiro.

lumenela
fonte
1

(esta não é uma resposta direta à pergunta do OP, mas pode ajudar outros)

Começou a obter o erro de keychain -34018 de forma consistente no simulador após atualizar o Xcode da versão 7.3.1 para 8.0.

Seguindo esta dica da resposta da daidai ,

Algumas instâncias do problema são causadas por assinatura incorreta do app. Você pode distinguir facilmente este caso porque o problema é 100% reproduzível.

foi descoberto que o Perfil de Provisionamento de alguma forma foi definido como Nenhum nas seções de Assinatura do destino.

No entanto, definir os campos do perfil de provisionamento com valores válidos não foi suficiente para resolver o problema neste caso.

Uma investigação mais aprofundada mostrou que o direito a notificações push também exibiu um erro. Ele dizia "Adicione o recurso de notificações push ao seu ID do aplicativo". etapa foi concluída, mas a etapa "Adicionar o direito de Notificações Push ao seu arquivo de direitos" não foi.

Depois de clicar em "Corrigir problema" para corrigir o problema de Notificação Push, o erro do keychain foi resolvido.

Para este destino específico, o direito de "Compartilhamento de Chaves" já havia sido ativado em algum momento anterior. Desligá-lo não fez com que o erro do keychain reaparecesse até agora, portanto, não está claro se ele é necessário neste caso.

jk7
fonte
0

No iOS 9, desliguei o Address Sanitizer e ele começou a funcionar no dispositivo.

pulse4life
fonte
0

A única solução que funcionou para mim foi primeiro armazenar nil para a chave especificada e, em seguida, armazenar meu novo valor com uma operação separada. Haveria falha devido ao erro -34018 se eu tentasse substituir o valor existente. Mas, desde que eu armazenasse nil primeiro, o valor atualizado seria armazenado com êxito imediatamente depois.

FranticRock
fonte
0

Eu encontrei este problema -34018 hoje ao executar a API SecItemDelete. O que fiz para consertar isso foi: 1. Seguindo @ k1th solução https://stackoverflow.com/a/33085955/889892 2. Execute o SecItemDelete no thread principal (anteriormente é lido do thread principal, então apenas alinhe isso com exclusão) .

Desculpe, ele volta novamente :(

Senry
fonte
0

Ative o compartilhamento de chaves nas capacidades do seu projeto, isso deve resolver o problema. insira a descrição da imagem aqui

Rizwan Ahmed
fonte
0

O que funcionou para mim

  • Ative o compartilhamento de chaveiro.
  • Use as chaves o menos possível e armazene os dados em cache na memória, preferências do usuário, disco, etc.
  • Repita várias vezes as operações CRUD do keychain se elas falharem.
  • Use DispatchQueue.sync para armazenar / excluir / atualizar os dados.
rockdaswift
fonte
0

Para mim, era um problema de assinatura de aplicativo. Simplesmente mudei para a equipe de assinatura correta no Xcode e o erro não ocorreu mais

Adam Smith
fonte