Java encryption using AES
I am trying to create an encryption system using the AES class:
package Source;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AES {
static String IV = "AAAAAAAAAAAAAAAA";
static String plaintext = "test text 123\0\0\0"; /*Note null padding*/
static String encryptionKey = "H4tch4repratygonetowil5h4kers";
public static void main(String [] args) {
try {
System.out.println("==Java==");
System.out.println("plain: " + plaintext);
byte[] cipher = encrypt(plaintext, encryptionKey);
System.out.print("cipher: ");
for (int i=0; i<cipher.length; i++)
System.out.print(new Integer(cipher[i])+" ");
System.out.println("");
String decrypted = decrypt(cipher, encryptionKey);
System.out.println("decrypt: " + decrypted);
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
return cipher.doFinal(plainText.getBytes("UTF-8"));
}
private static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
return new String(cipher.doFinal(cipherText),"UTF-8");
}
}
Here is my code implementation:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JTextPane;
import Source.AES;
import javax.swing.JTextField;
import javax.swing.JPasswordField;
import javax.swing.JTextArea;
public class first {
private JFrame frame;
private JPasswordField passwordField;
private JTextArea txtrEnterTextHere;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
first window = new first();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public first() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JOptionPane.showMessageDialog(null, "Welcome to Encryption System! ");
JButton btnNewButton = new JButton("Send Info");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String text = txtrEnterTextHere.getText();
String pass = passwordField.getText();
String str = null;
try {
str = new String(AES.encrypt(text, pass));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
txtrEnterTextHere.setText(str);
JOptionPane.showMessageDialog(null, "Your intel has been encrypted!");
}
});
frame.getContentPane().add(btnNewButton, BorderLayout.NORTH);
passwordField = new JPasswordField();
frame.getContentPane().add(passwordField, BorderLayout.SOUTH);
txtrEnterTextHere = new JTextArea();
txtrEnterTextHere.setText("ENTER TEXT HERE AND PASSWORD BELLOW!");
frame.getContentPane().add(txtrEnterTextHere, BorderLayout.CENTER);
}
}
How can I make the variable "str" actually have the value of the encrypted text? I get an error at runtime and I have an empty field... can I change the byte[] to a string?
Update error:
java.lang.IllegalArgumentException: javax.crypto.spec.SecretKeySpec at Source.AES.encrypt(AES.java:41). Null key at (SecretKeySpec.java:96) at first $2.actionPerformed (first.java:62) at javax.swing.DefaultButtonModel.setPressed (unknown source) at javax.swing.DefaultButtonModel.fireActionPerformed (unknown source) ) at javax.swing.AbstractButton$Handler.actionPerformed (unknown source) at javax.swing.DefaultButtonModel.setPressed (unknown source) at javax.swing.AbstractButton$Handler.actionPerformed (unknown source) at javax.swing.JComponent .processMouseEvent (unknown source) at javax.swing.JComponent.processMouseEvent (unknown source) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased (unknown source) at java.awt.Component.processEvent (unknown source) , java.awt.Container.processEvent (unknown source) at java.awt.Container.java.awt.Component.dispatchEventImpl (unknown source). java.awt.LightweightDispatcher. at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source). retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) Unknown source at java.awt.Container.dispatchEventImpl(java.awt.Window.dispatchEventImpl Unknown source of java.awt.Component.dispatchEventImpl (unknown source at java.awt.EventQueue.dispatchEventImpl) at java.awt.EventQueue.access$500 (unknown source) at java.awt.EventQueue$3.run (unknown source) at java.awt.EventQueue$3.run(unknown source) at java.security.AccessController.doPrivileged(native java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(method) method). Java's ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(unknown source), java.awt.EventQueue$4.run(unknown source), java.security.AccessController.doPrivileged(native method), java.awt.EventQueue$4.run (unknown source). security.ProtectionDomain $JavaSecurityAccessImpl.doIntersectionPrivilege (unknown source) in java.awt.
You have several problems here.
You have
Empty key at javax.crypto.spec.SecretKeySpec
an exception because you didn't enter any password.After entering the password, you will get a similar exception
Invalid AES key length: 8 bytes
because the key is expected to be a certain length (see here for more info ).After using the hash to generate the key, you will encounter the following exception -
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
, because your encryption mode does not use padding. you can change it toAES/CBC/PKCS5Padding
Finally, with the following "encrypt" method, you will get what you want:
public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
byte [] hashedPassword = sha.digest(encryptionKey.getBytes("UTF-8"));
hashedPassword = Arrays.copyOf(hashedPassword, 16);
SecretKeySpec key = new SecretKeySpec(hashedPassword, "AES");
cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
return cipher.doFinal(plainText.getBytes("UTF-8"));
}
(*) Of course, in order to decrypt the message, you also have to make similar changes in the "decrypt" method...