2008-09-23 16 views
11

¿Hay alguna forma en Java para eliminar datos (por ejemplo, un valor variable, objeto) y asegúrese 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.destrucción irrecuperable de datos en Java

Respuesta

19

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 quiere decir que una vieja copia (unzeroed) del objeto no será dejado en una página de intercambio sin usar, lo que podría persistir en los reinicios.
  • Tampoco impide que alguien adjunte 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 de pila.
1

No, a menos que tenga 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.

3

No se borra nada, simplemente es 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 caso de acceso directo a la memoria, siempre hay algo que leer, pero puede ser basura y no tiene sentido.

2

Al establecer su Objeto como nulo 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 recolectada y no tiene una fuga de memoria!)

Una vez que está marcado como listo para la recolecció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. Perfile su aplicación y mire el objeto y su identificación y puede ver lo que está haciendo referencia a ella. Java proporciona VisualVM con 1.6.0_07 y superior o puede usar NetBeans

0

Total y completamente irrecuperable es algo casi imposible en esta época. Cuando normalmente elimina algo, lo único que ocurre es que el primer punto en su 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 aún está allí hasta que sea sobrescrita por otra persona.

i sudgest ya sea TinyShredder, o el uso de CCleaner establece en el paso Gutmann

2

Como dijo zacherates, cero fuera de los campos sensibles de su objeto antes de retirar las referencias a ella. 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.

+0

Claro usted _CAN_ pone a cero el contenido de una cadena, suponiendo que no hay un administrador de seguridad y la voluntad de usar demasiada reflexión. Ok, tal vez no es la respuesta más simple. :) – jsight

1

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.

1

Los datos primitivos (byte, char, int, double) y sus matrices (byte [], ...) se pueden borrar escribiendo en ellos nuevos contenidos aleatorios.

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.

P.S. Si hablamos de contraseñas, es mejor usar funciones hash criptográficas fuertes (MD5, SHA1, ...) y nunca trabajar con contraseñas en texto claro.

1

Si está pensando en proteger contraseñas/administración de claves, podría escribir un código JNI que use la API específica de la plataforma para almacenar las claves de 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 sobre algunas de las respuestas anteriores, la JVM podría reubicar sus objetos en la memoria sin borrar sus ubicaciones anteriores, por lo que, incluso char [], bytes, ints y otros tipos de datos "borrables" no son Responda si realmente desea asegurarse de que no se almacene información confidencial en la memoria administrada por la JVM o que se haya intercambiado en el disco duro.

9

Almacene datos confidenciales en una matriz y luego "agúrelos" tan pronto como sea posible.

Cualquier dato en la RAM se puede copiar al disco mediante 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 luchar por la siguiente

  • mantener la ventana de tiempo un secreto es presente en la memoria tan corta como posible
  • tener cuidado con las tuberías IO (por ejemplo, BufferedInputStream) que internamente datos del buffer
  • mantienen las referencias al secreto en la pila y fuera del montón
  • no utilizan tipos inmutables, como String, para mantener secretos

Las API criptográficas en Java utilizan este enfoque, y cualquier API que cree debe ser compatible. Por ejemplo, KeyStore.load permite a una persona que llama para borrar una contraseña char[], y cuando la llamada se completa, al igual que el KeySpec for password-based encryption.

Lo ideal sería utilizar un bloque finally 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'); 
} 
Cuestiones relacionadas