¿Por qué se prefiere char[] a String para las contraseñas?
En Swing, el campo de contraseña tiene un método getPassword()
(devuelve char[]
) en lugar del método habitual getText()
(devuelve String
). De manera similar, me encontré con una sugerencia de no utilizarla String
para manejar contraseñas.
¿Por qué String
supone una amenaza para la seguridad cuando se trata de contraseñas? Se siente incómodo de usar char[]
.
Las cadenas son inmutables . Eso significa que una vez que haya creado el archivo String
, si otro proceso puede volcar la memoria, no hay manera (aparte de la reflexión ) de deshacerse de los datos antes de que se active la recolección de basura .
Con una matriz, puedes borrar explícitamente los datos una vez que hayas terminado. Puede sobrescribir la matriz con lo que desee y la contraseña no estará presente en ninguna parte del sistema, incluso antes de la recolección de basura.
Así que sí, esto es un problema de seguridad, pero incluso usarlo char[]
solo reduce la ventana de oportunidad para un atacante, y es solo para este tipo específico de ataque.
Como se señaló en los comentarios, es posible que las matrices que el recolector de basura mueve dejen copias perdidas de los datos en la memoria. Creo que esto es específico de la implementación: el recolector de basura puede borrar toda la memoria a medida que avanza para evitar este tipo de cosas. Incluso si lo hace, todavía existe el tiempo durante el cual char[]
contiene los personajes reales como una ventana de ataque.
Si bien otras sugerencias aquí parecen válidas, hay otra buena razón. Con Plain String
tienes muchas más posibilidades de imprimir accidentalmente la contraseña en registros , monitores o algún otro lugar inseguro. char[]
es menos vulnerable.
Considera esto:
public static void main(String[] args) {
Object pw = "Password";
System.out.println("String: " + pw);
pw = "Password".toCharArray();
System.out.println("Array: " + pw);
}
Huellas dactilares:
String: Password
Array: [C@5829428e
Para citar un documento oficial, la guía de Arquitectura de criptografía de Java dice esto sobre las contraseñas char[]
versus String
(sobre el cifrado basado en contraseñas, pero, por supuesto, se trata más generalmente de contraseñas):
Parecería lógico recopilar y almacenar la contraseña en un objeto de tipo
java.lang.String
. Sin embargo, aquí está la advertencia:Object
los mensajes de tipoString
son inmutables, es decir, no hay métodos definidos que le permitan cambiar (sobrescribir) o poner a cero el contenido de unString
uso posterior. Esta característica hace queString
los objetos no sean adecuados para almacenar información confidencial de seguridad, como contraseñas de usuario. En su lugar , siempre debe recopilar y almacenar información confidencial sobre seguridad en unachar
matriz.
La pauta 2-2 de las Pautas de codificación segura para el lenguaje de programación Java, versión 4.0 también dice algo similar (aunque originalmente está en el contexto del registro):
Directriz 2-2: No registre información altamente confidencial
Parte de la información, como los números de Seguro Social (SSN) y las contraseñas, es muy confidencial. Esta información no debe conservarse por más tiempo del necesario ni donde pueda ser vista, ni siquiera por los administradores. Por ejemplo, no debe enviarse a archivos de registro y su presencia no debe ser detectable mediante búsquedas. Algunos datos transitorios pueden conservarse en estructuras de datos mutables, como matrices de caracteres, y borrarse inmediatamente después de su uso. Borrar estructuras de datos ha reducido la efectividad en los sistemas típicos de tiempo de ejecución de Java, ya que los objetos se mueven en la memoria de forma transparente para el programador.
Esta directriz también tiene implicaciones para la implementación y el uso de bibliotecas de nivel inferior que no tienen conocimiento semántico de los datos con los que están tratando. Por ejemplo, una biblioteca de análisis de cadenas de bajo nivel puede registrar el texto en el que trabaja. Una aplicación puede analizar un SSN con la biblioteca. Esto crea una situación en la que los SSN están disponibles para los administradores con acceso a los archivos de registro.