verificar verificacion seguida puedo numero llega escribe enviaron demasiados cuenta contraseña confianza codigos codigo cambiar apple iphone core-data encryption ios4 data-protection

verificacion - ¿Cómo puedo averiguar si el usuario de iPhone actualmente tiene un conjunto de códigos de acceso y cifrado habilitado?



se enviaron demasiados codigos iphone (6)

Estoy escribiendo una aplicación de iPhone que requiere que sus datos sean encriptados. Aprendí a activar el cifrado de archivos estableciendo el atributo NSFileProtectionComplete. También sé cómo verificar la versión de iPhone para asegurarme de que ejecuten iOS 4.0 o superior.

Sin embargo, me di cuenta de que si el usuario no ha elegido un código de acceso y no ha habilitado específicamente la protección de datos en la pantalla de Configuración> General> Bloqueo de Passcade, entonces los datos en realidad no están protegidos en absoluto.

Me gustaría mostrar una advertencia y decirle al usuario que debe habilitar una contraseña y activar la protección de datos (que requiere una copia de seguridad y restauración en iPhones anteriores a 4), y luego salir de la aplicación si no tiene una contraseña y protección de datos habilitada. Sin embargo, no puedo averiguar de todos modos para averiguar el estado de estas configuraciones. Todas las API que he encontrado, como "protectedDataAvailable" en UIApplication, todas pasan con éxito si la protección de datos está deshabilitada.


Apple no proporciona un método para determinar si el usuario tiene un conjunto de códigos de acceso.

Si su aplicación necesita cifrado, debe considerar encriptar y descifrar los archivos con una implementación de encriptación de confianza y solicitando al usuario una clave de acceso o almacenando la clave en el llavero.


Desde iOS 9 , hay una marca LAPolicyDeviceOwnerAuthentication en LocalAuthentication framework.

+ (BOOL)isPasscodeEnabled { NSError *error = nil; LAContext *context = [[LAContext alloc] init]; BOOL passcodeEnabled = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error]; if(passcodeEnabled) { return YES; } return NO; }


Independientemente de NSDataWritingAtomic o NSDataWritingFileProtectionComplete, el resultado siempre es el mismo para mí. Comportamiento extraño, aquí está el código:

BOOL expandTilde = YES; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, expandTilde); NSString *filePath; filePath = [[paths lastObject] stringByAppendingPathComponent:@"passcode-check"]; NSMutableData *testData; testData = [NSMutableData dataWithLength:1024]; NSLog(@"Attempt to write data of length %u file: %@", [testData length], filePath); NSError *error = nil; if (![testData writeToFile:filePath options:NSDataWritingAtomic error:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); return NO; } else { NSLog(@"File write successful."); error = nil; NSDictionary *testFileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error]; NSLog(@"Getting attributes: %@", testFileAttributes); if ([NSFileProtectionComplete isEqualToString:[testFileAttributes objectForKey:NSFileProtectionKey]]) { error = nil; [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]; // passcode disabled return YES; } else { error = nil; [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]; return NO; } }


Swift 3

func isPasscodeEnabled() -> Bool { return LAContext().canEvaluatePolicy(LAPolicy.deviceOwnerAuthentica‌​tion, error:nil) }

iOS 9 o superior requerido.


iOS 8 (OS X Yosemite) introdujo una nueva API / constante utilizada para detectar si el dispositivo de un usuario tiene una contraseña.

kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly se puede utilizar para detectar si se ha establecido una contraseña en el dispositivo.

El flujo es:

  1. Intenta guardar un nuevo elemento en el llavero con ese conjunto de atributos
  2. Si tiene éxito, eso indica que un código de acceso está actualmente habilitado
  3. Si la contraseña no se guarda, eso indica que no hay contraseña
  4. Limpie el artículo, porque si ya está en el llavero hará que falle el "agregar", parece que el código de acceso no está configurado

Lo probé en mi iPhone 5S, primero fue true , luego deshabilité el código de acceso en la configuración y el resultado fue false . Finalmente, volví a habilitar el código de acceso y devuelve true . Las versiones anteriores de SO devolverán false . El código funciona en el simulador y se devuelve true en una máquina con la contraseña de OS X establecida (no he probado escenarios alternativos de OS X).

También vea el proyecto de muestra aquí: https://github.com/project-imas/passcode-check/pull/5

Finalmente, que yo sepa, iOS 8 no tiene una configuración para deshabilitar la protección de datos, así que supongo que esto es todo lo que necesita para garantizar el cifrado.

BOOL isAPIAvailable = (&kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly != NULL); // Not available prior to iOS 8 - safe to return false rather than crashing if(isAPIAvailable) { // From http://pastebin.com/T9YwEjnL NSData* secret = [@"Device has passcode set?" dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary *attributes = @{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: @"LocalDeviceServices", (__bridge id)kSecAttrAccount: @"NoAccount", (__bridge id)kSecValueData: secret, (__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly }; // Original code claimed to check if the item was already on the keychain // but in reality you can''t add duplicates so this will fail with errSecDuplicateItem // if the item is already on the keychain (which could throw off our check if // kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly was not set) OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL); if (status == errSecSuccess) { // item added okay, passcode has been set NSDictionary *query = @{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: @"LocalDeviceServices", (__bridge id)kSecAttrAccount: @"NoAccount" }; status = SecItemDelete((__bridge CFDictionaryRef)query); return true; } // errSecDecode seems to be the error thrown on a device with no passcode set if (status == errSecDecode) { return false; } } return false;

PD Como Apple señala en el video de la WWDC que presenta esto (711 Keychain y autenticación con Touch ID), optaron por no hacer que el estado del código de acceso esté directamente disponible a través de la API a propósito, para evitar que las aplicaciones entren en situaciones que no deberían be (es decir, "¿Este dispositivo tiene un código de acceso? De acuerdo, genial, voy a almacenar esta información privada en texto plano". Sería mucho mejor crear una clave de cifrado, almacenarla en kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly y encriptar ese archivo, que será irrecuperable si un usuario decide desactivar su contraseña).


Descargo de responsabilidad: Esta respuesta fue válida hasta ios 4.3.3

Si la protección de datos está activada, un archivo recién creado tendrá una NSFileProtectionKey nil por defecto.

Si la protección de datos está desactivada, un archivo recién creado tendrá una NSFileProtectionNone NSFileProtectionKey por defecto.

Por lo tanto, puede detectar la presencia de protección de archivos con el siguiente código:

NSString *tmpDirectoryPath = [NSHomeDirectory() stringByAppendingPathComponent:@"tmp"]; NSString *testFilePath = [tmpDirectoryPath stringByAppendingPathComponent:@"testFile"]; [@"" writeToFile:testFilePath atomically:YES encoding:NSUTF8StringEncoding error:NULL]; // obviously, do better error handling NSDictionary *testFileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:testFile1Path error:NULL]; BOOL fileProtectionEnabled = [NSFileProtectionNone isEqualToString:[testFile1Attributes objectForKey:NSFileProtectionKey]];