Java 加密或散列

Java 加密或散列,java,encryption,aes,Java,Encryption,Aes,我在网上看到一个函数说这是AES-256位加密: public static String encrypt(String strToEncrypt, String secret) { try { byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; IvParameterSpec ivspec = new IvParameterSpec(iv);

我在网上看到一个函数说这是AES-256位加密:

public static String encrypt(String strToEncrypt, String secret) 
{
    try
    {
        byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        IvParameterSpec ivspec = new IvParameterSpec(iv);
         
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
        SecretKey tmp = factory.generateSecret(spec);
        SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
         
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
        return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
    } 
    catch (Exception e) 
    {
        System.out.println("Error while encrypting: " + e.toString());
    }
    return null;
}
现在,这是使用HMAC-SHA256。这实际上是AES还是散列?或者只是使用HMAC对密钥进行散列?我是说SHA-256是散列算法? 此外,它听起来可能非常基本,但HMAC是哈希/加密吗?

这是用来将密码扩展到密钥的。然后使用该密钥在CBC模式下用AES加密数据

PBKDF2需要一个伪随机函数(PRF),这里使用的PRF是。HMAC需要一个压缩(哈希)函数,该函数的大小为256位摘要(通常称为“SHA-256”)


我不会说“这是AES-256位加密”。这是一个完整的加密系统,其中包括AES-256作为其组件之一。还有许多其他(而且更安全)的方法可以使用AES加密内容。例如,这似乎有一个静态IV+密钥(假设
salt
secret
是常量)。使用CBC模式是不安全的。它还缺少任何类型的身份验证,因此消息可能会在传输过程中被修改。这些类型的缺陷很常见,但不应将其视为AES-256的典型示例。

我将代码分为几个部分:

    byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    IvParameterSpec ivspec = new IvParameterSpec(iv);
在重复使用同一密钥时,切勿使用静态IV。使用相同的IV和密钥进行加密可以(并且在许多情况下会)提供泄露某些数据或完全破坏加密的方法。IV旨在确保安全地重复使用相同的加密密钥,对于CBC模式,IV需要的不仅仅是随机的,它必须是不可预测的

在没有深入理解的情况下复制/粘贴代码时,使用静态IV是常见的错误

    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
    SecretKey tmp = factory.generateSecret(spec);
    SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
     
加密密钥需要具有特定长度(AES-256需要256位),并且密钥需要具有高熵(高随机性)

人工密码往往具有不同的长度,而且密码的随机性也要小得多。这段代码(如另一个答案中所述)使用包含SHA-256哈希的65536轮密码创建密钥

使用多轮来减缓密钥生成的速度,试图降低暴力强制的可行性

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
    return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
这就是加密本身。所以整个例子就是提供加密。散列仅用作“密钥拉伸”算法的一部分,即从密码创建加密密钥


此示例不提供任何身份验证-密文可能被篡改,您无法验证完整性。

不要使用此代码;它不安全。但在这个过程中,关键要素发生了变化,破坏了其完整性

好的,让我们再试一次

现在,这是使用HMAC-SHA256

不,它使用的是PBKDF2。PBKDF2反过来可以使用HMAC,而HMAC反过来可以使用SHA-256

PBKDF2是一种密钥派生算法。它将文本密码转换为与对称密码一起使用的实际密钥。它的设计部分是为了限制不同密码作为密钥进行测试的速率。它可以击败字典攻击

这实际上是AES还是散列

两者都有。也不这是一个基于密码的加密系统,使用密码和密钥派生算法。如前所述,该密钥派生使用了两种算法,包括哈希算法

或者只是使用HMAC对密钥进行散列

这不仅仅是散播秘密。HMAC使用散列算法,但它也指定秘密、消息的填充,以及散列如何链接在一起。你可以考虑一下。HMAC只是充当伪随机函数(PRF)作为PBKDF2的一部分,它添加了其他元素,如PRF与秘密、盐和计数器的迭代,以在需要可调计算量的同时保持秘密的熵。你也可以

我是说SHA-256是散列算法

对。但它并没有直接用于顶级。它是一个嵌套在顶级PBKDF2算法中的组件

此外,它可能听起来很基本,但HMAC是哈希/加密吗


不。基本上,这是一个消息身份验证码。它可用于检测数据的更改。但是在这里,它被用作PRF来生成没有秘密的任何人都无法预测的数据流。

安全警告-此代码使用的是静态IV,使得完整的加密不安全。请使用随机IV和GCM模式进行身份验证。这是我对基于密码的加密问题的答案的损坏副本。那里的评论应该回答你的问题,恢复安全性所需的部分,解释更好模式的选项,等等。你的问题没有多大意义。AES提供机密性,SHA-256通过哈希提供密钥派生。它们一起构成了一个密码系统。除了密钥派生之外,还可以使用HMAC-SHA-256通过构建流式密码进行加密(保密),也可以通过使用CMAC使用AES进行真实性验证。然后他们会组成一个不同的密码系统。我有一些。还有用于密文认证(完整性检查)的HMAC,还有一个合成初始化向量(SIV)模式@kelalaka oh,它已经在RFC(rfc8452)中了:)很好,供参考