Minha pergunta diz respeito a chaveiros no iOS (iPhone, iPad, ...). Acho (mas não tenho certeza) que a implementação de chaveiros no Mac OS X levanta a mesma questão com a mesma resposta.
O iOS oferece cinco tipos (classes) de itens de chaveiro. Você deve escolher um desses cinco valores para a chave kSecClass
para determinar o tipo:
kSecClassGenericPassword used to store a generic password
kSecClassInternetPassword used to store an internet password
kSecClassCertificate used to store a certificate
kSecClassKey used to store a kryptographic key
kSecClassIdentity used to store an identity (certificate + private key)
Depois de muito tempo de documentação maçãs leitura, blogs e fórum-entradas, eu descobri que um item de chaveiro do tipo kSecClassGenericPassword
obtém sua singularidade dos atributos kSecAttrAccessGroup
, kSecAttrAccount
e kSecAttrService
.
Se esses três atributos na solicitação 1 forem iguais aos da solicitação 2, você receberá o mesmo item de chaveiro de senha genérica, independentemente de quaisquer outros atributos. Se um (ou dois ou todos) desses atributos alterar seu valor, você obterá itens diferentes.
Mas kSecAttrService
só está disponível para itens do tipo kSecClassGenericPassword
, portanto, não pode fazer parte da "chave única" de um item de qualquer outro tipo e parece não haver documentação que indique claramente quais atributos determinam exclusivamente um item de chaveiro.
O código de amostra na classe "KeychainItemWrapper" de "GenericKeychain" usa o atributo kSecAttrGeneric
para tornar um item único, mas isso é um bug. As duas entradas neste exemplo são armazenadas apenas como duas entradas distintas, porque kSecAttrAccessGroup
são diferentes (uma tem o grupo de acesso definido, a outra o deixa livre). Se você tentar adicionar uma 2ª senha sem um grupo de acesso, usando o da Apple KeychainItemWrapper
, você falhará.
Então, por favor, responda às minhas perguntas:
- É verdade, que a combinação de
kSecAttrAccessGroup
,kSecAttrAccount
ekSecAttrService
é a "chave única" de um item de chaveiro cuja kSecClass ékSecClassGenericPassword
? - Quais atributos tornam um item de chaveiro único se
kSecClass
não forkSecClassGenericPassword
?
fonte
Respostas:
As chaves primárias são as seguintes (derivadas de arquivos de código aberto da Apple, consulte Schema.m4 , KeySchema.m4 e SecItem.cpp ):
kSecClassGenericPassword
, a chave primária é a combinação dekSecAttrAccount
ekSecAttrService
.kSecClassInternetPassword
, a chave primária é a combinação dekSecAttrAccount
,kSecAttrSecurityDomain
,kSecAttrServer
,kSecAttrProtocol
,kSecAttrAuthenticationType
,kSecAttrPort
ekSecAttrPath
.kSecClassCertificate
, a chave primária é a combinação dekSecAttrCertificateType
,kSecAttrIssuer
ekSecAttrSerialNumber
.kSecClassKey
, a chave primária é a combinação dekSecAttrApplicationLabel
,kSecAttrApplicationTag
,kSecAttrKeyType
,kSecAttrKeySizeInBits
,kSecAttrEffectiveKeySize
, e do criador, data de início e fim data que não são expostos por SecItem ainda.kSecClassIdentity
, não encontrei informações sobre os campos de chave primária nos arquivos de código aberto, mas como uma identidade é a combinação de uma chave privada e um certificado, presumo que a chave primária é a combinação da chave primária campos parakSecClassKey
ekSecClassCertificate
.Como cada item de chaveiro pertence a um grupo de acesso de chaveiro, parece que o grupo de acesso de chaveiro (campo
kSecAttrAccessGroup
) é um campo adicionado a todas essas chaves primárias.fonte
kSecClass
comokSecClassCertificate
oukSecClassKey
o Keychain verifica também se a entrada (ovalue
) já está armazenada. Isso evita adicionar o mesmo certificado ou chave duas vezes. Além disso, se você especificar umakSecAttrApplicationTag
chave diferente (que deve ser única, em relação ao post acima), ela falhará.kSecClass
atributo como o nome da tabela e os valores especificados acima como apenas osprimary key
da respectiva tabela.kSecAttrAccount
ekSecAttrService
? - ou o programador pode escolher qualquer semântica que ele decidir?kSecAttrService
é para armazenar o serviço,kSecAttrAccount
é para armazenar o nome da conta. Você pode armazenar coisas diferentes neles, mas isso pode ficar confuso.Eu estava encontrando um bug outro dia (no iOS 7.1) que está relacionado a essa questão. Eu estava usando
SecItemCopyMatching
para ler umkSecClassGenericPassword
item e ele continuava retornandoerrSecItemNotFound
(-25300) mesmo assimkSecAttrAccessGroup
,kSecAttrAccount
ekSecAttrService
todos combinavam com o item no chaveiro.Eventualmente eu descobri que
kSecAttrAccessible
não combinava. O valor no chaveiro continha pdmn = dk (kSecAttrAccessibleAlways
), mas eu estava usandokSecAttrAccessibleWhenUnlocked
.É claro que esse valor não é necessário em primeiro lugar para
SecItemCopyMatching
, masOSStatus
não eraerrSecParam
nem,errSecBadReq
mas apenaserrSecItemNotFound
(-25300), o que o tornava um pouco complicado de encontrar.Pois
SecItemUpdate
eu experimentei o mesmo problema, mas neste método, mesmo usando o mesmokSecAttrAccessible
noquery
parâmetro não funcionou. Apenas remover completamente esse atributo corrigiu isso.Espero que este comentário economize alguns momentos preciosos de depuração para alguns de vocês.
fonte
A resposta dada por @Tammo Freese parece estar correta (mas não mencionando todas as chaves primárias). Eu estava procurando alguma prova na documentação. Finalmente encontrado:
Documentação da Apple mencionando as chaves primárias para cada classe de segredo (citação abaixo):
fonte
Aqui está outra informação útil sobre a exclusividade de um item de chaveiro, encontrada na seção "Garantir capacidade de pesquisa" desta página de documentos da Apple .
O item da classe
kSecClassInternetPassword
foi usado no exemplo, mas há uma nota que diz:fonte