【问题标题】:How to get IV for decryption in Java?如何在 Java 中获取 IV 进行解密?
【发布时间】:2013-05-24 05:55:56
【问题描述】:

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

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???

非常感谢任何帮助!

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

【问题讨论】:

  • 你没有'得到'它,你在两端定义它。

标签: java jakarta-ee encryption cryptography aes


【解决方案1】:

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

就像哈希的盐一样,IV 确保相同的明文永远不会导致相同的密文。

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

【讨论】:

  • 您是否建议我也应该将 IV 保存在数据库中并通过它进行解密?
  • @RameshSippy:没错。请参阅我的扩展答案。
  • @RameshSippy:是的,这叫 ECB 模式,不应该使用。 en.wikipedia.org/wiki/Block_cipher_mode_of_operation
  • 无论如何使用 IV(和 CBC)的一个原因,即使它不会使数据更安全,但不同的应用程序可以使用不同的 IV 值和相同的数据库,并且它们不会意外解码即使应用程序中的错误尝试这样做,也可以相互提供数据。
  • @LeeMeador:在这种情况下,每个应用程序都应该使用唯一的key
【解决方案2】:

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

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

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

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

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

编辑

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

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

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

选择 CBC 的位置。)

这很重要,因为每次使用的密钥、IV 和盐相同时,特定的字节串将加密为相同的结果。 IV 可以阻止这种情况发生。

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

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

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

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

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

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

【讨论】:

  • 不要这样做。这违背了IVs的目的,本质上与ECB相同。除非您完全了解您正在使用的操作,否则不要编写加密代码。否则,您很可能最终会造成安全漏洞或弱点。 把加密的东西留给专家。 (其中我不编号)
  • “如果您需要这种级别的安全性,请确保为每个加密块生成一个真正随机的 IV,并将其存储在某个地方以供解密时使用。” - 每个块不需要随机IV;仅适用于每个会话。
  • 事实上,你不能为每个区块指定不同的IV。
  • 出于 SLaks 解释的原因,我投了反对票。正确处理 IV 真的很容易,因此基于受保护数据价值低的论点没有说服力。
  • “所有程序都有安全漏洞”并不是故意编写安全漏洞的借口。这个论点不仅会弄巧成拙(如果他不关心保密,他一开始就不会加密),而且,根据国家/应用程序,这样做可能会得到即使没有“存储武器数据”,您也会陷入法律困境。 -1.
猜你喜欢
  • 1970-01-01
  • 2018-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-28
  • 2016-10-02
  • 1970-01-01
相关资源
最近更新 更多