Crypter le mot de passe dans les fichiers de Configuration? [fermé]

j'ai un programme qui lit les informations du serveur à partir d'un fichier de configuration et je voudrais chiffrer le mot de passe dans cette configuration qui peut être lu par mon programme et déchiffré.

requirements:

  • Crypter le mot de passe en clair pour être stockée dans le fichier
  • déchiffrer le mot de passe crypté lu dans le fichier de mon programme

toute recommandation sur la façon dont je me comporterais à ce sujet? Je pensais écrire mon propre algorithme mais je pense que ce serait terriblement peu sûr.

113
demandé sur Artjom B. 2009-07-15 20:47:21

10 réponses

une façon simple de le faire est d'utiliser le cryptage basé sur le mot de passe en Java. Cela vous permet de chiffrer et déchiffrer un texte en utilisant un mot de passe.

cela signifie essentiellement l'initialisation d'un javax.crypto.Cipher avec l'algorithme "AES/CBC/PKCS5Padding" et l'obtention d'une clé de javax.crypto.SecretKeyFactory avec l'algorithme "PBKDF2WithHmacSHA512" .

voici un exemple de code (mis à jour pour remplacer la variante moins sûre basée sur MD5):

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);
    }
}

il reste un problème: Où devez-vous stocker le mot de passe que vous utilisez pour crypter les mots de passe? Vous pouvez le stocker dans le fichier source et l'obscurcir, mais il n'est pas trop difficile de le retrouver. Vous pouvez également l'indiquer comme propriété du système lorsque vous démarrez le processus Java ( -DpropertyProtectionPassword=... ).

le même problème persiste si vous utilisez le KeyStore, qui est également protégé par un mot de passe. Fondamentalement, vous aurez besoin d'avoir un mot de passe maître, quelque part, et c'est assez difficile à protéger.

154
répondu Johannes Brodwall 2018-01-11 21:42:54

Oui, certainement ne pas écrire votre propre algorithme. Java a beaucoup d'API cryptographiques.

si le système D'exploitation sur lequel vous installez a un clavier, vous pouvez l'utiliser pour stocker vos clés de chiffrement dont vous aurez besoin pour chiffrer et déchiffrer les données sensibles de votre configuration ou d'autres fichiers.

20
répondu JeeBee 2009-07-15 16:50:45

Check out jasypt , qui est une bibliothèque offrant des capacités de cryptage de base avec un effort minimal.

18
répondu Kaitsu 2012-06-27 12:21:47

je pense que la meilleure approche est de s'assurer que votre fichier de configuration (contenant votre mot de passe) est uniquement accessible à un compte d'utilisateur spécifique . Par exemple, vous pouvez avoir un utilisateur spécifique à l'application appuser auquel seules les personnes de confiance ont le mot de passe (et auquel ils su ).

de cette façon, il n'y a pas de cryptographie ennuyeuse au-dessus et vous avez toujours un mot de passe qui est sécurisé.

EDIT: je suppose que vous n'exportez pas votre configuration d'application en dehors d'un environnement de confiance (ce qui n'aurait aucun sens, étant donné la question)

15
répondu oxbow_lakes 2009-07-15 17:26:24

bien pour résoudre les problèmes de maître mot de passe - la meilleure approche est de ne pas stocker le mot de passe n'importe où, l'application doit crypter les mots de passe pour lui - même-afin que seul il peut les déchiffrer. Donc, si j'ai été en utilisant un .fichier de configuration je ferais les mySettings suivants, .config :

encryptTheseKeys=secretKey, anotherSecret

secretKey=unprotectedpasswordthatiputhere151930920"

anotherSecret=anotherPass

someKey=unprotectedSettingIdontCareAbout

pour que je lise dans les touches qui sont mentionnées dans le encrypttheskeys, appliquer l'exemple de Brodwalls d'en haut sur eux et les écrire dans le fichier avec un marqueur quelconque (disons crypte: ) pour laisser l'application ne sais pas le faire de nouveau, la sortie devrait ressembler à ceci:

encryptTheseKeys=secretKey, anotherSecret

secretKey= crypte: ii4jfj304fjhfj934fouh938

anotherSecret= crypte: jd48jofh48h

someKey=unprotectedSettingIdontCareAbout

assurez-vous de garder les originaux en lieu sûr...

4
répondu user1007231 2012-01-17 22:18:30

le grand point, et l'éléphant dans la salle et tout cela, est que si votre application peut obtenir le mot de passe, alors un pirate informatique avec accès à la boîte peut obtenir de lui aussi!

le seul moyen de contourner ce problème, c'est que l'application demande le" mot de passe maître " sur la console en utilisant L'entrée Standard, puis l'utilise pour déchiffrer les mots de passe stockés dans le fichier. Bien sûr, cela rend complètement impossible d'avoir le démarrage de l'application sans surveillance avec le système d'exploitation lors du démarrage.

cependant, même avec ce niveau d'ennui, si un hacker parvient à obtenir l'accès root (ou même tout simplement l'accès en tant qu'utilisateur exécutant votre application), il pourrait vider la mémoire et y trouver le mot de passe.

la chose à assurer, est de ne pas laisser l'ensemble de l'entreprise ont accès au serveur de production (et donc aux mots de passe), et s'assurer qu'il est impossible de fissurer cette boîte!

4
répondu stolsvik 2013-10-06 19:32:05

essayez les méthodes de cryptage ESAPIs. Il est facile à configurer et vous pouvez aussi modifier facilement vos clés.

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

vous

1) chiffrement 2)décrypter 3)inscrivez-vous 4)unsign 5)le malaxage 6) signatures basées sur le temps et beaucoup plus avec une seule bibliothèque.

1
répondu Rohit Salecha 2012-12-05 07:12:33

voir ce qui est disponible dans Jetty pour stocker le mot de passe (ou les hashes) dans les fichiers de configuration, et de considérer si L'encodage OBF pourrait être utile pour vous. Puis voir dans la source comment il est fait.

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

1
répondu Thorbjørn Ravn Andersen 2014-12-12 16:11:28

selon la sécurité des fichiers de configuration ou la fiabilité de votre application, http://activemq.apache.org/encrypted-passwords.html peut être une bonne solution pour vous.

si vous n'avez pas trop peur que le mot de passe soit déchiffré et il peut être très simple de configurer en utilisant un bean pour stocker la clé de mot de passe. Toutefois, si vous avez besoin de plus de sécurité, vous pouvez définir une variable d'environnement avec le secret et l'enlever après lancer. Avec cela, vous devez vous soucier de l'application / serveur va vers le bas et pas application pas automatiquement relance.

0
répondu CPrescott 2014-01-07 22:02:14

si vous utilisez java 8 l'utilisation de l'encodeur et du décodeur interne Base64 peut être évitée en remplaçant

return new BASE64Encoder().encode(bytes);

avec

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

et

return new BASE64Decoder().decodeBuffer(property);

avec

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

notez que cette solution ne protège pas vos données comme les méthodes pour décryptage sont stockées au même endroit. Il rend juste plus difficile à briser. Il évite surtout de l'imprimer et de la montrer à tout le monde par erreur.

-5
répondu Antonio Raposo 2015-01-23 17:39:43