it-swarm.com.de

Passwort in Konfigurationsdateien verschlüsseln?

Ich habe ein Programm, das Serverinformationen aus einer Konfigurationsdatei liest und das Kennwort in dieser Konfiguration verschlüsseln möchte, das von meinem Programm gelesen und entschlüsselt werden kann.

Anforderungen:

  • Verschlüsseln Sie das Klartext-Passwort, das in der Datei gespeichert werden soll
  • Entschlüsseln Sie das verschlüsselte Passwort, das aus der Datei aus meinem Programm eingelesen wurde

Irgendwelche Empfehlungen, wie ich das machen würde? Ich habe darüber nachgedacht, meinen eigenen Algorithmus zu schreiben, aber ich denke, es wäre schrecklich unsicher.

125
Petey B

Eine einfache Möglichkeit hierfür ist die Verwendung der kennwortbasierten Verschlüsselung in Java. Auf diese Weise können Sie einen Text mit einem Kennwort verschlüsseln und entschlüsseln.

Dies bedeutet im Grunde, einen javax.crypto.Cipher Mit dem Algorithmus "AES/CBC/PKCS5Padding" Zu initialisieren und einen Schlüssel von javax.crypto.SecretKeyFactory Mit dem Algorithmus "PBKDF2WithHmacSHA512" Abzurufen.

Hier ist ein Codebeispiel (aktualisiert, um die weniger sichere MD5-basierte Variante zu ersetzen):

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

Ein Problem bleibt bestehen: Wo sollten Sie das Kennwort speichern, mit dem Sie die Kennwörter verschlüsseln? Sie können es in der Quelldatei speichern und verschleiern, aber es ist nicht zu schwer, es wieder zu finden. Alternativ können Sie es als Systemeigenschaft angeben, wenn Sie den Java process (-DpropertyProtectionPassword=...) Starten.

Das gleiche Problem bleibt bestehen, wenn Sie den KeyStore verwenden, der ebenfalls durch ein Kennwort geschützt ist. Grundsätzlich müssen Sie irgendwo ein Hauptkennwort haben, und es ist ziemlich schwer zu schützen.

163

Ja, schreibe definitiv keinen eigenen Algorithmus. Java hat viele Kryptographie-APIs.

Wenn das Betriebssystem, auf dem Sie installieren, über einen Schlüsselspeicher verfügt, können Sie darin Ihre Kryptoschlüssel speichern, die Sie zum Ver- und Entschlüsseln der vertraulichen Daten in Ihrer Konfiguration oder in anderen Dateien benötigen.

20
JeeBee

Schauen Sie sich jasypt an, eine Bibliothek, die grundlegende Verschlüsselungsfunktionen mit minimalem Aufwand bietet.

18
Christophe

Ich denke, der beste Ansatz ist es, sicherzustellen, dass Ihre Konfigurationsdatei (die Ihr Passwort enthält) nur für ein bestimmtes Benutzerkonto zugänglich ist . Beispielsweise könnten Sie einen anwendungsspezifischen Benutzer appuser haben, für den nur vertrauenswürdige Personen das Kennwort haben (und für den sie su).

Auf diese Weise entsteht kein lästiger Aufwand für die Kryptografie, und Sie haben immer noch ein sicheres Kennwort.

BEARBEITEN: Ich gehe davon aus, dass Sie Ihre Anwendungskonfiguration nicht außerhalb einer vertrauenswürdigen Umgebung exportieren (was angesichts der gestellten Frage sicher keinen Sinn ergibt).

16
oxbow_lakes

Um die Probleme des Master-Passworts zu lösen, ist es am besten, das Passwort nirgendwo zu speichern. Die Anwendung sollte Passwörter für sich selbst verschlüsseln, damit nur sie entschlüsselt werden können. Wenn ich also eine .config-Datei verwenden würde, würde ich Folgendes tun: mySettings.config:

encryptTheseKeys = secretKey, anotherSecret

secretKey = unprotectedPasswordThatIputHere

anotherSecret = anotherPass

someKey = unprotectedSettingIdontCareAbout

ich würde also die Schlüssel einlesen, die in den encryptTheseKeys erwähnt werden, das Brodwalls-Beispiel von oben auf sie anwenden und sie mit einer Markierung in die Datei zurückschreiben (sagen wir crypt:) Wenn die Anwendung weiß, dass sie es nicht noch einmal tun soll, sieht die Ausgabe folgendermaßen aus:

encryptTheseKeys = secretKey, anotherSecret

secretKey = crypt: ii4jfj304fjhfj934fouh938

anotherSecret = crypt: jd48jofh48h

someKey = unprotectedSettingIdontCareAbout

Bewahren Sie die Originale an einem sicheren Ort auf ...

4
user1007231

Der große Punkt, und der Elefant im Raum und all das, ist, dass wenn Ihre Anwendung das Passwort erhalten kann, ein Hacker mit Zugriff auf die Box auch darauf zugreifen kann!

Die einzige Möglichkeit, dies zu umgehen, besteht darin, dass die Anwendung über die Standardeingabe nach dem "Hauptkennwort" auf der Konsole fragt und dieses verwendet, um die in der Datei gespeicherten Kennwörter zu entschlüsseln. Dies macht es natürlich völlig unmöglich, die Anwendung zusammen mit dem Betriebssystem beim Booten unbeaufsichtigt zu starten.

Wenn ein Hacker jedoch selbst mit diesem Ärger Root-Zugriff erhält (oder sogar nur als Benutzer, der Ihre Anwendung ausführt), könnte er den Speicher entleeren und dort das Kennwort finden.

Das Wichtigste ist, dass nicht das gesamte Unternehmen Zugriff auf den Produktionsserver (und damit auf die Passwörter) hat und dass es unmöglich ist, diese Box zu knacken!

4
stolsvik

Sehen Sie sich an, was in Jetty zum Speichern von Kennwörtern (oder Hashes) in Konfigurationsdateien verfügbar ist, und prüfen Sie, ob die OBF-Codierung für Sie nützlich sein könnte. Dann sehen Sie in der Quelle, wie es gemacht wird.

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

Versuchen Sie es mit ESAPIs-Verschlüsselungsmethoden. Es ist einfach zu konfigurieren und Sie können auch einfach Ihre Schlüssel ändern.

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

Du

1) verschlüsseln 2) entschlüsseln 3) signieren 4) unsignieren 5) hashen 6) zeitbasierte signaturen und vieles mehr mit nur einer bibliothek.

1
Rohit Salecha

Abhängig davon, wie sicher Sie die Konfigurationsdateien benötigen oder wie zuverlässig Ihre Anwendung ist, ist http://activemq.Apache.org/encrypted-passwords.html möglicherweise eine gute Lösung für Sie.

Wenn Sie keine Angst haben, dass das Kennwort entschlüsselt wird, und es sehr einfach sein kann, den Kennwortschlüssel mithilfe einer Bean zu speichern. Wenn Sie jedoch mehr Sicherheit benötigen, können Sie eine Umgebungsvariable mit dem Geheimnis festlegen und nach dem Start entfernen. Hiermit müssen Sie sich Sorgen machen, dass die Anwendung/der Server ausfällt und die Anwendung nicht automatisch neu gestartet wird.

0
CPrescott