Un moyen simple de le faire est d'utiliser le cryptage basé sur le mot de passe en Java. Cela vous permet de crypter et de décrypter un texte à l'aide d'un mot de passe.
Cela signifie essentiellement initialiser un javax.crypto.Cipher
algorithme with "AES/CBC/PKCS5Padding"
et obtenir une clé javax.crypto.SecretKeyFactory
avec l' "PBKDF2WithHmacSHA512"
algorithme.
Voici un exemple de code (mis à jour pour remplacer la variante la moins sécurisée 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);
}
}
Un problème demeure: 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 le masquer, mais il n'est pas trop difficile de le retrouver. Vous pouvez également le donner en tant que propriété 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'un mot de passe principal quelque part, et c'est assez difficile à protéger.
Oui, n'écrivez certainement pas votre propre algorithme. Java possède de nombreuses API de cryptographie.
Si le système d'exploitation sur lequel vous installez dispose d'un fichier de clés, 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.
la source
Découvrez jasypt , une bibliothèque offrant des capacités de cryptage de base avec un minimum d'effort.
la source
Je pense que la meilleure approche est de s'assurer que votre fichier de configuration (contenant votre mot de passe) n'est accessible qu'à un compte utilisateur spécifique . Par exemple, vous pouvez avoir un utilisateur spécifique
appuser
à une application dont seules les personnes de confiance ont le mot de passe (et auquel ellessu
doivent).De cette façon, il n'y a pas de frais généraux de cryptographie ennuyeux et vous avez toujours un mot de passe sécurisé.
EDIT: Je suppose que vous n'exportez pas la configuration de votre application en dehors d'un environnement de confiance (ce qui, je ne suis pas sûr, aurait du sens, étant donné la question)
la source
Eh bien, pour résoudre les problèmes de mot de passe principal - la meilleure approche est de ne pas stocker le mot de passe n'importe où, l'application doit chiffrer les mots de passe pour elle-même - afin qu'elle seule puisse les déchiffrer. Donc, si j'utilisais un fichier .config, je ferais ce qui suit, mySettings.config :
donc je lirais les clés mentionnées dans encryptTheseKeys, appliquerais l'exemple Brodwalls ci-dessus et les réécrirais dans le fichier avec un marqueur d'une sorte (disons crypt :) pour que l'application sache de ne pas le faire encore une fois, la sortie ressemblerait à ceci:
Assurez-vous simplement de conserver les originaux dans votre propre endroit sécurisé ...
la source
Le gros point, et l'éléphant dans la salle et tout ça, c'est que si votre application peut obtenir le mot de passe, alors un hacker ayant accès à la boîte peut aussi s'en emparer!
Le seul moyen de contourner ce problème est que l'application demande le "mot de passe principal" 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 le démarrage de l'application sans surveillance avec le système d'exploitation au démarrage.
Cependant, même avec ce niveau de gêne, si un pirate parvient à obtenir un accès root (ou même simplement un 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 à s'assurer, c'est de ne pas laisser toute l'entreprise avoir accès au serveur de production (et donc aux mots de passe), et de s'assurer qu'il est impossible de casser cette boîte!
la source
Essayez d'utiliser les méthodes de chiffrement ESAPI. Il est facile à configurer et vous pouvez également changer facilement vos clés.
http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/org/owasp/esapi/Encryptor.html
Tu
1) crypter 2) décrypter 3) signer 4) non signer 5) hacher 6) signatures basées sur l'heure et bien plus encore avec une seule bibliothèque.
la source
Voyez ce qui est disponible dans Jetty pour stocker le mot de passe (ou les hachages) dans les fichiers de configuration et déterminez si l'encodage OBF peut vous être utile. Ensuite, voyez dans la source comment cela se fait.
http://www.eclipse.org/jetty/documentation/current/configuring-security-secure-passwords.html
la source
Selon la sécurité dont vous avez besoin 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 du déchiffrement du mot de passe et que cela peut être très simple à configurer en utilisant un bean pour stocker la clé de mot de passe. Cependant, si vous avez besoin de plus de sécurité, vous pouvez définir une variable d'environnement avec le secret et la supprimer après le lancement. Avec cela, vous devez vous soucier de la panne de l'application / du serveur et non du redémarrage automatique de l'application.
la source
Si vous utilisez java 8, l'utilisation de l'encodeur et du décodeur internes 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 car les méthodes de décryptage sont stockées au même endroit. Cela rend simplement plus difficile la rupture. Principalement, cela évite de l'imprimer et de le montrer à tout le monde par erreur.
la source