java 如何在Java中获得IV进行解密?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16721266/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 23:46:59  来源:igfitidea点击:

How to get IV for decryption in Java?

javajakarta-eeencryptioncryptographyaes

提问by Ramesh Sippy

I need to encrypt / decrypt a username field and I was planning to use the code below:

我需要加密/解密用户名字段,我打算使用下面的代码:

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

I've taken this code from another site. The above code works fine when run as standalone. But the issue that I'm facing is how to decrypt the value when username is already encrypted?

我从另一个站点获取了此代码。当作为独立运行时,上面的代码工作正常。但是我面临的问题是如何在用户名已加密时解密该值?

I'll be calling encrypt & decrypt functions from different classes, so if the string is already encrypted & stored in the DB, then when user logs into website, when I'll call decrypt method, how do I pass the IV as CBC mode decrypt requires an IV parameter, while I've not stored iv during the encryption???

我将从不同的类调用加密和解密函数,所以如果字符串已经加密并存储在数据库中,那么当用户登录网站时,当我调用解密方法时,我如何将 IV 作为 CBC 模式传递解密需要一个 IV 参数,而我在加密期间没有存储 iv ???

Any help is much appreciated!!

任何帮助深表感谢!!

NOTE: This has nothing to do with password protection. As mentioned, need to encrypt userid & not password! For password protection, I'm using hash only.

注意:这与密码保护无关。如前所述,需要加密用户 ID 而不是密码!对于密码保护,我只使用哈希。

采纳答案by Lee Meador

To decrypt you have to have the IV and the secret key.

要解密,您必须拥有 IV 和密钥。

Though it is less secure, what I've seen is that people always keep the key (or password) safe somewhere and sometimes just code the IV into the program.

虽然它不太安全,但我所看到的是人们总是将密钥(或密码)保存在某个地方,有时只是将 IV 编码到程序中。

byte[] iv = new byte[] 
{ 
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f 
};

Or with some other set of byte values.

或者使用其他一些字节值集。

[Note that your code is generating an IV for each call to encrypt()]

[请注意,您的代码正在为每次调用生成一个 IV encrypt()]

Edit

编辑

Commenter @SLaks points out that using a constant IV reduces the level of protection and removes the extra level of security added by using CBC (which uses the IV). It reduces to the level of ECB (which has no IV).

评论者@SLaks 指出,使用恒定的 IV 会降低保护级别并消除使用 CBC(使用 IV)添加的额外安全级别。它降低到欧洲央行的水平(没有 IV)。

(Note: in the code above:

(注意:在上面的代码中:

Cipher.getInstance("AES/CBC/PKCS5Padding");

where CBC is selected.)

选择 CBC 的地方。)

This is significant in that a particular string of bytes will encrypt to the same result every time when the key, IV and salt used are the same. IV is there to make this stop happening.

这很重要,因为每次使用相同的密钥、IV 和盐时,特定的字节串都会加密为相同的结果。IV 是为了让这种情况停止发生。

We want the encrypted results to be as random looking as possible. That keeps the bad guys from figuring out the original content.

我们希望加密的结果看起来尽可能随机。这使坏人无法弄清楚原始内容。

Think of the IV as adding randomness to the plain-text message. For example, you might be encrypting passwords people give you. Those people tend to choose poor passwords and multiple people tend to choose the same one. Adding randomness would be a good thing in this case.

将 IV 视为向纯文本消息添加随机性。例如,您可能正在加密人们给您的密码。这些人倾向于选择糟糕的密码,而多人倾向于选择相同的密码。在这种情况下,添加随机性将是一件好事。

Think of a salt as adding randomness to the passphrase (which is just a fancy word for password to highlight using a long and varied one). In this case, again, people choose poor ones and adding randomness to them makes the encrypted results more random.

将盐视为为密码短语添加随机性(这只是密码的一个花哨词,以使用长而多变的密码突出显示)。在这种情况下,人们再次选择较差的,并为其添加随机性使加密结果更加随机。

That's why you would choose a random bunch of bits to serve as the IV for each message encrypted. To keep it from looking like other encrypted messages. But they have to be stored with each message so it can be decrypted.

这就是为什么您会选择随机的一组位作为每条加密消息的 IV。防止它看起来像其他加密消息。但是它们必须与每条消息一起存储,以便可以解密。

Any choosing a random bunch of bits to serve as the salt for each person will serve to make their messages encrypt and look different from anyone elses messages. You could use a different salt each time the person logs in or each time they change their password or even just once per person. However you do it, you have to save the salt values so you can decrypt the messages later.

任何选择随机一组位作为每个人的盐都将有助于使他们的消息加密并且看起来与其他人的消息不同。您可以在用户每次登录或每次更改密码时使用不同的盐,甚至每个人只更改一次。不管你怎么做,你都必须保存盐值,以便以后可以解密消息。

If you need this level of security, be sure to generate a truly random IV for each message encrypted and store it somewhere to be used when decrypting.

如果您需要这种级别的安全性,请确保为每条加密消息生成一个真正随机的 IV,并将其存储在某个地方以供解密时使用。

回答by SLaks

The IV is something you need to supplywhen encrypting or decrypting data.

IV 是您在加密或解密数据时需要提供的东西。

Like salt for a hash, the IV ensures that the identical plaintexts will never result in indentical ciphertexts.

就像散列的盐一样,IV 确保相同的明文永远不会产生相同的密文。

You need to generate a (securely) random IV when you encrypt each plaintext and store it alongside the ciphertext.

当您加密每个明文并将其与密文一起存储时,您需要生成一个(安全的)随机 IV。