implicaciones de seguridad de almacenar una contraseña en Settings.bundle y conseguir con CFPreferencesCopyAppValue

StackOverflow https://stackoverflow.com/questions/1248575

Pregunta

Disculpas por la obviedad aparente de esta pregunta, pero por alguna razón no he podido encontrar una respuesta definitiva en la documentación de Apple acerca de dónde y cómo información de contraseña se almacena Settings.bundle. Mi pregunta: ¿Y si necesito para almacenar algunas credenciales para una aplicación, y utilizo un Settings.bundle de manera que se introduzca la contraseña en un campo de texto en PSTextFieldSpecifier área Configuración de Apple con isSecure = SÍ, y luego acceder al valor de mi aplicación con la CFPreferencesCopyAppValue, no escribir nunca fuera a NSUserDefaults y sólo enviarlos a través de la red de forma segura, cómo es seguro es que el método de almacenamiento y recuperación, en comparación con el almacenamiento y la recuperación de la contraseña utilizando la llave en mis propias configuración de la aplicación? Gracias por tu aportación.

¿Fue útil?

Solución

CFPreferencesCopyAppValue es sólo la forma base fundamental de acceso a la misma información que se obtiene cuando se utiliza NSUserDefaults. En términos de seguridad, las características son exactamente lo mismo. Es decir, que no está encriptada. Es seguro sólo en el sentido de que está oscurecida. La respuesta "correcta" es utilizar el llavero.

El contador de esto es que muchas aplicaciones utilizan NSUserDefaults para almacenar contraseñas. Se podría argumentar que a menos que los controles de contraseña de acceso a la información de cualquier valor, entonces no vale la pena el esfuerzo en tratar de utilizar el llavero. Lo que me lleva al segundo argumento en favor de la utilización de un campo seguro en la aplicación Ajustes:. La API de llavero es horrible y, en mi experiencia, al menos, la escritura de código libre de errores es complicado

Otros consejos

No guardar la contraseña de un usuario en el paquete de configuración.
No es segura.

Recuerde, usted no necesita saber lo que es la clave original, lo que necesita saber si la contraseña que el usuario entra partidos la contraseña original. La forma correcta de tratar con las contraseñas en IOS es en

  • Utilice el llavero, como otros han mencionado
  • Generar una función hash criptográfica unidireccional usando SHA-512 u otra encriptación y almacenar el hash resultante y la sal en NSUserDefaults

De estas opciones, el cifrado de la contraseña y almacenar el hash + sal es, con mucho, la más fácil. Esto es lo que haces para almacenar la contraseña:

  1. Coge la contraseña del usuario
  2. Crea un valor sal al azar
  3. Crear un hash sólo hacia adelante usando SHA-512 y el valor de la sal al azar
  4. Almacenar el valor hash y la sal resultante en NSUserDefaults -. Estos valores no pueden ser utilizados por los hackers para determinar la contraseña original, por lo que no hay necesidad para que los guarde en un lugar seguro

Ahora, cuando el usuario introduce su contraseña y usted tiene que comprobar si es correcta, esto es lo que hace:

  1. Coge la contraseña del usuario
  2. Coge el valor hash + sal previamente salvado de NSUserDefaults
  3. Crear un hash sólo hacia adelante usando la misma función hash unidireccional que utilizó para cifrar la clave original - pasándole el intento de contraseña y el valor de la sal NSUserDefaults
  4. Comparar el hash resultante con la que se almacena en NSUSerDefaults. Si son iguales, entonces el usuario introduce la contraseña correcta.

Este es el código para generar la sal y el hash de sólo avance:

NSString *FZARandomSalt(void) {
    uint8_t bytes[16] = {0};
    int status = SecRandomCopyBytes(kSecRandomDefault, 16, bytes);
    if (status == -1) {
        NSLog(@"Error using randomization services: %s", strerror(errno));
        return nil;
    }
    NSString *salt = [NSString stringWithFormat: @"%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
                      bytes[0],  bytes[1],  bytes[2],  bytes[3],
                      bytes[4],  bytes[5],  bytes[6],  bytes[7],
                      bytes[8],  bytes[9],  bytes[10], bytes[11],
                      bytes[12], bytes[13], bytes[14], bytes[15]];
    return salt;
}

NSData *FZAHashPassword(NSString *password, NSString *salt) {
    NSCParameterAssert([salt length] >= 32);
    uint8_t hashBuffer[64] = {0};
    NSString *saltedPassword = [[salt substringToIndex: 32] stringByAppendingString: password];
    const char *passwordBytes = [saltedPassword cStringUsingEncoding: NSUTF8StringEncoding];
    NSUInteger length = [saltedPassword lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
    CC_SHA512(passwordBytes, length, hashBuffer);
    for (NSInteger i = 0; i < 4999; i++) {
        CC_SHA512(hashBuffer, 64, hashBuffer);
    }
    return [NSData dataWithBytes: hashBuffer length: 64];
}

El código para este ejemplo se encontró aquí: http://blog.securemacprogramming.com/2011/04/storing-and-testing-credentials-cocoa-touch-edition/

llavero en el iPhone va a ser el más seguro, a menos que estés usando cifrado personalizado, que es muy difícil de hacer (y exportación). NSUserDefaults no se considera seguro.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top