0

I am implementing AES algorithm in java.I am converting SecretKey to String and passing to server.java through sockets. In server.java, I am converting this string back to SecretKey.However, I am getting the error mentioned below.

I have tried all possible solutions but nothing worked for me. In client.java, I am converting secKey to String

 String encodedKey = 
 Base64.getEncoder().encodeToString(secKey.getEncoded());
 System.out.println(secKey);

Output:

de.flexiprovider.core.rijndael.RijndaelKey@714b1429

I have converted this string back to SecretKey

 byte[] decodedKey = Base64.getDecoder().decode(line);
 SecretKey secKey = new SecretKeySpec(decodedKey, "AES");
 System.out.println(secKey);`

Output - de.flexiprovider.api.keys.SecretKeySpec@fffe87c2

Here, both outputs are not same and I am getting the following error

Exception in thread "main" java.security.InvalidKeyException: 
unsupported type
   at 
de.flexiprovider.api.BlockCipher.engineInit(BlockCipher.java:165)
   at de.flexiprovider.api.Cipher.engineInit(Cipher.java:68)
   at javax.crypto.Cipher.init(Cipher.java:1246)
   at javax.crypto.Cipher.init(Cipher.java:1186)
   at server.main(server.java:93)

How can I correct this error?

server.java

 import java.net.*;
   import java.io.*;
   import java.security.Security;
   import javax.crypto.*;
   import de.flexiprovider.api.keys.SecretKeySpec;
   import de.flexiprovider.core.FlexiCoreProvider;
   import de.flexiprovider.core.rijndael.RijndaelKeyFactory;
   import java.util.Base64;
   public class server {
    public final static int FILE_SIZE = 6022386; 
    private Socket          socket   = null;
    private ServerSocket    server   = null;
    private DataInputStream in       =  null;
    int bytesRead;
    int current = 0;
    FileOutputStream fos = null;
    BufferedOutputStream bos = null;
    static SecretKey secKey = null;


    public server(int port)
    {
        // starts server and waits for a connection
        try
        {
               server = new ServerSocket(port);
            System.out.println("Server started");
            System.out.println("Waiting for a client ...");
            socket = server.accept();
            System.out.println("Client accepted");



            // takes input from the client socket
            in = new DataInputStream(new 
      BufferedInputStream(socket.getInputStream()));
            String line = in.readUTF();

          byte[] decodedKey = Base64.getDecoder().decode(line);
            secKey = new SecretKeySpec(decodedKey, "AES"); 





            byte [] mybytearray  = new byte [FILE_SIZE];
            InputStream is = socket.getInputStream();
            fos = new FileOutputStream("cipher.txt");
            bos = new BufferedOutputStream(fos);
            bytesRead = is.read(mybytearray,0,mybytearray.length);
            current = bytesRead;
            do {
                bytesRead =
                   is.read(mybytearray, current, (mybytearray.length-
         current));
                if(bytesRead >= 0) current += bytesRead;
             } while(bytesRead > -1);
            bos.write(mybytearray, 0 , current);
            bos.flush();
            System.out.println("File Received" );

            // close connection
            socket.close();
            in.close();fos.close();bos.close();
        }
        catch(IOException i)
        {
            System.out.println(i);
        }
        }
       public static void main(String args[]) throws Exception
       {
        Security.addProvider(new FlexiCoreProvider());
        Cipher cipher = Cipher.getInstance("AES128_CBC", "FlexiCore");
        server ser = new server(5003);

        byte[] block = new byte[8];
        int i;

        String ciphertextFile = "cipher.txt";
        String cleartextAgainFile = "cleartextAgainSymm.txt";

        System.out.println(secKey);
        cipher.init(Cipher.DECRYPT_MODE, secKey);
        FileInputStream fis  = new FileInputStream(ciphertextFile);
        CipherInputStream cis = new CipherInputStream(fis, cipher);


    FileOutputStream  fos = new FileOutputStream(cleartextAgainFile);

            while ((i = cis.read(block)) != -1) {
                fos.write(block, 0, i);
            }
            fos.close();
           }
         }

server output

   Server started
Waiting for a client ...
Client accepted
File Received
de.flexiprovider.api.keys.SecretKeySpec@fffe8f6c
Exception in thread "main" java.security.InvalidKeyException: unsupported type
    at de.flexiprovider.api.BlockCipher.engineInit(BlockCipher.java:165)
    at de.flexiprovider.api.Cipher.engineInit(Cipher.java:68)
    at javax.crypto.Cipher.init(Cipher.java:1246)
    at javax.crypto.Cipher.init(Cipher.java:1186)

client.java

   import java.net.*;
import java.io.*;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import de.flexiprovider.api.keys.SecretKeySpec;
import de.flexiprovider.core.FlexiCoreProvider;

import java.util.Arrays;
import java.util.Base64;

public class Client {

    static SecretKey secKey;
    // initialize socket and input output streams
    private Socket socket            = null;
    private DataInputStream  input   = null;
    private DataOutputStream out     = null;
    FileInputStream fis;
    File myFile;
    BufferedInputStream bis = null;
    OutputStream os = null;

    public Client(String address, int port)
    {

        // establish a connection
        try
        {
            socket = new Socket(address, port);
            System.out.println("Connected");

            // takes input from terminal
            input  = new DataInputStream(System.in);

            // sends output to the socket
            out    = new DataOutputStream(socket.getOutputStream());


            String encodedKey = Base64.getEncoder().encodeToString(secKey.getEncoded());
            out.writeUTF(encodedKey);

             myFile = new File ("ciphertextSymm.txt");
             byte [] mybytearray  = new byte [(int)myFile.length()];
             fis=new FileInputStream(myFile);
             bis = new BufferedInputStream(fis);
             bis.read(mybytearray,0,mybytearray.length);
             os = socket.getOutputStream();
             System.out.println("Sending ");
             os.write(mybytearray,0,mybytearray.length);
             os.flush();
             System.out.println("Done.");

        }
        catch(UnknownHostException u)
        {
            System.out.println(u);
        }
        catch(IOException i)
        {
            System.out.println(i);
        }

        // close the connection
        try
        {
            input.close();
            out.close();
            socket.close();
            bis.close();
            os.close();
        }
        catch(IOException x)
        {
            System.out.println(x);
        }
    }
    public static void main(String args[]) throws Exception
    {
        Security.addProvider(new FlexiCoreProvider());
        Cipher cipher = Cipher.getInstance("AES128_CBC", "FlexiCore");
        KeyGenerator keyGen = KeyGenerator.getInstance("AES", "FlexiCore");
        secKey = keyGen.generateKey();


        System.out.println(secKey);
        cipher.init(Cipher.ENCRYPT_MODE, secKey);
        String cleartextFile = "cleartext.txt";
        String ciphertextFile = "ciphertextSymm.txt";

        FileInputStream fis = new FileInputStream(cleartextFile);
        FileOutputStream fos = new FileOutputStream(ciphertextFile);
        CipherOutputStream cos = new CipherOutputStream(fos, cipher);

        byte[] block = new byte[8];
        int i;
        while ((i = fis.read(block)) != -1) {
            cos.write(block, 0, i);
        }
        cos.close();

        Client client = new Client("127.0.0.1", 5003);
    }
}

client output

    de.flexiprovider.core.rijndael.RijndaelKey@7c226727
Connected
Sending 
Done.
  • I don't know how you got your output, none of the shown code snippets writes anything, and it is definitely not the value of the string `encodedKey` (not a base64 encoding). The output looks like the result of calling `toString` on an SecretKey object. To get meaningful help please show **exactly** what you are doing. – Henry Jan 17 '18 at 18:28
  • The first code you presented can never give you the output `de.flexiprovider.core.rijndael.RijndaelKey@714b1429`. Anyway why are you using Flexiprovidder? AES is integrated in Java. – Robert Jan 17 '18 at 18:44
  • You'd get a much better idea of your problem if you printed the encoded form of the key (`encodedKey`, rather than `secKey`) before sending, and after receiving (`line` instead of `secKey`). – erickson Jan 17 '18 at 19:01
  • I have tried this https://stackoverflow.com/a/12039611/7403803 .But it didn't work for me – Bathini Pranay kumar Jan 17 '18 at 19:56

2 Answers2

0

I would recommend to read Java 256-bit AES Password-Based Encryption. But here a quick overview. You will have to create a SecretKeyFactory, a KeySpec and then you can generate your SecretKey based on the KeySpec. From there, you can specify that your key is an AES through SecretKeySpec. There are some magic numbers here that you will have to consider. One is the password iterations, and the other the key sizes. For the example that I created below, I am using a 128 key instead of a 256. Sorry, I am not an expert in security topics so I used some examples that I have.

public static void main(String[] args) {
    try {
        //message to be encrypted
        final String message = "This is a test message";  
        final String password = "password";

        // Here the magic numbers
        final int pswdIterations = 65536;
        final int keySize = 128;

        final byte[] saltBytes = {0, 1, 2, 3, 4, 5, 6};

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, pswdIterations, keySize);
        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

        // Instantiate the cipher
        Cipher cipher = Cipher.getInstance("AES");

        // Encrypt
        cipher.init(Cipher.ENCRYPT_MODE, secret);
        byte[] encrypted = cipher.doFinal(message.getBytes());
        System.out.println("Original string: " + message);
        System.out.println("Encrypted string: " + Arrays.toString(encrypted));

        // Decrypt
        cipher.init(Cipher.DECRYPT_MODE, secret);
        byte[] decrypt_original = cipher.doFinal(encrypted);
        String decrypt_originalString = new String(decrypt_original);
        System.out.println("Decrypt string: " + decrypt_originalString);
    } catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex) {
        Logger.getLogger(Sandbox.class.getName()).log(Level.SEVERE, null, ex);
    }
}

Hopefully, this will help you.

Cagt
  • 80
  • 6
0

For Java 7 or below:

Secret Key to String:

stringKey = Base64.encodeToString(secretKey.getEncoded(), Base64.DEFAULT);

String to Secret Key:

byte[] encodedKey     = Base64.decode(stringKey, Base64.DEFAULT);
SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");

For Java 8:

Secret Key to String:

String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());

String to Secret Key:

byte[] decodedKey = Base64.getDecoder().decode(encodedKey);

SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); 

Taken from reference: https://stackoverflow.com/a/12039611/7403803

Himesh Nandani
  • 121
  • 1
  • 8