我需要加密/解密用户名字段,我打算使用以下代码:
public class Decrypter {
Cipher dcipher;
byte[] salt = new String("12345678").getBytes();
int iterationCount = 1024;
int keyStrength = 256;
SecretKey key;
byte[] iv;
Decrypter(String passPhrase) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount, keyStrength);
SecretKey tmp = factory.generateSecret(spec);
key = new SecretKeySpec(tmp.getEncoded(), "AES");
dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
}
public String encrypt(String data) throws Exception {
dcipher.init(Cipher.ENCRYPT_MODE, key);
AlgorithmParameters params = dcipher.getParameters();
iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] utf8EncryptedData = dcipher.doFinal(data.getBytes());
String base64EncryptedData = new sun.misc.BASE64Encoder().encodeBuffer(utf8EncryptedData);
System.out.println("IV " + new sun.misc.BASE64Encoder().encodeBuffer(iv));
System.out.println("Encrypted Data " + base64EncryptedData);
return base64EncryptedData;
}
public String decrypt(String base64EncryptedData) throws Exception {
dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] decryptedData = new sun.misc.BASE64Decoder().decodeBuffer(base64EncryptedData);
byte[] utf8 = dcipher.doFinal(decryptedData);
return new String(utf8, "UTF8");
}
public static void main(String args[]) throws Exception {
Decrypter decrypter = new Decrypter("ABCDEFGHIJKL");
String encrypted = decrypter.encrypt("StringToBeEncrypted");
String decrypted = decrypter.decrypt(encrypted);
System.out.println(decrypted);
}
}
我从其他网站上获取此代码。上面的代码在独立运行时工作正常。但我面临的问题是如何在用户名已加密时解密该值?
我会打电话给加密&解密来自不同类的函数,因此如果该字符串已经加密并且已经加密。存储在数据库中,然后当用户登录网站时,当我打电话给解密方法时,如何通过IV作为CBC模式解密需要一个IV参数,而我在加密期间没有存储iv?
非常感谢任何帮助!!
注意:这与密码保护无关。如上所述,需要加密userid&不是密码!为了保护密码,我只使用哈希。
答案 0 :(得分:8)
在加密或解密数据时,您需要提供。
就像散列的盐一样,IV确保相同的明文永远不会导致缩进的密文。
当您加密每个明文并将其与密文一起存储时,您需要生成(安全)随机IV。
答案 1 :(得分:-3)
要解密,您必须拥有IV和密钥。
虽然它不太安全,但我所看到的是人们总是将密钥(或密码)保存在某处,有时只是将IV编码到程序中。
byte[] iv = new byte[]
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};
或者使用其他一些字节值。
[请注意,您的代码为每次调用encrypt()
]
修改的
Commenter @SLaks指出,使用常量IV会降低保护级别,并消除使用CBC(使用IV)所增加的额外安全级别。它降低到ECB(没有IV)的水平。
(注意:在上面的代码中:
Cipher.getInstance("AES/CBC/PKCS5Padding");
选择CBC。)
这很重要,因为每当使用的密钥,IV和盐相同时,特定字节串将加密到相同的结果。 IV是为了让这种停止发生。
我们希望加密结果尽可能随机。这让坏人无法搞清楚原始内容。
将IV视为向纯文本消息添加随机性。例如,您可能正在加密人们提供给您的密码。那些人倾向于选择不良密码,而多人倾向于选择相同的密码。在这种情况下,添加随机性将是一件好事。
将salt视为为密码添加随机性(这只是密码的一个奇特的词,以突出显示使用长而多变的密码)。在这种情况下,人们再次选择不好的人,并为他们添加随机性使得加密结果更加随机。
这就是为什么你会选择一组随机位作为加密的每条消息的IV。使其看起来不像其他加密邮件。但是它们必须与每条消息一起存储,以便可以解密。
任何选择随机串位作为每个人的盐都将有助于使他们的消息加密并且看起来与任何人的消息不同。每次登录时或每次更改密码时,您都可以使用不同的盐,甚至每人一次。但是,您必须保存salt值,以便稍后解密消息。
如果您需要此级别的安全性,请务必为每封加密的邮件生成一个真正的随机IV,并将其存储在解密时使用的位置。