Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中加密和解密属性文件值_Java_Encryption - Fatal编程技术网

在java中加密和解密属性文件值

在java中加密和解密属性文件值,java,encryption,Java,Encryption,我正在寻找一种在配置文件中加密密码的方法 这是由Java程序读取的。目前,我在 来自文本文件的密码,但这会使密码保持正确 如果有人要查看配置文件,请公开 我在考虑构建一个简单的类,用户可以在其中输入 他们想要的密码,得到加密版本的密码,然后 将加密版本粘贴到配置文本文件中。然后 应用程序将读取加密的密码,然后将密码解密回来 然后继续前进 我在使用字符串-->encrytped bytes-->时遇到问题 转换 我正在使用内置的java安全类来实现这段代码。 以下是一些示例测试代码: //

我正在寻找一种在配置文件中加密密码的方法 这是由Java程序读取的。目前,我在 来自文本文件的密码,但这会使密码保持正确 如果有人要查看配置文件,请公开

我在考虑构建一个简单的类,用户可以在其中输入 他们想要的密码,得到加密版本的密码,然后 将加密版本粘贴到配置文本文件中。然后 应用程序将读取加密的密码,然后将密码解密回来 然后继续前进

我在使用字符串-->encrytped bytes-->时遇到问题 转换

我正在使用内置的java安全类来实现这段代码。 以下是一些示例测试代码:

    // Reads password from config file
String password = ScriptConfig.getString( "password" );

// Generate Key
KeyGenerator kg = KeyGenerator.getInstance("DES");
Key key = kg.generateKey();

// Create Encryption cipher
Cipher cipher = Cipher.getInstance( "DES" );
cipher.init( Cipher.ENCRYPT_MODE, key );

// Encrypt password
byte[] encrypted = cipher.doFinal( password.getBytes() );

// Create decryption cipher
cipher.init( Cipher.DECRYPT_MODE, key );
byte[] decrypted = cipher.doFinal( encrypted );

// Convert byte[] to String
String decryptedString = new String(decrypted);

System.out.println("password: " + password);
System.out.println("encrypted: " + encrypted);
System.out.println("decrypted: " + decryptedString);

// Read encrypted string from config file
String encryptedPassword = ScriptConfig.getString( "encryptedPassword"
);

// Convert encryptedPassword string into byte[]
byte[] encryptedPasswordBytes = new byte[1024];
encryptedPasswordBytes = encryptedPassword.getBytes();

// Decrypt encrypted password from config file
byte[] decryptedPassword = cipher.doFinal( encryptedPasswordBytes );//error here

System.out.println("encryptedPassword: " + encryptedPassword);
System.out.println("decryptedPassword: " + decryptedPassword);


The config file has the following variables:
password=password
encryptedPassword=[B@2a4983


When I run the code, I get the following output:
password: passwd
encrypted: [B@2a4983
decrypted: passwd
javax.crypto.IllegalBlockSizeException: Input length must be multiple
of 8 when decrypting with padded cipher
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.DESCipher.engineDoFinal(Da shoA12275)
at javax.crypto.Cipher.doFinal(DashoA12275)
at com.sapient.fbi.uid.TestEncryption.main(TestEncryp tion.java:4
关于我用来执行此操作的错误、结构或过程,有什么帮助吗 那太好了。谢谢

我在字符串-->加密字节-->字符串转换方面遇到问题

我将通过base64 en/解码器填充字节数组,这样您就必须在ASCII(一个子集)中保留只包含字符的字符串,这将限制您的麻烦。例如,查看并用调用org.apache.commons.codec.binary.Base64类中的一个静态方法替换您的
新字符串(已解密)


除此之外,我认为您最终想要做的不是严格地“加密”密码,而是只存储密码的散列,上面已经讨论过了。

一个非常简单的解决方案是使用Base64编码,请参阅下面的代码片段:-

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

...

private String encode(String str) {
    BASE64Encoder encoder = new BASE64Encoder();
    str = new String(encoder.encodeBuffer(str.getBytes()));
    return str;
}

private String decode(String str) {
    BASE64Decoder decoder = new BASE64Decoder();
    try {
        str = new String(decoder.decodeBuffer(str));
    } catch (IOException e) {
        e.printStackTrace();
    }       
    return str;
}

...
看一看。它已经为你完成了繁重的工作。具体来说,
org.jasypt.encryption.pbe.StandardPBEStringEncryptor
org.jasypt.properties.PropertyValueEncryptionUtils

创建加密程序:

SimplePBEConfig config = new SimplePBEConfig(); 
config.setAlgorithm("PBEWithMD5AndTripleDES");
config.setKeyObtentionIterations(1000);
config.setPassword("propertiesFilePassword");

StandardPBEStringEncryptor encryptor = new org.jasypt.encryption.pbe.StandardPBEStringEncryptor();
encryptor.setConfig(config);
encryptor.initialize();
然后使用
PropertyValueEncryptionUtils
加密/解密值:

PropertyValueEncryptionUtils.encrypt(value, encryptor);
PropertyValueEncryptionUtils.decrypt(encodedValue, encryptor)
注意编码值将以ENC(开始,以
结束)
结束,因此很容易判断文件中的属性是否加密

另外,请注意,用于
config.setPassword()
的密码不是要存储在属性文件中的编码密码。相反,它是加密/解密存储值的密码。此密码是什么以及如何设置由您决定。我默认为读取属性文件的任何对象的完全限定类名


最后,如果您正在使用Spring,Jasypt有一个
EncryptablePropertyPlaceHolderConfigure
类,您可以使用该类加载属性文件,并在SpringXML文件中使用
${foo}
语法对DB密码等进行变量替换。

以下是一些在Java中使用AES加密或解密的帮助:

public static final String AES = "AES";

/**
 * Encrypt a value and generate a keyfile.
 * If the keyfile is not found, then a new one will be created.
 * 
 * @throws GeneralSecurityException
 * @throws IOException if an I/O error occurs
 */
public static String encrypt(String value, File keyFile)
        throws GeneralSecurityException, IOException {
    if (!keyFile.exists()) {
        KeyGenerator keyGen = KeyGenerator.getInstance(CryptoUtils.AES);
        keyGen.init(128);
        SecretKey sk = keyGen.generateKey();
        FileWriter fw = new FileWriter(keyFile);
        fw.write(byteArrayToHexString(sk.getEncoded()));
        fw.flush();
        fw.close();
    }

    SecretKeySpec sks = getSecretKeySpec(keyFile);
    Cipher cipher = Cipher.getInstance(CryptoUtils.AES);
    cipher.init(Cipher.ENCRYPT_MODE, sks, cipher.getParameters());
    byte[] encrypted = cipher.doFinal(value.getBytes());
    return byteArrayToHexString(encrypted);
}

/**
 * Decrypt a value.
 * 
 * @throws GeneralSecurityException
 * @throws IOException if an I/O error occurs
 */
public static String decrypt(String message, File keyFile)
        throws GeneralSecurityException, IOException {
    SecretKeySpec sks = getSecretKeySpec(keyFile);
    Cipher cipher = Cipher.getInstance(CryptoUtils.AES);
    cipher.init(Cipher.DECRYPT_MODE, sks);
    byte[] decrypted = cipher.doFinal(hexStringToByteArray(message));
    return new String(decrypted);
}

private static SecretKeySpec getSecretKeySpec(File keyFile)
        throws NoSuchAlgorithmException, IOException {
    byte[] key = readKeyFile(keyFile);
    SecretKeySpec sks = new SecretKeySpec(key, CryptoUtils.AES);
    return sks;
}

private static byte[] readKeyFile(File keyFile)
        throws FileNotFoundException {
    Scanner scanner = new Scanner(keyFile).useDelimiter("\\Z");
    String keyValue = scanner.next();
    scanner.close();
    return hexStringToByteArray(keyValue);
}

private static String byteArrayToHexString(byte[] b) {
    StringBuffer sb = new StringBuffer(b.length * 2);
    for (int i = 0; i < b.length; i++) {
        int v = b[i] & 0xff;
        if (v < 16) {
            sb.append('0');
        }
        sb.append(Integer.toHexString(v));
    }
    return sb.toString().toUpperCase();
}

private static byte[] hexStringToByteArray(String s) {
    byte[] b = new byte[s.length() / 2];
    for (int i = 0; i < b.length; i++) {
        int index = i * 2;
        int v = Integer.parseInt(s.substring(index, index + 2), 16);
        b[i] = (byte) v;
    }
    return b;
}
公共静态最终字符串AES=“AES”;
/**
*加密值并生成密钥文件。
*如果找不到密钥文件,则将创建一个新的密钥文件。
* 
*@throws-GeneralSecurityException
*@在发生I/O错误时引发IOException
*/
公共静态字符串加密(字符串值、文件密钥文件)
抛出GeneralSecurityException,IOException{
如果(!keyFile.exists()){
KeyGenerator keyGen=KeyGenerator.getInstance(CryptoUtils.AES);
密钥初始化(128);
SecretKey sk=keyGen.generateKey();
FileWriter fw=新的FileWriter(密钥文件);
write(byteArrayToHexString(sk.getEncoded());
fw.flush();
fw.close();
}
SecretKeySpec sks=getSecretKeySpec(keyFile);
Cipher Cipher=Cipher.getInstance(CryptoUtils.AES);
cipher.init(cipher.ENCRYPT_模式,sks,cipher.getParameters());
byte[]encrypted=cipher.doFinal(value.getBytes());
返回byteArrayTohextString(加密);
}
/**
*解密一个值。
* 
*@throws-GeneralSecurityException
*@在发生I/O错误时引发IOException
*/
公共静态字符串解密(字符串消息、文件密钥文件)
抛出GeneralSecurityException,IOException{
SecretKeySpec sks=getSecretKeySpec(keyFile);
Cipher Cipher=Cipher.getInstance(CryptoUtils.AES);
cipher.init(cipher.DECRYPT_模式,sks);
byte[]decrypted=cipher.doFinal(hexStringToByteArray(message));
返回新字符串(已解密);
}
私有静态SecretKeySpec getSecretKeySpec(File keyFile)
抛出NoSuchAlgorithmException,IOException{
字节[]键=读取键文件(键文件);
SecretKeySpec sks=新的SecretKeySpec(key,CryptoUtils.AES);
返回sks;
}
私有静态字节[]readKeyFile(文件keyFile)
抛出FileNotFoundException{
Scanner Scanner=新的扫描仪(密钥文件)。使用分隔符(\\Z”);
字符串keyValue=scanner.next();
scanner.close();
返回hexStringToByteArray(keyValue);
}
私有静态字符串byteArrayToHexString(字节[]b){
StringBuffer sb=新的StringBuffer(b.长度*2);
for(int i=0;i

只需调用appropiate方法。

如果您的应用程序位于客户机上,则可以对其进行破解并发现解密密钥。一旦发生这种情况,你也可以使用纯文本。真正保护该工作流的唯一方法是在安全的服务器上进行解密。你想解决什么问题导致你尝试这个?(为什么需要这样存储密码?)我不想在配置文件中以纯文本形式存储密码。@user234194:你没有抓住要点。如果将解密密钥存储在客户端上,则该密钥不安全且