1

Every time the encryption values changed by using AES, let anyone investigate the below code and let me know the issue

code:

private static final String secretKeys = "58BA833E57A51CBF9BF8BAB696BF9"

public static String encrypt() throws Exception {
        byte[] salt = new byte[16];
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        PBEKeySpec pbeKeySpec = new PBEKeySpec(secretKeys.getChars(),salt,1000, 256);
        Key secretKey = factory.generateSecret(pbeKeySpec);
        byte[] key = new byte[32];
        byte[] iv = new byte[16];
        SecretKeySpec secret = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret);
        byte[] result = cipher.doFinal("welcome".getBytes("UTF-8"));
        String s = Base64.getEncoder().encodeToString(result);
        return s
        }

Output first time I got the below-encrypted string

CZRIP35M4CnJtuDQ6YpmaQ==

The second time I got the below-encrypted string

/fylTjohAZDsnCaHhiZo3A==

I have three questions:

  1. why the encrypted string not a constant?

  2. how can I set the Blocksize? ( AES.BlockSize = 128;)

  3. How can I set the padding mode? (AES.Padding = PaddingMode.PKCS7;)

Freiheit
  • 8,408
  • 6
  • 59
  • 101
Prabu
  • 3,550
  • 9
  • 44
  • 85
  • Does the value of salt change on each execution? – Freiheit Aug 02 '19 at 13:15
  • @Freiheit sorry I don't know how can I check the salt value? – Prabu Aug 02 '19 at 13:19
  • 1
    When I print the salt value its shows like [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] – Prabu Aug 02 '19 at 13:22
  • 3
    Do you realize that you're always using a byte array full of 0s as your key, and that the 4 first lines of code don't do anything? And that you never use the iv, too? – JB Nizet Aug 02 '19 at 13:23
  • 2
    And why do you care about the output? What matters is that it can be decrypted with the same key. – JB Nizet Aug 02 '19 at 13:25
  • Posting comments because I don't have a complete answer. This Security.SE link has some good answers for your first question - https://security.stackexchange.com/questions/42642/should-aes-always-give-the-same-output – Freiheit Aug 02 '19 at 14:06

3 Answers3

3
  1. For the first question, @Freiheit already answered this. Long story short, based on the iv (initilization vector) which acts as a salt and will be different for each encryption. Having that said, encrypting the same plain text will result in different encrypted text, but the decryption (if necessary) will result back into the same plain text. IV is helpful to make the encryption predictable. Having stored the same password for 2 different users in a database will have different values, but will be the same password.

  2. With the current cipher configured, you already have 128 block size. You can read more about the different cypher transformation here. You can also find more information of the block sizes for different algorithms here

  3. You just need to change the Cipher.getInstance() to AES/CBC/PKCS7Padding
Andrei Sfat
  • 8,440
  • 5
  • 49
  • 69
1

1) the encrypted text is always different because the Cipher initialization is providing it's own IV since you are not providing one. You need to provide the IV you've "computed" in order to have a consistent output. Remember you never want to use an IV more than once for whatever this code is ultimately intended to do.

2) The keysize can be 128, 192 or 256 but the blocksize is always 128.

3) Java only provides PKCS5, but there is no difference in the implementation for AES. see what-is-the-difference-between-pkcs5-padding-and-pkcs7-padding

As was already pointed out there are several problems with the code provided such as the first lines not actually doing anything and the key and iv both being uninitialized. I would additionally suggest you use SecureRandom to initialize your key and iv. If you plan on using only a single AES key, this can be computed once and placed in the code or configuration file instead of running PBKDF2 every time.

micker
  • 878
  • 6
  • 13
0

Only adding to the answer provided by @micker, you need to invoke another version of Cipher.init(); one that takes the IV into account:

...
byte[] iv = new byte[16];
IvParameterSpec ivSpec = new IvParameterSpec(iv); // <= Wrap your IV bytes here.
SecretKeySpec secret = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret, ivSpec); // <= Add IV here.
...

That being said, the implementation suffers from a slew of other issues (key being all zeroes, IV being all zeroes, first 4 line don't do anything for you (as @JBNizet pointed out)). I hope you are only using it to study how Java's encryption mechanics works.

Daniel
  • 4,033
  • 4
  • 24
  • 33