2011-03-20 13 views
19

¿Es posible actualizar el valor del atributo kSecAttrAccessible de elementos existentes en el llavero? Parece que no se puede cambiar después de que el artículo se haya agregado al Llavero. Los siguientes pasos respaldan mi suposición.¿Es posible actualizar el valor de kSecAttrAccessible de un elemento Keychain?

Añadir un nuevo elemento a la Llavero:

NSData *encodedIdentifier = [@"BUNDLE_IDENTIFIER" 
          dataUsingEncoding:NSUTF8StringEncoding]; 
NSData *encodedPassword = [@"PASSWORD" 
          dataUsingEncoding:NSUTF8StringEncoding]; 

// Construct a Keychain item 
NSDictionary *keychainItem = 
    [NSDictionary dictionaryWithObjectsAndKeys: 
     kSecClassGenericPassword, kSecClass, 
     encodedIdentifier, kSecAttrGeneric, 
     encodedIdentifier, kSecAttrService, 
     @"USERNAME", kSecAttrAccount, 
     kSecAttrAccessibleWhenUnlocked, kSecAttrAccessible, 
     encodedPassword, kSecValueData 
     nil]; 

// Add item to Keychain 
OSStatus addItemStatus = SecItemAdd((CFDictionaryRef)keychainItem, NULL); 

En un momento posterior, cambiar el atributo kSecAttrAccessiblekSecAttrAccessibleWhenUnlocked-kSecAttrAccessibleAfterFirstUnlock:

NSData *encodedIdentifier = [@"BUNDLE_IDENTIFIER" 
          dataUsingEncoding:NSUTF8StringEncoding]; 

NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys: 
         kSecClassGenericPassword, kSecClass, 
         encodedIdentifier, kSecAttrGeneric, 
         encodedIdentifier, kSecAttrService, 
         nil]; 

NSDictionary *updatedAttributes = 
    [NSDictionary dictionaryWithObject:kSecAttrAccessibleAfterFirstUnlock 
           forKey:kSecAttrAccessible]; 

OSStatus updateItemStatus = SecItemUpdate((CFDictionaryRef)query, 
              (CFDictionaryRef)updatedAttributes); 

El problema con este enfoque es que updateItemStatus siempre resulta en el estado errSecUnimplemented.

Creo que debería ser posible actualizar el valor de kSecAttrAccessible porque los requisitos de las aplicaciones cambian. ¿Qué sucede si una aplicación agrega diez elementos al llavero en el pasado sin especificar la clase de protección con kSecAttrAccessible? El llavero asigna implícitamente nuevos elementos al valor kSecAttrAccessibleWhenUnlocked si la clase de protección no está establecida explícitamente por el desarrollador. Más tarde, el desarrollador debe cambiar la clase de protección a kSecAttrAccessibleAfterFirstUnlock porque la aplicación debe acceder a ella en segundo plano (Multitarea). ¿Cómo puede el desarrollador lograr eso?

Ya hay un hilo en los Foros de desarrolladores de Apple, pero no ha dado todavía una respuesta: https://devforums.apple.com/thread/87646?tstart=0

Respuesta

18

Después de abrir un incidente de soporte de Apple para desarrolladores de Soporte Técnico (ADTS), recibí una respuesta que responde a esta pregunta. SecItemUpdate() requiere los datos del elemento Llavero a través del atributo kSecValueData para realizar la actualización del atributo kSecAttrAccessible. Según ADTS, esta restricción actualmente no está documentada en la documentación de referencia.

NSData *encodedIdentifier = [@"BUNDLE_IDENTIFIER" 
          dataUsingEncoding:NSUTF8StringEncoding]; 
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys: 
         kSecClassGenericPassword, kSecClass, 
         encodedIdentifier, kSecAttrGeneric, 
         encodedIdentifier, kSecAttrService, 
         nil]; 

// Obtain the Keychain item's data via SecItemCopyMatching() 
NSData *itemData = ...; 

NSDictionary *updatedAttributes = 
    [NSDictionary dictionaryWithObjectsAndKeys: 
     kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessible, 
     (CFDataRef)itemData, kSecValueData, 
     nil]; 

OSStatus updateItemStatus = SecItemUpdate((CFDictionaryRef)query, 
              (CFDictionaryRef)updatedAttributes); 

// updateItemStatus should have the value errSecSuccess 
+1

Ahora está [documentado] (https://developer.apple.com/library/ios/documentation/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/c/data/kSecAttrAccessible) para ser necesario en iOS 4 y anteriores. –

+0

¡Buen descubrimiento! Gracias. – mbinna

+0

Si usa pares de claves RSA, asegúrese de hacer esto para * both * keys. –

1

No he podido obtener la otra respuesta para trabajar. Terminé probando kSecAttrAccessibile y, si no era lo que quería, grabé el valor y los atributos del llavero en variables locales, reinicié el llavero, configuré kSecAttrAccessible como lo deseaba y luego establecí el valor y los atributos del llavero en su configuración original.

+0

No tiene un fragmento de código para esto, ¿verdad? Tener problemas para hacer que esto funcione –

Cuestiones relacionadas