我正在寻找一种加密配置文件中密码的方法 正在被Java程序读取。目前,我读了 来自文本文件的密码,但密码保持正确 如果有人要查看配置文件,请打开。
我正在考虑构建一个用户可以输入的简单类 他们想要的密码,然后获得密码的加密版本 将加密版本粘贴到配置文本文件中。那么 应用程序将读取加密密码,解密密码 变成一个字符串,继续前进。
我遇到字符串问题 - >加密字节 - >字符串 转化
我使用内置的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
我正在使用的错误,结构或过程的任何帮助 会很好。感谢。
答案 0 :(得分:12)
看看Jasypt。它已经为你完成了繁重的工作。具体来说,是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有一个EncryptablePropertyPlaceholderConfigurer
类,您可以使用它来加载属性文件并在Spring XML文件中使用${foo}
语法对DB之类的内容进行变量替换密码。
答案 1 :(得分:4)
以下是在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;
}
只需调用适当的方法。
答案 2 :(得分:2)
我遇到字符串问题 - &gt;加密字节 - &gt;字符串转换。
我通过base64 en / decoder填充字节数组,这样你就必须在ASCII(子集)中保留除字符之外的字符串,这应该可以限制你的麻烦。看看,例如在commons codecs,并通过调用new String(decrypted)
类中的一个静态方法替换您的org.apache.commons.codec.binary.Base64
。
除此之外,我认为您最终想要做的并不是严格“加密”密码,而是仅存储密码的哈希值,这已在SO上讨论过。
答案 3 :(得分:-10)
一个非常简单的解决方案是使用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;
}
...