Zaszyfrować hasło w plikach konfiguracyjnych? [zamknięte]

Mam program, który odczytuje informacje o serwerze z pliku konfiguracyjnego i chciałby zaszyfrować hasło w tej konfiguracji, które może być odczytane przez mój program i odszyfrowane.

Wymagania:

  • Szyfruj hasło tekstowe, które ma być zapisane w pliku
  • Odszyfruj zaszyfrowane hasło odczytane z pliku z mojego programu

Jakieś zalecenia, jak bym to zrobił? Myślałem o napisaniu własnego algorytmu, ale czuję, że będzie strasznie niepewna siebie.

Author: Artjom B., 2009-07-15

10 answers

Prostym sposobem na to jest użycie szyfrowania opartego na hasłach w Javie. Umożliwia to szyfrowanie i odszyfrowywanie tekstu za pomocą hasła.

Oznacza to w zasadzie zainicjowanie javax.crypto.Cipher algorytmem "AES/CBC/PKCS5Padding" i uzyskanie klucza z javax.crypto.SecretKeyFactory algorytmem "PBKDF2WithHmacSHA512".

Oto przykład kodu (zaktualizowany w celu zastąpienia mniej bezpiecznego wariantu 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);
    }
}

Pozostaje jeden problem: gdzie należy przechowywać hasło, którego używa się do szyfrowania haseł? Można go przechowywać w plik źródłowy i zaciemnić go, ale nie jest to zbyt trudne, aby znaleźć go ponownie. Alternatywnie, możesz podać ją jako właściwość systemową podczas uruchamiania procesu Java (-DpropertyProtectionPassword=...).

Ten sam problem pozostaje, jeśli używasz KeyStore, który również jest chroniony hasłem. Zasadniczo musisz mieć gdzieś jedno hasło główne i jest to dość trudne do ochrony.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-11 21:42:54

Tak, zdecydowanie nie pisz własnego algorytmu. Java ma wiele interfejsów API kryptograficznych.

Jeśli system operacyjny, na którym instalujesz, ma keystore, możesz go użyć do przechowywania kluczy kryptograficznych, które będą potrzebne do zaszyfrowania i odszyfrowania poufnych danych w konfiguracji lub innych plikach.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-15 16:50:45

Sprawdź jasypt , która jest biblioteką oferującą podstawowe możliwości szyfrowania przy minimalnym wysiłku.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-27 12:21:47

Myślę, że najlepszym rozwiązaniem jest upewnienie się, że plik konfiguracyjny (zawierający Twoje hasło) jest dostępny tylko dla określonego konta użytkownika . Na przykład, możesz mieć konkretnego użytkownika aplikacji appuser, do którego tylko zaufane osoby mają hasło (i do którego su).

W ten sposób nie ma irytującej kryptografii i nadal masz bezpieczne hasło.

Edytuj: zakładam, że nie eksportujesz swojej aplikacji konfiguracja poza zaufanym środowiskiem (co nie wiem, czy miałoby sens, biorąc pod uwagę pytanie)

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-15 17:26:24

Cóż, aby rozwiązać problemy z hasłem głównym-najlepszym podejściem jest nie przechowywanie hasła w dowolnym miejscu, aplikacja powinna szyfrować hasła dla siebie - tak, że tylko ona może je odszyfrować. Więc jeśli używam .plik konfiguracyjny wykonałbym następujące czynności: mySettings.config :

EncryptTheseKeys=secretKey, anotherSecret

SecretKey=unprotectedPasswordThatIputHere

AnotherSecret=anotherPass

SomeKey=unprotectedSettingIdontCareAbout

Więc poczytałbym w kluczach, które są wymienione w szyfruj, zastosuj przykład Brodwalls z góry na nich i zapisz je z powrotem do pliku za pomocą jakiegoś znacznika (powiedzmy crypt: ), aby aplikacja wiedziała, że nie robi tego ponownie, wynik będzie wyglądał tak:

EncryptTheseKeys=secretKey, anotherSecret

SecretKey=crypt: ii4jfj304fjhfj934fouh938

AnotherSecret=crypt:jd48jofh48h

SomeKey=unprotectedSettingIdontCareAbout

Upewnij się, że oryginały są w Twoim bezpiecznym miejscu...

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-17 22:18:30

Najważniejsze jest to, że jeśli Twoja aplikacja może zdobyć hasło, to haker z dostępem do skrzynki też może je zdobyć!

Jedynym sposobem na obejście tego problemu jest to, że aplikacja prosi o" hasło główne " na konsoli przy użyciu standardowego wejścia, a następnie używa go do odszyfrowania haseł przechowywanych w pliku. Oczywiście całkowicie uniemożliwia to uruchomienie aplikacji bez nadzoru wraz z OS kiedy się uruchamia.

Jednak nawet przy takim poziomie irytacji, jeśli hakerowi uda się uzyskać dostęp do roota (lub nawet po prostu dostęp jako użytkownik uruchamiający aplikację), może zrzucić pamięć i znaleźć tam hasło.

Chodzi o to, aby nie pozwolić całej firmie na dostęp do serwera produkcyjnego (a tym samym do haseł) i upewnić się, że nie można złamać tego pola!

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-06 19:32:05

Spróbuj użyć metod szyfrowania ESAPIs. Jest łatwy w konfiguracji, a także można łatwo zmienić klucze.

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

Ty

1)encrypt 2) odszyfruj 3) znak 4) unsign 5) haszowanie 6) podpisy oparte na czasie i wiele więcej za pomocą tylko jednej biblioteki.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-05 07:12:33

Zobacz, co jest dostępne w Jetty do przechowywania haseł (lub skrótów) w plikach konfiguracyjnych i zastanów się, czy kodowanie OBF może być dla Ciebie przydatne. Następnie zobacz w źródle, jak to się robi.

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/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-12 16:11:28

W zależności od tego, jak bezpieczne są pliki konfiguracyjne lub jak niezawodna jest Twoja aplikacja, http://activemq.apache.org/encrypted-passwords.html może być dla Ciebie dobrym rozwiązaniem.

Jeśli nie boisz się, że hasło zostanie odszyfrowane, a konfiguracja za pomocą fasoli może być naprawdę prosta. Jeśli jednak potrzebujesz większego bezpieczeństwa, możesz ustawić zmienną środowiskową z tajemnicą i usunąć ją po uruchomieniu. Z tym musisz się martwić o wyłączanie aplikacji / serwera, a nie Automatyczne ponowne uruchamianie aplikacji.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-07 22:02:14

Jeśli używasz java 8 można uniknąć użycia wewnętrznego kodera i dekodera Base64, zastępując

return new BASE64Encoder().encode(bytes);

Z

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

I

return new BASE64Decoder().decodeBuffer(property);

Z

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

Zauważ, że to rozwiązanie nie chroni Twoich danych, ponieważ metody deszyfrowania są przechowywane w tym samym miejscu. To tylko utrudnia złamanie. Głównie unika go wydrukować i pokazać wszystkim przez pomyłkę.

 -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/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-23 17:39:43