在配置文件中加密密码? [英] Encrypt Password in Configuration Files?

查看:154
本文介绍了在配置文件中加密密码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序从配置文件中读取服务器信息,并希望对该配置中的密码进行加密,可以由我的程序读取并解密。



要求:




  • 加密明文密码存储在文件中

  • 解密加密密码从我的程序的文件



任何关于我将如何做这个的建议?我正在考虑编写自己的算法,但我觉得这将是非常不安全的。

解决方案

这样做的一个简单方法是在Java中使用基于密码的加密。这使您可以使用密码加密和解密文本。



这基本上意味着初始化一个 javax.crypto.Cipher 与算法AES / CBC / PKCS5Padding并从 javax.crypto.SecretKeyFactory code>PBKDF2WithHmacSHA512算法。



这是一个代码示例(更新以替换不太安全的基于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异常{
String password = System.getProperty(password);
if(password == null){
throw new IllegalArgumentException(Run with -Dpassword =< password>);
}

// salt(可能)可以与加密数据一起存储
byte [] salt = new String(12345678)。getBytes();

//减少启动时间,减少启动时间,并且可以在测试过程中使用,但这也使得暴力攻击者更容易获得
int iterationCount = 40000;
//其他值给我java.security.InvalidKeyException:非法键大小或默认参数
int keyLength = 128;
SecretKeySpec key = createSecretKey(System.getProperty(password)。toCharArray(),
salt,iterationCount,keyLength);

String originalPassword =secret;
System.out.println(原始密码:+ originalPassword);
String encryptedPassword = encrypt(originalPassword,key);
System.out.println(加密密码:+ encryptedPassword);
String decryptptedPassword = decrypt(encryptedPassword,key);
System.out.println(解密密码:+ decryptptedPassword);
}

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);
返回新的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();
返回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];
密码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);
}
}

一个问题依然存在:你用来加密密码?您可以将其存储在源文件中并对其进行模糊处理,但再次找到它并不难。或者,您可以在启动Java进程( -DpropertyProtectionPassword = ... )时将其作为系统属性。



如果您使用也受密码保护的KeyStore,则仍然会出现同样的问题。基本上你需要一个主密码,这很难保护。


I have a program that reads server information from a configuration file and would like to encrypt the password in that configuration that can be read by my program and decrypted.

Requirments:

  • Encrypt plaintext password to be stored in the file
  • Decrypt the encrypted password read in from the file from my program

Any reccomendations on how i would go about doing this? I was thinking of writing my own algorithm but i feel it would be terribly insecure.

解决方案

A simple way of doing this is to use Password Based Encryption in Java. This allows you to encrypt and decrypt a text by using a password.

This basically means initializing a javax.crypto.Cipher with algorithm "AES/CBC/PKCS5Padding" and getting a key from javax.crypto.SecretKeyFactory with the "PBKDF2WithHmacSHA512" algorithm.

Here is a code example (updated to replace the less secure MD5-based variant):

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(System.getProperty("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);
    }
}

One problem remains: Where should you store the password that you use to encrypt the passwords? You can store it in the source file and obfuscate it, but it's not too hard to find it again. Alternatively, you can give it as a system property when you start the Java process (-DpropertyProtectionPassword=...).

The same issue remains if you use the KeyStore, which also is protected by a password. Basically, you will need to have one master password somewhere, and it's pretty hard to protect.

这篇关于在配置文件中加密密码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆