1

I have tried adding getbytes("UTF") or getbytes("UTF-8"), since it was suggested in a similar question. It said we need to try UTF while converting bytes to string and vice a versa. But still it is not working for my code...please help

public class Password1 {

    private static final String ALGO = "AES";
    private static byte[] keyValue = new byte[]{'t','h','y','u','e','f','z','s','y','k','f','l','d','a','b','m'};

    public static void main(String[] args) {
        //Password1 p = new Password1();
        Scanner sc = new Scanner(System.in);
        String i = sc.nextLine();
        System.out.println("Password = "+i);

        try {
            String en = encrypt(i);
            System.out.println(en);
            String dec = decrypt(en);

            System.out.println("Encrypted = " + en);
            System.out.println("Decrypted = " + dec);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static String encrypt(String Data) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encVal = c.doFinal(Data.getBytes("UTF-8"));
        String encrypted = new BASE64Encoder().encode(encVal);

        return encrypted;
    }

    public static String decrypt(String encrypted) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);
        //Byte bencrypted = Byte.valueOf(encrypted);
        byte[] decoded = new BASE64Decoder().decodeBuffer(encrypted);

        byte[] decValue = c.doFinal(decoded);
        String decrypted = new String(decValue);
        return decrypted;
    }

    private static Key generateKey() throws Exception {
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        keyValue = sha.digest(keyValue);
        keyValue = Arrays.copyOf(keyValue, 16);
        SecretKeySpec key = new SecretKeySpec(keyValue, ALGO);
        return key;
    }

}
sasha00
  • 23
  • 1
  • 1
  • 5
  • Can you post the stack trace you are getting as well? – Nick DeFazio Mar 07 '16 at 20:54
  • What is not working? – zaph Mar 07 '16 at 21:07
  • General advice: **Always use a fully qualified Cipher string.** `Cipher.getInstance("AES");` may result in different ciphers depending on the default security provider. It most likely results in `"AES/ECB/PKCS5Padding"`, but it doesn't have to be. If it changes, you'll lose compatibility between different JVMs. – Artjom B. Mar 07 '16 at 21:27
  • **Never use [ECB mode](http://crypto.stackexchange.com/q/14487/13022)**. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like [CBC](http://crypto.stackexchange.com/q/22260/13022) or [CTR](http://crypto.stackexchange.com/a/2378/13022). It is better to authenticate your ciphertexts so that attacks like a [padding oracle attack](http://crypto.stackexchange.com/q/18185/13022) are not possible. This can be done with authenticated modes like GCM or EAX, or with an [encrypt-then-MAC](http://crypto.stackexchange.com/q/202/13022) scheme. – Artjom B. Mar 07 '16 at 21:28
  • here is the Stacktrace hduhducsaoaoksnwl Password = hduhducsaoaoksnwl k2yWnTrcb/oVeFA4X9SV2Zl4o+8Humzdog7ZJG8Gnyc= javax.crypto.BadPaddingException: Given final block not properly padded at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811) at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676) at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:420) at javax.crypto.Cipher.doFinal(Cipher.java:1922) at com.pack1.Password1.decrypt(Password1.java:60) at com.pack1.Password1.main(Password1.java:29) – sasha00 Mar 07 '16 at 21:48

2 Answers2

3

When you call encrypt() you replace the password by its hash, and then use the hash as a key.

Then you call decrypt(), and rehash the hash, and use the hashed hash as the key. So you're not using the same key for encryption and decryption.

Generate the key once in main(), and pass it as parameter to encrypt() and decrypt(). Make keyValue final. Or even better, make it a local variable of main.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • thanks a lot...problem solved after generating key just once in main and passing it to both the functions.... – sasha00 Mar 07 '16 at 22:00
1

On the line where you have Cipher.getInstance(ALGO) have your ALGO variable be "AES/CBC/PKCS5Padding" (or whatever other mode and padding you want to use). This should resolve any padding issues you might run into like the one you are now.

If you don't do it in this way I believe you'll have to handle all of the padding logic yourself.

JB Nizet's answer about how you're generating keys is the other half of your problem.

Aaron
  • 10,386
  • 13
  • 37
  • 53
  • One issue, the code does not supply an iv that CBC mode needs. – zaph Mar 07 '16 at 21:17
  • I guess you can either add that support in or pick another mode that doesn't rely on an IV. `AES/CBC/PKCS5Padding` was just an example. There are other modes and padding types you can use. If you decide to use ECB mode so that you don't have to use an IV just be aware that you're greatly weakening things. See here for why https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29 – Aaron Mar 07 '16 at 21:18