有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java AES加密在ECB模式下实现,但不符合安全性要求。如何实施CBC模式

我已经用java实现了AES加密,但该算法不被团队接受,因为它是在ECB模式下实现的,不符合安全性。我对密码学和安全要求非常陌生

有人能帮我把算法改成CBC模式吗。我已经附加了在ECB模式下实现的代码

public String encrypt(String plainPwd)
{
    byte[] outputBytes = new byte[] {};
    String returnString = "";
    try
    {
        byte[] raw = "XXXXX@XXXXXX.XXX".getBytes("UTF-8");

        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

        outputBytes = cipher.doFinal(plainPwd.getBytes("UTF-8"));
        if (null != outputBytes)
        {
            returnString = Base64Encrypter.getInstance().encode(outputBytes);
        }
        return returnString.trim();

    }
    catch (Exception e)
    {
        System.out.println(e);
    }

    return new String(outputBytes).trim();
}

public String decrypt(String encryptedPwd)
{
    byte[] outputBytes = new byte[] {};
    try
    {
        byte[] raw = "XXXXX@XXXXXX.XXX".getBytes("UTF-8");

        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);

        byte[] inputBytes = Base64Encrypter.getInstance().decode(encryptedPwd);
        if (null != inputBytes)
        {
            outputBytes = cipher.doFinal(inputBytes);
        }
    }
    catch (Exception e)
    {
        System.out.println(e);
    }

    return new String(outputBytes).trim();
}

如能早日答复,将不胜感激。 提前谢谢


共 (3) 个答案

  1. # 1 楼答案

    如果您的数据较短且随机,ECB可能是可以接受的(至少不比CBC差)。但这很可能是一个好主意,甚至不要试图让这一点是正确的

    请记住,CBC也不提供完整性保护。使用额外的HMAC或专用模式包装机密(AESKYWRAP)或使用身份验证模式(AES/GCM)更好。(这不仅仅是一个避免修改的问题,它还关闭了一类针对协议隐私保护的攻击)

    如果数据不是随机/可预测的,则需要使用一种模式,该模式也使用IV。对于CBC,如果未指定,Java将选择随机IV

    然而,对于解密(特别是如果您有一个填充来进行验证),您需要指定完全相同的IV,所以不要忘记检索和传输它。因此(由于未经验证而不安全)加密变为:

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    byte[] iv = cipher.getIV(); // randomly filled.
    ...
    
    // on decrypt specify this IV again
    cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv));
    

    这还有一个优点,即它实际上指定了要使用的填充,因此您不依赖于Java的默认选择(始终指定完整模式字符串)

  2. # 2 楼答案

    将请求字符串从AES更改为AES/CBC/PKCS5PADDING,并添加一个iv。虽然填充不是特定于CBC的,但最好显式定义所有参数,除少数例外情况外,需要填充

    对于iv,生成块大小的加密安全随机数(AES为16字节)。为了使iv可用于解密,通常的做法是将其预加密到加密数据中,它不需要是机密的

  3. # 3 楼答案

    AES有大约6种不同的加密模式。对于正在使用它的应用程序,使用正确的模式非常重要。正如@eckes所说,ECB对于随机加密/解密访问有用的少量数据来说是合适的。ECB的缺点是,相同的输入将具有相同的输出,因此攻击者可以看到模式,如果实际值的数量有限,则可以对其进行反向工程

    查看how to choose AES encryption mode了解有关选择正确操作模式的更多指导