mynameispnthony
mynameispnthony

Reputation: 1

AES256 in java error

i am testing AES 256 in a java applet. It works just fine if i decode the byte[] i get in the code. I print the byte in binary format in encoded string textbox. if i take that string and decode, I get an exception Given final block not properly padded . What's the problem?

my code follows


public class TestApplet extends Applet {
 Label lblKey = new Label("Key");
 TextField inputLineKey = new TextField(15);
 Label lblString = new Label("Value");
 TextField inputLineString = new TextField(15);
 Label lblStringEncoded = new Label("Encoded Value");
 TextField inputLineStringEncoded = new TextField(15);
 Label lblStringDecoded = new Label("Decoded Value");
 TextField inputLineStringDecoded = new TextField(15);
 Button encodeButton = new Button("Test Encrypt");
 Button decodeButton = new Button("Test Decrypt");

 public TestApplet() {
  add(inputLineKey);
  add(lblKey);
  add(inputLineString);
  add(lblString);
  add(inputLineStringEncoded);
  add(lblStringEncoded);
  add(inputLineStringDecoded);
  add(lblStringDecoded);
  add(encodeButton);
  add(decodeButton);
  // inputLine.addActionListener(new MyActionListener());
 }

 /**
  * Turns array of bytes into string
  * 
  * @param buf
  *            Array of bytes to convert to hex string
  * @return Generated hex string
  */
 public static String asHex(byte buf[]) {
  StringBuffer strbuf = new StringBuffer(buf.length * 2);
  int i;

  for (i = 0; i < buf.length; i++) {
   if (((int) buf[i] & 0xff) < 0x10)
    strbuf.append("0");

   strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
  }

  return strbuf.toString();
 }

 public boolean action(Event e, Object args) {

  // so do something!

  // ///////////////////////
  try {
   String message = "This is just an example";

   // Get the KeyGenerator

   KeyGenerator kgen = KeyGenerator.getInstance("AES");
   kgen.init(128); // 192 and 256 bits may not be available

   // Generate the secret key specs.
   SecretKey skey = kgen.generateKey();
   byte[] raw = skey.getEncoded();

   SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

   // Instantiate the cipher

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

   if (e.target == encodeButton) { // User has clicked on encrypt
           // button
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

    byte[] encrypted = cipher.doFinal((inputLineString.getText()
      .length() == 0 ? message : inputLineString.getText())
      .getBytes());
    // System.out.println("encrypted string: " + asHex(encrypted));

    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    byte[] original = cipher.doFinal(encrypted);
    String originalString = new String(original);
    // System.out.println("Original string: " +
    // originalString + " " + asHex(original));

    // Create a BigInteger using the byte array
    BigInteger bi = new BigInteger(encrypted);

    inputLineStringEncoded.setText(bi.toString(2)); // (new String(encrypted));
    inputLineStringDecoded.setText(originalString);
   }

   if (e.target == decodeButton) { // User has clicked on decrypt
           // button
   // cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
   //
   // byte[] encrypted = cipher.doFinal((inputLineString.getText()
   // .length() == 0 ? message : inputLineString.getText())
   // .getBytes());
   // // System.out.println("encrypted string: " + asHex(encrypted));

    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    // Parse binary string
    BigInteger bi = new BigInteger(inputLineStringEncoded
      .getText(), 2);

    byte[] original = cipher.doFinal(bi.toByteArray());
    String originalString = new String(original);
    // System.out.println("Original string: " +
    // originalString + " " + asHex(original));
    inputLineString.setText(originalString);
    inputLineStringDecoded.setText(originalString);
   }

  } catch (Exception exc) {
   inputLineStringEncoded.setText(exc.getMessage());
  }
  return true; // Yes, we do need this!
 }

 class MyActionListener implements ActionListener {
  public void actionPerformed(ActionEvent event) {
  }
 }
}
________________________________

Upvotes: 0

Views: 666

Answers (2)

Jorge Ferreira
Jorge Ferreira

Reputation: 97839

You should encode byte[] encrypted in some suitable TEXT format like hex encode or base64. To decrypt you pass from text representation again to byte[].

The problem is around these lines:

byte[] original = cipher.doFinal(bi.toByteArray());
String originalString = new String(original);

and

BigInteger bi = new BigInteger(encrypted);

Where you must encode it to a string using, for example, one of the above encodings. Take a look at commons-codec for that task.

http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1499760

This is the problem:

String originalString = new String(original);

You're taking opaque binary data and trying to interpret it as if it were a valid text string. It almost certainly won't be. Furthermore, you're converting it using the system default encoding, which is almost never a good idea.

To represent arbitrary binary data in text, it's best to use base64 to encode and decode it. Alternatively, use hex - you've already got a way of converting binary data to hex, so you might want to use that. It's slightly longer than base64, but you may find it easier to deal with.

Upvotes: 3

Related Questions