Mi pregunta se refiere a los llaveros en iOS (iPhone, iPad, ...). Creo (pero no estoy seguro) que la implementación de llaveros en Mac OS X plantea la misma pregunta con la misma respuesta.
iOS proporciona cinco tipos (clases) de elementos de llavero. Debe elegir uno de esos cinco valores para que la clave kSecClass
determine el 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)
Después de mucho tiempo de leer la documentación de las manzanas, los blogs y las entradas al foro, descubrí que un elemento de tipo llavero kSecClassGenericPassword
obtiene su singularidad de los atributos kSecAttrAccessGroup
,kSecAttrAccount
y kSecAttrService
.
Si esos tres atributos en la solicitud 1 son los mismos que en la solicitud 2, entonces recibirá el mismo elemento de llavero de contraseña genérico, independientemente de cualquier otro atributo. Si uno (o dos o todos) de estos atributos cambia su valor, obtendrá elementos diferentes.
Pero kSecAttrService
solo está disponible para artículos de tipokSecClassGenericPassword
, por lo que no puede ser parte de la "clave única" de un elemento de ningún otro tipo, y parece que no hay documentación que indique claramente qué atributos determinan de manera única un elemento de llavero.
El código de muestra en la clase "KeychainItemWrapper" de "GenericKeychain" usa el atributo kSecAttrGeneric
para hacer que un elemento sea único, pero esto es un error. Las dos entradas en este ejemplo solo se almacenan como dos entradas distintas, porque kSecAttrAccessGroup
son diferentes (una tiene el grupo de acceso configurado, la otra lo deja libre). Si intenta agregar una segunda contraseña sin un grupo de acceso, utilizando Apple KeychainItemWrapper
, fallará.
Entonces, por favor, responda mis preguntas:
- Es cierto, que la combinación de
kSecAttrAccessGroup
,kSecAttrAccount
ykSecAttrService
es la "clave única" de un elemento llavero cuya kSecClass eskSecClassGenericPassword
? - ¿Qué atributos hacen que un elemento de llavero sea único si
kSecClass
no lo eskSecClassGenericPassword
?
fuente
Respuestas:
Las claves principales son las siguientes (derivadas de archivos de código abierto de Apple, consulte Schema.m4 , KeySchema.m4 y SecItem.cpp ):
kSecClassGenericPassword
, la clave principal es la combinación dekSecAttrAccount
ykSecAttrService
.kSecClassInternetPassword
, la clave principal es la combinación dekSecAttrAccount
,kSecAttrSecurityDomain
,kSecAttrServer
,kSecAttrProtocol
,kSecAttrAuthenticationType
,kSecAttrPort
ykSecAttrPath
.kSecClassCertificate
, la clave principal es la combinación dekSecAttrCertificateType
,kSecAttrIssuer
ykSecAttrSerialNumber
.kSecClassKey
, la clave principal es la combinación dekSecAttrApplicationLabel
,kSecAttrApplicationTag
,kSecAttrKeyType
,kSecAttrKeySizeInBits
,kSecAttrEffectiveKeySize
, y el creador, fecha de inicio y de finalización que no están expuestos por SecItem todavía.kSecClassIdentity
no he encontrado información sobre los campos de clave principal en los archivos de código abierto, pero como una identidad es la combinación de una clave privada y un certificado, asumo que la clave principal es la combinación de la clave principal. campos parakSecClassKey
ykSecClassCertificate
.Como cada elemento de llavero pertenece a un grupo de acceso de llavero, parece que el grupo de acceso de llavero (campo
kSecAttrAccessGroup
) es un campo agregado a todas estas claves primarias.fuente
kSecClass
tokSecClassCertificate
okSecClassKey
el llavero también verifica si la entrada (thevalue
) ya está almacenada. Esto evita agregar el mismo certificado o clave dos veces. Además, si especifica unakSecAttrApplicationTag
clave diferente (que debe ser única, con respecto a la publicación anterior), fallará.kSecClass
atributo como el nombre de la tabla y los valores especificados arriba como solo elprimary key
de la tabla respectiva.kSecAttrAccount
ykSecAttrService
? - ¿O puede el programador elegir cualquier semántica que decida?kSecAttrService
es para almacenar el servicio,kSecAttrAccount
es para almacenar el nombre de la cuenta. Puede almacenar diferentes cosas en ellos, pero eso puede resultar confuso.El otro día encontré un error (en iOS 7.1) relacionado con esta pregunta. Estaba usando
SecItemCopyMatching
para leer unkSecClassGenericPassword
artículo y seguía volviendoerrSecItemNotFound
(-25300) a pesar de quekSecAttrAccessGroup
,kSecAttrAccount
ykSecAttrService
todos coincidían con el artículo en el llavero.Eventualmente me di cuenta de que
kSecAttrAccessible
no coincidía. El valor en el llavero tenía pdmn = dk (kSecAttrAccessibleAlways
), pero estaba usandokSecAttrAccessibleWhenUnlocked
.Por supuesto, este valor no es necesario en primer lugar para
SecItemCopyMatching
, pero elOSStatus
no eraerrSecParam
ni,errSecBadReq
sino soloerrSecItemNotFound
(-25300), lo que hizo que fuera un poco difícil de encontrar.por
SecItemUpdate
he experimentado el mismo problema, pero en este método, incluso usar el mismokSecAttrAccessible
en elquery
parámetro no funcionó. Solo la eliminación completa de este atributo lo solucionó.Espero que este comentario les ahorre unos preciosos momentos de depuración para algunos de ustedes.
fuente
La respuesta dada por @Tammo Freese parece ser correcta (pero sin mencionar todas las claves primarias). Estaba buscando alguna prueba en la documentación. Finalmente encontrado:
Documentación de Apple que menciona las claves primarias para cada clase de secreto (cita a continuación):
fuente
Aquí hay otra pieza de información útil sobre la singularidad de un elemento de llavero, que se encuentra en la sección "Garantizar la capacidad de búsqueda" de esta página de documentos de Apple .
El elemento de clase
kSecClassInternetPassword
se usó en el ejemplo, pero hay una nota que dice:fuente