Cifrar Contraseña en Archivos de configuración? [cerrado]


Tengo un programa que lee la información del servidor de un archivo de configuración y me gustaría cifrar la contraseña en esa configuración que puede ser leída por mi programa y descifrada.

Requisitos:

  • Cifrar la contraseña de texto plano que se almacenará en el archivo
  • Descifrar la contraseña cifrada leída desde el archivo de mi programa

¿Alguna recomendación sobre cómo haría esto? Estaba pensando en escribir mi propio algoritmo pero siento que sería terriblemente inseguro.

Author: Artjom B., 2009-07-15

10 answers

Una forma sencilla de hacer esto es usar Cifrado Basado en Contraseña en Java. Esto le permite cifrar y descifrar un texto mediante una contraseña.

Esto básicamente significa inicializar un javax.crypto.Cipher con el algoritmo "AES/CBC/PKCS5Padding" y obtener una clave de javax.crypto.SecretKeyFactory con el algoritmo "PBKDF2WithHmacSHA512".

Aquí hay un ejemplo de código (actualizado para reemplazar la variante basada en MD5 menos segura):

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

public class ProtectedConfigFile {

    public static void main(String[] args) throws Exception {
        String password = System.getProperty("password");
        if (password == null) {
            throw new IllegalArgumentException("Run with -Dpassword=<password>");
        }

        // The salt (probably) can be stored along with the encrypted data
        byte[] salt = new String("12345678").getBytes();

        // Decreasing this speeds down startup time and can be useful during testing, but it also makes it easier for brute force attackers
        int iterationCount = 40000;
        // Other values give me java.security.InvalidKeyException: Illegal key size or default parameters
        int keyLength = 128;
        SecretKeySpec key = createSecretKey(password.toCharArray(),
                salt, iterationCount, keyLength);

        String originalPassword = "secret";
        System.out.println("Original password: " + originalPassword);
        String encryptedPassword = encrypt(originalPassword, key);
        System.out.println("Encrypted password: " + encryptedPassword);
        String decryptedPassword = decrypt(encryptedPassword, key);
        System.out.println("Decrypted password: " + decryptedPassword);
    }

    private static SecretKeySpec createSecretKey(char[] password, byte[] salt, int iterationCount, int keyLength) throws NoSuchAlgorithmException, InvalidKeySpecException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
        PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterationCount, keyLength);
        SecretKey keyTmp = keyFactory.generateSecret(keySpec);
        return new SecretKeySpec(keyTmp.getEncoded(), "AES");
    }

    private static String encrypt(String property, SecretKeySpec key) throws GeneralSecurityException, UnsupportedEncodingException {
        Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        pbeCipher.init(Cipher.ENCRYPT_MODE, key);
        AlgorithmParameters parameters = pbeCipher.getParameters();
        IvParameterSpec ivParameterSpec = parameters.getParameterSpec(IvParameterSpec.class);
        byte[] cryptoText = pbeCipher.doFinal(property.getBytes("UTF-8"));
        byte[] iv = ivParameterSpec.getIV();
        return base64Encode(iv) + ":" + base64Encode(cryptoText);
    }

    private static String base64Encode(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }

    private static String decrypt(String string, SecretKeySpec key) throws GeneralSecurityException, IOException {
        String iv = string.split(":")[0];
        String property = string.split(":")[1];
        Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        pbeCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(base64Decode(iv)));
        return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
    }

    private static byte[] base64Decode(String property) throws IOException {
        return Base64.getDecoder().decode(property);
    }
}

Queda un problema: ¿Dónde debe almacenar la contraseña que utiliza para cifrar las contraseñas? Puedes guardarlo en el archivo de origen y ofuscar, pero no es demasiado difícil de encontrar de nuevo. Alternativamente, puede darle como una propiedad del sistema cuando inicie el proceso Java (-DpropertyProtectionPassword=...).

El mismo problema permanece si utiliza el almacén de claves, que también está protegido por una contraseña. Básicamente, necesitará tener una contraseña maestra en algún lugar, y es bastante difícil de proteger.

 154
Author: Johannes Brodwall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-11 21:42:54

Sí, definitivamente no escribas tu propio algoritmo. Java tiene muchas API de criptografía.

Si el sistema operativo sobre el que está instalando tiene un almacén de claves, puede usarlo para almacenar sus claves criptográficas que necesitará para cifrar y descifrar los datos confidenciales en su configuración u otros archivos.

 20
Author: JeeBee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-15 16:50:45

Echa un vistazo a jasypt, que es una biblioteca que ofrece capacidades básicas de cifrado con el mínimo esfuerzo.

 18
Author: Kaitsu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-27 12:21:47

Creo que el mejor enfoque es asegurarse de que su archivo de configuración (que contiene su contraseña) sea solo accesible para una cuenta de usuario específica. Por ejemplo, es posible que tenga un usuario específico de la aplicación appuser para el que solo las personas de confianza tienen la contraseña (y para el que su).

De esa manera, no hay una sobrecarga de criptografía molesta y todavía tiene una contraseña que es segura.

EDITAR: Estoy asumiendo que usted no está exportando su aplicación configuración fuera de un entorno de confianza (que no estoy seguro tendría ningún sentido, dada la pregunta)

 15
Author: oxbow_lakes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-15 17:26:24

Bien para resolver los problemas de la contraseña maestra - el mejor enfoque es no almacenar la contraseña en cualquier lugar, la aplicación debe cifrar las contraseñas por sí misma - para que solo ella pueda descifrarlas. Así que si yo estaba usando una .archivo de configuración Haría lo siguiente, MySettings.config :

EncryptTheseKeys = SecretKey,anotherSecret

SecretKey = unprotectedPasswordThatIputHere

Othersecret = otherpass

SomeWey=unprotectedSettingIdontCareAbout

Así que leería en las teclas que se mencionan en el encryptTheseKeys, aplicar el ejemplo Brodwalls de arriba en ellos y escríbalos de nuevo en el archivo con un marcador de algún tipo (digamos crypt: ) para que la aplicación sepa que no debe hacerlo de nuevo, la salida se vería así:

EncryptTheseKeys = SecretKey,anotherSecret

SecretKey = crypt: ii4jfj304fjhfj934fouh938

Otro secreto = cripta: jd48jofh48h

SomeWey=unprotectedSettingIdontCareAbout

Solo asegúrese de mantener los originales en su propio lugar seguro...

 4
Author: user1007231,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-17 22:18:30

El gran punto, y el elefante en la habitación y todo eso, es que si su aplicación puede hacerse con la contraseña, entonces un hacker con acceso a la caja puede hacerse con ella también!

La única manera de evitar esto, es que la aplicación pide la "contraseña maestra" en la consola usando la entrada estándar, y luego la usa para descifrar las contraseñas almacenadas en el archivo. Por supuesto, esto hace completamente imposible que la aplicación se inicie desatendida junto con el OS cuando arranca.

Sin embargo, incluso con este nivel de molestia, si un hacker logra obtener acceso de root (o incluso simplemente acceder como el usuario que ejecuta su aplicación), podría volcar la memoria y encontrar la contraseña allí.

Lo que hay que garantizar, es no dejar que toda la empresa tenga acceso al servidor de producción (y por lo tanto a las contraseñas), y asegurarse de que es imposible romper esta caja!

 4
Author: stolsvik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-06 19:32:05

Intente usar métodos de cifrado ESAPIs. Es fácil de configurar y también puede cambiar fácilmente sus claves.

Http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/org/owasp/esapi/Encryptor.html

Usted

1) cifrar 2)descifrar 3)firmar 4) unsign 5) hashing 6) firmas basadas en tiempo y mucho más con una sola biblioteca.

 1
Author: Rohit Salecha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-05 07:12:33

Vea lo que está disponible en Jetty para almacenar contraseñas (o hashes) en archivos de configuración, y considere si la codificación OBF podría ser útil para usted. Luego vea en la fuente cómo se hace.

Http://www.eclipse.org/jetty/documentation/current/configuring-security-secure-passwords.html

 1
Author: Thorbjørn Ravn Andersen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-12 16:11:28

Dependiendo de qué tan seguro necesite los archivos de configuración o qué tan confiable sea su aplicación, http://activemq.apache.org/encrypted-passwords.html puede ser una buena solución para usted.

Si no tiene demasiado miedo de que la contraseña se descifre y puede ser muy simple de configurar usando un bean para almacenar la clave de contraseña. Sin embargo, si necesita más seguridad, puede establecer una variable de entorno con el secreto y eliminarla después del lanzamiento. Con esto usted tiene que preocuparse por el la aplicación / servidor se cae y no la aplicación no se reinicia automáticamente.

 0
Author: CPrescott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-07 22:02:14

Si está utilizando java 8 el uso del codificador y decodificador Base64 interno se puede evitar reemplazando

return new BASE64Encoder().encode(bytes);

Con

return Base64.getEncoder().encodeToString(bytes);

Y

return new BASE64Decoder().decodeBuffer(property);

Con

return Base64.getDecoder().decode(property);

Tenga en cuenta que esta solución no protege sus datos ya que los métodos para descifrar se almacenan en el mismo lugar. Sólo hace que sea más difícil de romper. Principalmente evita imprimirlo y mostrarlo a todo el mundo por error.

 -5
Author: Antonio Raposo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-23 17:39:43