-1

I got one function online saying this is AES-256 bit encryption:

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

Now, this is using HMAC-SHA256. So is this actually AES or is this hashing? Or is it only hashing the secret key using HMAC? I mean SHA-256 is a hashing algorithm? Also, it might sound very basic but Is HMAC a hashing/encryption?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Ankit Bansal
  • 2,162
  • 8
  • 42
  • 79
  • 2
    **Security warning** - this code is using a static IV that makes the complete encryption **UNSECURE**. Please use a random IV and for authentication kindly use GCM mode. – Michael Fehr Oct 14 '20 at 20:19
  • This is a corrupted copy of my answer to a question on password-based encryption. The commentary there should answer your questions as well as restoring the parts needed for security and explaining options for better modes, etc. – erickson Oct 14 '20 at 20:50
  • https://stackoverflow.com/a/992413/3474 – erickson Oct 14 '20 at 21:15
  • Your questions don't make much sense. AES provides confidentiality and SHA-256 provides key derivation through hashing. Together they make up a cryptosystem. It is possible to use HMAC-SHA-256 in addition to key derivation also for encryption (confidentiality) by building a streaming cipher from it and it is possible to use AES for authenticity by using CMAC. Then they would make up a different cryptosystem. – Artjom B. Oct 15 '20 at 16:35
  • I have some [examples](https://gusto77.wordpress.com/2017/10/30/encryption-reference-project/). There is HMAC used for ciphertext authentication (integrity check) – gusto2 Oct 15 '20 at 19:46

3 Answers3

4

This is using PKBDF2 to stretch a password into a key. It's then using that key to encrypt the data with AES in CBC mode.

PBKDF2 requires a pseudorandom function (PRF), and the PRF used here is HMAC. HMAC requires a compression (hash) function, and that function is SHA-2, with a 256-bit digest size (commonly called "SHA-256").

I wouldn't say "this is AES-256 bit encryption." This is a complete crypto system that includes AES-256 as one of its components. There are many other (and more secure) ways to encrypt things using AES. For example, this appears to have a static IV+Key (assuming that salt and secret are constant). That's an insecure way to use CBC mode. It also lacks any kind of authentication, so messages can potentially be modified in transit. Those kinds of flaws are common, but this shouldn't be thought of as a canonical example of AES-256.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
1

I'd separate the code to several parts:

    byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    IvParameterSpec ivspec = new IvParameterSpec(iv);

NEVER EVER use static IV while reusing the same key. Using the same IV and key for encryption can (and in many instances will) provide ways to reveal some data or completely break the encryption. The IV is intended to make safe to reuse the same encryption key, for the CBC mode the IV needs to be more than random, it must be unpredictable.

Using a static IV is a common error when copy/paste code without deeper understanding.

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

An encryption key needs to have a specific length (AES-256 needs 256 bit ) and a key is expected to have high entropy (high randomness).

Human passwords are tend to have different length and the passwords are having much less randomness. This piece of code (as already described in another answer) creates a key from a password using 65536 rounds containing the SHA-256 hashing.

Multiple rounds are used to slow down the key generation, trying to make brute forcing less viable.

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
    return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));

This is encryption itself. So the whole example is to provide the encryption. The hashing is only used as a part of the "key stretching" algorithm - creating an encryption key from a password.

This example doesn't provide any authentication -the ciphertext could be tampered with and you have no means to validate the integrity.

kelalaka
  • 5,064
  • 5
  • 27
  • 44
gusto2
  • 11,210
  • 2
  • 17
  • 36
  • Also, there is a Synthetic Initialization Vector (SIV) mode as [nonce-misuse resistance](https://crypto.stackexchange.com/q/82105/18298) – kelalaka Oct 14 '20 at 20:20
  • 1
    @kelalaka oh, it's in RFC already (rfc8452) :) Nice, thx for the reference – gusto2 Oct 14 '20 at 20:27
0

Don't use this code; it's not secure. It is based on one of my answers, but in the process, critical elements were changed that destroy its integrity.

Okay, let's try this again.

Now, this is using HMAC-SHA256.

No, it's using PBKDF2. PBKDF2 in turn can use HMAC, and that, in turn, can use SHA-256.

PBKDF2 is a key derivation algorithm. It turns a text password into the actual key that is used with a symmetric cipher. It's designed in part to limit the rate at which different passwords can be tested as keys. It defeats dictionary attacks.

So is this actually AES or is this Hashing?

Both. Neither. It's a password-based encryption system that uses a cipher and a key derivation algorithm. As noted already, this key derivation uses a couple of algorithms, including a hash algorithm.

Or is it only hashing the secret key using HMAC?

It's not only hashing the secret. HMAC uses a hash algorithm, but it also specifies padding for the secret, the message, and how hashes are chained together. You can read more about it. The HMAC just acts as pseudo-random function (PRF) as part of PBKDF2, which adds other elements like iteration of the PRF with the secret, a salt, and a counter, in an effort to preserve the entropy of the secret while requiring a tunable amount of computational effort. You can read more about it too.

I mean SHA-256 is a hashing algorithm?

Yes. But it's not used directly at a top-level here. It's a component nested deeply in a top-level PBKDF2 algorithm.

Also, it might sound very basic but Is HMAC a hashing/encryption?

No. Fundamentally, it's a message authentication code. It can be used to detect alteration of data. But here, it's used as a PRF to generate a stream of data that can't be predicted by anyone without the secret.

erickson
  • 265,237
  • 58
  • 395
  • 493