Wachtwoord coderen in configuratiebestanden?

Ik heb een programma dat serverinformatie uit een configuratiebestand leest en wil het wachtwoord in die configuratie versleutelen dat door mijn programma kan worden gelezen en ontsleuteld.

Vereisten:

  • Versleutel het wachtwoord in platte tekst dat in het bestand moet worden opgeslagen
  • Ontsleutel het gecodeerde wachtwoord dat is ingelezen uit het bestand van mijn programma

Enige aanbevelingen over hoe ik dit zou doen? Ik dacht erover om mijn eigen algoritme te schrijven, maar ik denk dat het vreselijk onzeker zou zijn.


Antwoord 1, autoriteit 100%

Een eenvoudige manier om dit te doen is door wachtwoordgebaseerde versleuteling in Java te gebruiken. Hiermee kunt u een tekst coderen en decoderen met een wachtwoord.

Dit betekent in feite het initialiseren van een javax.crypto.Ciphermet algoritme "AES/CBC/PKCS5Padding"en het verkrijgen van een sleutel van javax.crypto.SecretKeyFactorymet het "PBKDF2WithHmacSHA512"algoritme.

Hier is een codevoorbeeld (bijgewerkt om de minder veilige op MD5 gebaseerde variant te vervangen):

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

Er blijft één probleem: waar moet u het wachtwoord opslaan dat u gebruikt om de wachtwoorden te coderen? Je kunt het opslaan in het bronbestand en het verdoezelen, maar het is niet zo moeilijk om het terug te vinden. Als alternatief kunt u het als een systeemeigenschap opgeven wanneer u het Java-proces start (-DpropertyProtectionPassword=...).

Hetzelfde probleem blijft bestaan als u de KeyStore gebruikt, die ook is beveiligd met een wachtwoord. Kortom, je zult ergens één hoofdwachtwoord moeten hebben, en het is vrij moeilijk te beschermen.


Antwoord 2, autoriteit 12%

Bekijk jasypt, een bibliotheek die met minimale inspanning basisversleutelingsmogelijkheden biedt.


Antwoord 3, autoriteit 11%

Ja, schrijf zeker niet je eigen algoritme. Java heeft veel cryptografie-API’s.

Als het besturingssysteem waarop u installeert een sleutelarchief heeft, kunt u dat gebruiken om uw cryptosleutels op te slaan die u nodig heeft om de gevoelige gegevens in uw configuratie of andere bestanden te versleutelen en ontsleutelen.


Antwoord 4, autoriteit 9%

Ik denk dat de beste aanpak is om ervoor te zorgen dat uw configuratiebestand (met uw wachtwoord) alleen toegankelijk is voor een specifiek gebruikersaccount. U kunt bijvoorbeeld een applicatiespecifieke gebruiker appuserhebben waarvoor alleen vertrouwde mensen het wachtwoord hebben (en waaraan zij sutoe).

Op die manier is er geen vervelende cryptografie-overhead en heb je nog steeds een veilig wachtwoord.

BEWERK:Ik ga ervan uit dat u uw applicatieconfiguratie niet exporteert buiten een vertrouwde omgeving (waarvan ik niet zeker weet of dit logisch zou zijn, gezien de vraag)


Antwoord 5, autoriteit 2%

Om de problemen met het hoofdwachtwoord op te lossen – de beste aanpak is om het wachtwoord nergens op te slaan, moet de toepassing wachtwoorden voor zichzelf versleutelen – zodat alleen zij ze kan ontsleutelen. Dus als ik een .config-bestand zou gebruiken, zou ik het volgende doen, mySettings.config:

encryptTheseKeys=secretKey,anotherSecret

secretKey=unprotectedPasswordThatIputHere

anotherSecret=anotherPass

someKey=unprotectedSettingIdontCareAbout

dus ik zou de sleutels inlezen die worden genoemd in de
encryptTheseKeys, pas het Brodwalls-voorbeeld van boven erop toe en
schrijf ze terug naar het bestand met een soort markering (laten we zeggen crypt:) om de toepassing te laten weten het niet nog een keer te doen, de uitvoer ziet er als volgt uit:

encryptTheseKeys=secretKey,anotherSecret

secretKey=crypt:ii4jfj304fjhfj934fouh938

anotherSecret=crypt:jd48jofh48h

someKey=unprotectedSettingIdontCareAbout

Zorg er wel voor dat u de originelen op uw eigen veilige plaats bewaart…


Antwoord 6

Probeer de versleutelingsmethoden van ESAPI’s te gebruiken. Het is eenvoudig te configureren en u kunt ook eenvoudig uw sleutels wijzigen.

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

Jij

1)versleutelen
2) decoderen
3) teken:
4) afmelden
5) hashen
6) op tijd gebaseerde handtekeningen en nog veel meer met slechts één bibliotheek.


Antwoord 7

Bekijk wat er in Jetty beschikbaar is voor het opslaan van wachtwoorden (of hashes) in configuratiebestanden en overweeg of de OBF-codering nuttig voor u kan zijn. Kijk dan in de bron hoe het moet.

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


Antwoord 8

Afhankelijk van hoe veilig je de configuratiebestanden nodig hebt of hoe betrouwbaar je applicatie is, http:// activemq.apache.org/encrypted-passwords.htmlkan een goede oplossing voor je zijn.

Als je niet al te bang bent dat het wachtwoord wordt ontsleuteld en het heel eenvoudig kan zijn om een bean te gebruiken om de wachtwoordsleutel op te slaan. Als u echter meer beveiliging nodig heeft, kunt u een omgevingsvariabele met het geheim instellen en deze na het starten verwijderen. Hiermee hoeft u zich geen zorgen te maken dat de applicatie / server uitvalt en niet dat de applicatie niet automatisch opnieuw wordt gestart.


Antwoord 9

Als u java 8gebruikt, kan het gebruik van de interne Base64-encoder en -decoder worden vermeden door deze te vervangen

return new BASE64Encoder().encode(bytes);

met

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

en

return new BASE64Decoder().decodeBuffer(property);

met

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

Houd er rekening mee dat deze oplossing uw gegevens niet beschermt, aangezien de ontsleutelingsmethoden op dezelfde plaats worden opgeslagen. Het maakt het alleen maar moeilijker om te breken. Het vermijdt vooral om het af te drukken en het per ongeluk aan iedereen te laten zien.

Other episodes