2

This is my first project in Java and I decided to make a simple text encryptor using AES.

The error I am getting is: The method init(int, Key) in the type Cipher is not applicable for the arguments (int, byte[])

Code:

import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Key;

import javax.crypto.*;
import java.util.*;

public class Encryptor {

    public static void main(String[] args) throws Exception {
        String FileName = "encryptedtext.txt";
        String FileName2 = "decryptedtext.txt";

        Scanner input = new Scanner(System.in);

       System.out.println("Enter your 16 character key here:");
       String EncryptionKey = input.next();



        KeyGenerator KeyGen = KeyGenerator.getInstance("AES");
        KeyGen.init(128);

        Cipher AesCipher = Cipher.getInstance("AES");

        System.out.println("Enter text to encrypt or decrypt:");
        String Text = input.next();

        System.out.println("Do you want to encrypt or decrypt (e/d)");
        String answer = input.next();
        if (answer.equalsIgnoreCase("e")){

            byte[] byteKey = (EncryptionKey.getBytes());
            byte[] byteText = (Text).getBytes();

            AesCipher.init(Cipher.ENCRYPT_MODE, byteKey); // ERROR LINE
            byte[] byteCipherText = AesCipher.doFinal(byteText);
            Files.write(Paths.get(FileName), byteCipherText);


              }
        else if (answer.equalsIgnoreCase("d")){

            byte[] byteKey = (EncryptionKey.getBytes());
            byte[] byteText = (Text).getBytes();
            byte[] cipherText = Files.readAllBytes(Paths.get(FileName));

            AesCipher.init(Cipher.DECRYPT_MODE, byteKey); // ERROR LINE
            byte[] bytePlainText = AesCipher.doFinal(cipherText);
            Files.write(Paths.get(FileName2), bytePlainText);
        }
}

}

Thanks in advance! :)

mubeen
  • 813
  • 2
  • 18
  • 39
  • 1
    There are farily good samples here : http://stackoverflow.com/questions/15554296/simple-java-aes-encrypt-decrypt-example. Please, use camel case for your naming conventions, it helps :). – GPI Apr 19 '16 at 14:52
  • its your first java project, by the way try to write your first unit test for this project :) – La VloZ Merrill Apr 19 '16 at 16:01
  • 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. Apr 19 '16 at 18:41
  • **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. Apr 19 '16 at 18:42

3 Answers3

1

You should not pass byte array directly to Cipher object, instead you need to create object of SecretKeySpecs.

This is complete Code

  import java.nio.file.Files;
  import java.nio.file.Paths;
  import javax.crypto.*;
  import javax.crypto.spec.IvParameterSpec;
  import javax.crypto.spec.SecretKeySpec;

  import java.util.*;

  public class Encrypter {

  public static void main(String[] args) throws Exception {
  String FileName = "encryptedtext.txt";
  String FileName2 = "decryptedtext.txt";

  Scanner input = new Scanner(System.in);

  System.out.println("Enter your 16 character key here:");
  String EncryptionKey = input.next();
  byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  IvParameterSpec ivspec = new IvParameterSpec(iv);


  KeyGenerator KeyGen = KeyGenerator.getInstance("AES");
  KeyGen.init(128);


  Cipher AesCipher = Cipher.getInstance("AES/CFB/NoPadding");
  System.out.println("Enter text to encrypt or decrypt:");
  String Text = input.next();

  System.out.println("Do you want to encrypt or decrypt (e/d)");
  String answer = input.next();
  if (answer.equalsIgnoreCase("e")) {

   byte[] byteKey = (EncryptionKey.getBytes());
   byte[] byteText = (Text).getBytes();
   SecretKeySpec secretKeySpec = new SecretKeySpec(byteKey, "AES");
   AesCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivspec);
   AesCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivspec); // ERROR LINE
   byte[] byteCipherText = AesCipher.doFinal(byteText);
   Files.write(Paths.get(FileName), byteCipherText);


  } else if (answer.equalsIgnoreCase("d")) {

   byte[] byteKey = (EncryptionKey.getBytes());
   byte[] byteText = (Text).getBytes();
   byte[] cipherText = Files.readAllBytes(Paths.get(FileName));

   SecretKeySpec secretKeySpec = new SecretKeySpec(byteKey, "AES");
   AesCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivspec); // ERROR LINE
   byte[] bytePlainText = AesCipher.doFinal(cipherText);
   Files.write(Paths.get(FileName2), bytePlainText);
  }
 }

}
Mehdi Karamosly
  • 5,388
  • 2
  • 32
  • 50
Prashant
  • 138
  • 8
  • Thanks that solved it kinda :p When entering a text containing a space I cant click e/d and when choosing d (if i've only entered 1 word) I get this: Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher @Prashant – Emil Andersson Apr 19 '16 at 15:24
  • use this Cipher AesCipher = Cipher.getInstance("AES/CFB/NoPadding"); while creating object of aescipher.Click on accept answer button if it helped you – Prashant Apr 19 '16 at 15:27
  • I'm still getting a error when decrypting: Exception in thread "main" java.security.InvalidKeyException: Parameters missing And I cant have a text that has space "test" is fine but when writing "test test" I cant press e/d Regards, – Emil Andersson Apr 19 '16 at 15:55
  • can u check http://stackoverflow.com/questions/6669181/why-does-my-aes-encryption-throws-an-invalidkeyexception this link in mean while.I will update code if it work, give me 10minutes. We need to add initialization vector, iv. we can use 0 zero vector for that – Prashant Apr 19 '16 at 17:32
1

This is Full code

Full code:

import java.nio.file.Files;
import java.nio.file.Paths;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import java.util.*;

public class Encrypter {

public static void main(String[] args) throws Exception {
    String FileName = "encryptedtext.txt";
    String FileName2 = "decryptedtext.txt";

    Scanner input = new Scanner(System.in);

   System.out.println("Enter your 16 character key here:");
   String EncryptionKey = input.next();
   byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
   IvParameterSpec ivspec = new IvParameterSpec(iv);


    KeyGenerator KeyGen = KeyGenerator.getInstance("AES");
    KeyGen.init(128);


    Cipher AesCipher = Cipher.getInstance("AES/CFB/NoPadding");
    System.out.println("Enter text to encrypt or decrypt:");
    String Text = input.next();

    System.out.println("Do you want to encrypt or decrypt (e/d)");
    String answer = input.next();
    if (answer.equalsIgnoreCase("e")){

        byte[] byteKey = (EncryptionKey.getBytes());
        byte[] byteText = (Text).getBytes();
        SecretKeySpec secretKeySpec = new SecretKeySpec(byteKey, "AES");
        AesCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,ivspec );
        AesCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,ivspec); // ERROR LINE
        byte[] byteCipherText = AesCipher.doFinal(byteText);
        Files.write(Paths.get(FileName), byteCipherText);


          }
    else if (answer.equalsIgnoreCase("d")){

        byte[] byteKey = (EncryptionKey.getBytes());
        byte[] byteText = (Text).getBytes();
        byte[] cipherText = Files.readAllBytes(Paths.get(FileName));

        SecretKeySpec secretKeySpec = new SecretKeySpec(byteKey, "AES");
        AesCipher.init(Cipher.DECRYPT_MODE, secretKeySpec,ivspec); // ERROR LINE
        byte[] bytePlainText = AesCipher.doFinal(cipherText);
        Files.write(Paths.get(FileName2), bytePlainText);
    }
}

}
Prashant
  • 138
  • 8
0

I had to encrypt a URL for been exposed in a external link, and I have created a class to encrypt on AES. Maybe this can help someone. I added a method to create my Random Initial Vector and it is on this class also.

package br.com.tokiomarine.captcha.encryption;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.text.CharacterPredicates;
import org.apache.commons.text.RandomStringGenerator;

public class Encryptor 
{
    public static String encrypt(String key, String initVector, String value) throws Exception
    {
        IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

        byte[] encrypted = cipher.doFinal(value.getBytes());

        return Base64.encodeBase64URLSafeString(encrypted);
    }

    public static String decrypt(String key, String initVector, String encrypted) throws Exception 
    {
        IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

        byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));

        return new String(original);
    }

    public static String generateInitVector() {
    RandomStringGenerator randomStringGenerator =
        new RandomStringGenerator.Builder()
            .withinRange('0', 'z')
            .filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS)
            .build();
    return randomStringGenerator.generate(16);
    }

}

And here is my Test Class:

public class EcryptionTest {

    @Test
    public void encryptionTest() {
        try 
        {
            String key = "Key@TokioMarineC";
            for(int i = 0; i < 1000; i++) 
            {
                String initVector = Encryptor.generateInitVector();
                String encrypted = Encryptor.encrypt(key, initVector, "StringTeste");
                assertTrue("StringTeste".equals(Encryptor.decrypt(key, initVector, encrypted)));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}