2008-12-03 18 views
13

Estamos ocupados desarrollando un servicio web Java para un cliente. Hay dos opciones posibles:Java: cifrar/descifrar el nombre de usuario y la contraseña de un archivo de configuración

  • Almacene el nombre de usuario/contraseña encriptados en el cliente del servicio web. Leer desde una configuración archivo en el lado del cliente, descifrar y enviar.

  • Almacene el nombre de usuario/contraseña encriptados en el servidor web. Leer desde una configuración archivo en el servidor web, descifrar y utilizar en el servicio web.

El nombre de usuario/contraseña es utilizado por el servicio web para acceder a una aplicación de terceros.

El cliente ya tiene clases que proporcionan esta funcionalidad, pero este enfoque implica enviar el nombre de usuario/contraseña en forma clara (aunque dentro de la intranet). Preferirían almacenar la información. dentro del servicio web pero realmente no quieren pagar por algo que ya tienen. (La seguridad no es una gran consideración porque solo está dentro de su intranet).

Necesitamos algo rápido y fácil en Java.

¿Alguna recomendación?

El servidor es Tomkat 5.5. El servicio web es Axis2.

  • ¿Qué paquete de cifrado/descifrado deberíamos usar?
  • ¿Qué tal un almacén de claves?
  • ¿Qué mecanismo de configuración deberíamos usar?
  • ¿Será fácil de implementar?

Respuesta

18

Estar en la intranet ciertamente no justifica el despido de la seguridad. La mayoría del daño infligido a la información es por personas internas. Mire el valor de lo que se está protegiendo y preste la debida consideración a la seguridad.

Parece que hay una aplicación de terceros, para la cual tiene un conjunto de credenciales, y algunos clientes que efectivamente comparten esta identidad cuando utilizan la aplicación de terceros. Si ese es el caso, recomiendo el siguiente enfoque.

No distribuya la contraseña de terceros más allá de su servidor web.

La forma más segura de hacerlo es proporcionándola a la aplicación web de forma interactiva. Esto podría ser ServletContextListener que solicita la contraseña cuando se inicia la aplicación, o una página en la aplicación para que un administrador pueda ingresarla a través de un formulario. La contraseña se almacena en ServletContext y se utiliza para autenticar solicitudes al servicio de terceros.

Un paso atrás en seguridad es almacenar la contraseña en el sistema de archivos del servidor para que solo pueda ser leída por el usuario que ejecuta el servidor. Esto depende de los permisos del sistema de archivos del servidor para la protección.

Intentar almacenar una forma cifrada de la contraseña, en el cliente o en el servidor, es simplemente retroceder un paso. Caes en una regresión infinita cuando tratas de proteger un secreto con otro secreto.

Además, los clientes deben autenticarse en el servidor.Si el cliente es interactivo, solicite a los usuarios que ingresen una contraseña. El servidor puede decidir si ese usuario está autorizado para acceder al servicio de terceros. Si el cliente no es interactivo, la siguiente mejor seguridad es proteger la contraseña del cliente utilizando los permisos del sistema de archivos.

Para proteger las credenciales de los clientes, el canal entre el cliente y su servidor web debe estar protegido con SSL. Aquí, operar en una intranet es ventajoso, porque puede usar un certificado autofirmado en el servidor.

Si almacena contraseñas en un archivo, colóquelas en un archivo por sí mismas; hace que la necesidad de administrar permisos sea más llamativa y minimiza la necesidad de que muchos usuarios editen ese archivo y vean la contraseña.

24

Como entiendo de todos modos para llamar al servicio web de terceros, pasas la contraseña como texto sin formato y no hay certificados de seguridad implicados.

Entonces yo diría que el enfoque más fácil sería almacenar la contraseña en formato cifrado (a través del mecanismo de cifrado de Java) cuando la clave de cifrado/descifrado está codificada en el código.

Definitivamente lo almacenaría en el lado del servidor (sistema de archivos o db) en lugar de distribuirlo y mantenerlo en los clientes múltiples.

Aquí es cómo podría trabajar con "DES" cifrado:

// only the first 8 Bytes of the constructor argument are used 
// as material for generating the keySpec 
DESKeySpec keySpec = new DESKeySpec("YourSecr".getBytes("UTF8")); 
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 
SecretKey key = keyFactory.generateSecret(keySpec); 
sun.misc.BASE64Encoder base64encoder = new BASE64Encoder(); 
sun.misc.BASE64Decoder base64decoder = new BASE64Decoder(); 
......... 

// ENCODE plainTextPassword String 
byte[] cleartext = plainTextPassword.getBytes("UTF8");  

Cipher cipher = Cipher.getInstance("DES"); // cipher is not thread safe 
cipher.init(Cipher.ENCRYPT_MODE, key); 
String encrypedPwd = base64encoder.encode(cipher.doFinal(cleartext)); 
// now you can store it 
...... 

// DECODE encryptedPwd String 
byte[] encrypedPwdBytes = base64decoder.decodeBuffer(encryptedPwd); 

Cipher cipher = Cipher.getInstance("DES");// cipher is not thread safe 
cipher.init(Cipher.DECRYPT_MODE, key); 
byte[] plainTextPwdBytes = (cipher.doFinal(encrypedPwdBytes)); 
+0

dónde viene "su frase clave secreta" vienen? Si esa fuente es segura, ¿por qué no usarla para contener la contraseña actual? – erickson

+0

Como mencioné, la frase clave está codificada en clase Java, alternativamente podría almacenarse en la base de datos. Usar la contraseña en sí requeriría recompilar el código cada vez que se cambie la contraseña. –

+3

cualquiera que sea capaz de obtener acceso al archivo también puede obtener acceso a su código y descompilarlo (o simplemente usarlo) para obtener la clave. Microsoft intentó algo similar para proteger el SAM y se rompió casi de inmediato. – frankodwyer

Cuestiones relacionadas