Ma question concerne les porte-clés sous iOS (iPhone, iPad, ...). Je pense (mais je ne suis pas sûr) que la mise en œuvre des trousseaux sous Mac OS X soulève la même question avec la même réponse.
iOS propose cinq types (classes) d'éléments de trousseau. Vous devez choisir l'une de ces cinq valeurs pour la clé kSecClass
pour déterminer le type:
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)
Après avoir longtemps lu la documentation sur les pommes, les blogs et les entrées de forum, j'ai découvert qu'un élément de trousseau de type kSecClassGenericPassword
tire son caractère unique des attributs kSecAttrAccessGroup
, kSecAttrAccount
et kSecAttrService
.
Si ces trois attributs dans la demande 1 sont les mêmes que dans la demande 2, vous recevez le même élément de trousseau de mot de passe générique, quels que soient les autres attributs. Si un (ou deux ou tous) de ces attributs change sa valeur, alors vous obtenez différents éléments.
Mais kSecAttrService
n'est disponible que pour les éléments de type kSecClassGenericPassword
, il ne peut donc pas faire partie de la "clé unique" d'un élément de tout autre type, et il ne semble pas y avoir de documentation qui indique clairement quels attributs déterminent de manière unique un élément de trousseau.
L'exemple de code de la classe "KeychainItemWrapper" de "GenericKeychain" utilise l'attribut kSecAttrGeneric
pour rendre un élément unique, mais il s'agit d'un bogue. Les deux entrées de cet exemple uniquement sont stockées en tant que deux entrées distinctes, car leur kSecAttrAccessGroup
est différent (l'un a le groupe d'accès défini, l'autre le laisse libre). Si vous essayez d'ajouter un deuxième mot de passe sans groupe d'accès, en utilisant KeychainItemWrapper
d'Apple, vous échouerez.
Alors, s'il vous plaît, répondez à mes questions:
kSecAttrAccessGroup
, kSecAttrAccount
et kSecAttrService
est la "clé unique" d'un élément de trousseau dont la kSecClass est kSecClassGenericPassword
?kSecClass
n'est pas kSecClassGenericPassword
?Les clés primaires sont les suivantes (dérivées de fichiers open source d'Apple, voir Schema.m4 , KeySchema.m4 et SecItem.cpp ):
kSecClassGenericPassword
, la clé primaire est la combinaison de kSecAttrAccount
et kSecAttrService
.kSecClassInternetPassword
, la clé primaire est la combinaison de kSecAttrAccount
, kSecAttrSecurityDomain
, kSecAttrServer
, kSecAttrProtocol
, kSecAttrAuthenticationType
, kSecAttrPort
et kSecAttrPath
.kSecClassCertificate
, la clé primaire est la combinaison de kSecAttrCertificateType
, kSecAttrIssuer
et kSecAttrSerialNumber
.kSecClassKey
, la clé primaire est la combinaison de kSecAttrApplicationLabel
, kSecAttrApplicationTag
, kSecAttrKeyType
, kSecAttrKeySizeInBits
, kSecAttrEffectiveKeySize
, et le créateur, la date de début et la date de fin qui ne sont pas encore exposées par SecItem.kSecClassIdentity
Je n'ai pas trouvé d'informations sur les champs de clé primaire dans les fichiers open source, mais comme une identité est la combinaison d'une clé privée et d'un certificat, je suppose que la clé primaire est la combinaison des champs de clé primaire pour kSecClassKey
et kSecClassCertificate
.Comme chaque élément de trousseau appartient à un groupe d'accès au trousseau, il semble que le groupe d'accès au trousseau (champ kSecAttrAccessGroup
) est un champ ajouté à toutes ces clés primaires.
L'autre jour (sur iOS 7.1), je rencontrais un bug lié à cette question. J'utilisais SecItemCopyMatching
pour lire un élément kSecClassGenericPassword
et il ne cessait de renvoyer errSecItemNotFound
(-25300) même si kSecAttrAccessGroup
, kSecAttrAccount
et kSecAttrService
correspondaient tous à l'élément du trousseau.
Finalement, j'ai compris que kSecAttrAccessible
ne correspondait pas. La valeur du trousseau contenait pdmn = dk (kSecAttrAccessibleAlways
), mais j'utilisais kSecAttrAccessibleWhenUnlocked
.
Bien sûr, cette valeur n'est pas nécessaire en premier lieu pour SecItemCopyMatching
, mais le OSStatus
n'était pas errSecParam
ni errSecBadReq
mais juste errSecItemNotFound
(-25300) ce qui le rendait un peu difficile à trouver.
Pour SecItemUpdate
, j'ai rencontré le même problème, mais dans cette méthode, même l'utilisation du même kSecAttrAccessible
dans le paramètre query
n'a pas fonctionné. La suppression complète de cet attribut ne l'a corrigé.
J'espère que ce commentaire sauvera quelques précieux moments de débogage pour certains d'entre vous.
La réponse donnée par @Tammo Freese semble être correcte (mais sans mentionner toutes les clés primaires). Je cherchais des preuves dans la documentation. Finalement trouvé:
Le système considère qu'un élément est un doublon pour un trousseau donné lorsque ce trousseau a déjà un élément de la même classe avec le même ensemble de clés primaires composites. Chaque classe d'élément de trousseau a un ensemble différent de clés primaires, bien que quelques attributs soient utilisés en commun dans toutes les classes. En particulier, le cas échéant, kSecAttrSynchronizable et kSecAttrAccessGroup font partie de l'ensemble de clés primaires. Les clés primaires supplémentaires par classe sont répertoriées ci-dessous:
- Pour les mots de passe génériques, les clés primaires incluent kSecAttrAccount et kSecAttrService.
- Pour les mots de passe Internet, les clés primaires incluent kSecAttrAccount, kSecAttrSecurityDomain, kSecAttrServer, kSecAttrProtocol, kSecAttrAuthenticationType, kSecAttrPort et kSecAttrPath.
- Pour les certificats, les clés primaires incluent kSecAttrCertificateType, kSecAttrIssuer et kSecAttrSerialNumber.
- Pour les éléments clés, les clés primaires incluent kSecAttrKeyClass, kSecAttrKeyType, kSecAttrApplicationLabel, kSecAttrApplicationTag, kSecAttrKeySizeInBits et kSecAttrEffectiveKeySize.
- Pour les éléments d'identité, qui sont un certificat et une clé privée regroupés, les clés primaires sont les mêmes que pour un certificat. Parce qu'une clé privée peut être certifiée plusieurs fois, l'unicité de la certificat détermine celui de l'identité.