yet - java.security.accesscontrolexception access denied
Destrucción irrecuperable de datos en Java (10)
Al establecer su Object en null no significa que su objeto se elimine de la memoria. La máquina virtual marcará ese objeto como listo para la recolección de basura si no hay más referencias a ese objeto. Dependiendo de su código, podría seguir siendo referenciado aunque lo haya establecido como nulo, en cuyo caso no se eliminará. (¡En esencia, si espera que sea basura y no tiene una fuga de memoria!)
Una vez que está marcado como listo para la recopilación, no tiene control sobre cuándo el Recolector de basura lo eliminará. Puede perder el tiempo con las estrategias de recolección de basura, pero yo no lo aconsejaría. Haga un perfil de su aplicación y mire el objeto y su ID, y podrá ver lo que está haciendo referencia a él. Java proporciona VisualVM con 1.6.0_07 y superior o puede usar NetBeans
¿Hay alguna forma en Java para eliminar datos (por ejemplo, un valor variable, objeto) y asegurarse de que no se pueda recuperar de la memoria? ¿La asignación de null
a una variable en Java elimina el valor de la memoria? ¿Algunas ideas? Las respuestas aplicables a otros idiomas también son aceptables.
Almacene los datos confidenciales en una matriz y luego "cero" lo antes posible.
Cualquier información en la RAM puede ser copiada al disco por un sistema de memoria virtual. Los datos en la RAM (o un volcado del núcleo) también pueden inspeccionarse mediante herramientas de depuración. Para minimizar la posibilidad de que esto ocurra, debe esforzarse por lo siguiente
- mantener la ventana de tiempo en secreto está presente en la memoria lo más corto posible
- tenga cuidado con las canalizaciones de E / S (p. ej., BufferedInputStream) que almacenan datos de memoria interna
- mantener las referencias al secreto en la pila y fuera del montón
- no use tipos inmutables, como
String
, para guardar secretos
Las API criptográficas en Java usan este enfoque, y cualquier API que crees debería ser compatible. Por ejemplo, KeyStore.load
permite que una persona que llama borre una contraseña char[]
y cuando la llamada finalice, al igual que KeySpec para el cifrado basado en contraseña.
Idealmente, usarías un bloque finally
para poner a cero la matriz, así:
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream is = …
char[] pw = System.console().readPassword();
try {
ks.load(is, pw);
}
finally {
Arrays.fill(pw, ''/0'');
}
Como dijo Zacherates, ponga a cero los campos sensibles de su objeto antes de eliminar las referencias a él. Tenga en cuenta que no puede poner a cero el contenido de una Cadena, así que use las matrices de caracteres y ponga a cero cada elemento.
Creo que tu mejor opción (que no es compleja) es usar un char [] y luego cambiar cada posición en el conjunto. Los otros comentarios sobre la posibilidad de que se copie en la memoria siguen vigentes.
Debido a la maravillosa memoria virtual, es casi imposible eliminar algo de la memoria de una manera completamente irrecuperable. Su mejor apuesta es poner a cero los campos de valor; sin embargo:
- Esto no significa que no se dejará una copia antigua (no puesta a cero) del objeto en una página de intercambio no utilizada, que podría persistir durante el reinicio.
- Tampoco impide que alguien conecte un depurador a su aplicación y hurgue antes de que el objeto se ponga a cero o se cuelgue la máquina virtual y hurgue en el volcado del montón.
Los datos primitivos (byte, char, int, double) y las matrices de ellos (byte [], ...) se borran al escribir nuevo contenido aleatorio en ellos.
Los datos del objeto deben ser desinfectados sobrescribiendo sus propiedades primitivas; establecer una variable en nulo solo hace que el objeto esté disponible para GC, pero no inmediatamente. Un volcado de VM los contendrá para que cualquiera los vea.
Los datos inmutables como String no se pueden sobrescribir de ninguna manera. Cualquier modificación solo hace una copia. Deberá evitar guardar datos confidenciales en dichos objetos.
PD: si hablamos de contraseñas, es mejor utilizar funciones hash criptográficas fuertes (MD5, SHA1, ...) y nunca trabajar con contraseñas en texto claro.
Nada se borra, solo se trata de ser accesible o no para la aplicación. Una vez inaccesible, el espacio se convierte en candidato para su uso posterior cuando sea necesario y se sobrescribirá el espacio. En el caso de acceso directo a memoria, siempre hay algo para leer, pero puede ser basura y no tiene sentido.
No, a menos que tengas una respuesta directa al hardware. Existe la posibilidad de que la variable se guarde en caché en algún lugar. Los datos confidenciales incluso pueden almacenarse en swap :) Si solo le preocupa la RAM, puede jugar con el recolector de basura. En los langs de alto nivel, por lo general, no tiene acceso directo a la memoria, por lo que no es posible controlar este aspecto. Por ejemplo, en .NET hay una clase SecureString que usa interoperabilidad y acceso directo a la memoria.
Si está pensando en proteger contraseñas / administración de claves, puede escribir un código JNI que use una API específica de la plataforma para almacenar las claves de una manera segura y no filtrar los datos en la memoria administrada por la JVM. Por ejemplo, podría almacenar las claves en una página bloqueada en la memoria física y podría evitar que el bus IO acceda a la memoria.
EDITAR: para comentar algunas de las respuestas anteriores, la JVM podría reubicar los objetos en la memoria sin borrar sus ubicaciones anteriores, por lo que, incluso los caracteres char [], bytes, ints y otros tipos de datos "borrables" no son una respuesta si realmente desea asegurarse de que no se almacene información confidencial en la memoria administrada por la JVM o intercambiada en el disco duro.
Total y completamente irrecuperable es algo casi imposible en este día y edad. Cuando normalmente borras algo, lo único que sucede es que el primer punto en tu memoria se vacía. Este primer lugar solía contener la información sobre cuánto tenía que reservarse la memoria para ese programa u otra cosa.
Pero toda la otra información todavía está allí hasta que alguien más la sobrescriba.
de repente, o TinyShredder, o usando CCleaner configurado para el pase Gutmann