I've done a lot of griping about how there's no memo encryption implemented on the frontends I use. Last night I decided to stop griping and write some code about it. I made a laser-focused, no frills whatsoever, desktop application that (hopefully) anyone can use to encrypt transfer memos, or just about whatever text they like.
The source will be included near the end of this post, so if you want to audit it or tell me how it could be improved I'd love to hear from you.
As you can see the form is very minimal. One needs only provide an encryption key in the form of any text, input the cyphertext or cleartext, and click the corresponding button to encrypt or decrypt the message. This is an AES implementation, which means it's symmetric key encryption. In plain English that means that the same key is used for encrypting and decrypting a given message. I will be working on another version that uses a Diffie-Hellman key exchange protocol soon.
While this utility can provide privacy against eavesdropping it, like virtually any cryptosystem, is not completely bulletproof. Even someone with cryptography know-how can't decrypt your messages without the key, but state-level actors and the like could probably break this encryption. AES is actually used in the real world, such as for WiFi security, but I wouldn't stake my life on this application. I'm not liable for any misadventures you might get into using this software. Protect yourself, don't be foolish.
However you end up using it I hope you enjoy it, and maybe you'll even get some utility out of it. If I can provide one person with even marginally enhanced privacy it's more than worth it in my book. I'd probably break even with just a laugh.
I'll start with the class that handles the AES protocol.
package MemoEncryptor;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class AES {
private static SecretKeySpec secret;//the secret encryption key
private static byte[] keybytes;//a container for it's bytes
private static void setkey(String keystring){//function to initialize the encryption key given a passphrase string
MessageDigest sha = null;//declare hash object for turning passphrase to key
try{
keybytes = keystring.getBytes();//turn passphrase to bytes
sha = MessageDigest.getInstance("SHA-1");//initialize hash algorithm
keybytes = sha.digest(keybytes);//do hashing
keybytes = Arrays.copyOf(keybytes, 16);//ensure proper length of byte array
secret = new SecretKeySpec(keybytes, "AES");//construct AES encryption key object
}catch (Exception e){
System.out.println("Error setting key: " + e.toString());
}
}
public static String encrypt(String cleartext, String key){//encrypt a given text with a given passphrase
try{
setkey(key);//turn passphrase to AES encryption key
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");//instantiate AES object
aes.init(Cipher.ENCRYPT_MODE, secret);//initialize AES instance for encryption with the encryption key
return Base64.getEncoder().encodeToString(aes.doFinal(cleartext.getBytes()));//return AES encrypted string
}catch (Exception e){
System.out.println("Error encrypting: " + e.toString());
}
return null;
}
public static String decrypt(String ciphertext, String key){//decrypt a given text with a given passphrase. mostly as above except...
try {
setkey(key);
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
aes.init(Cipher.DECRYPT_MODE, secret);//...initialize for decryption...
return new String(aes.doFinal(Base64.getDecoder().decode(ciphertext)));//...and return decrypted string
} catch (Exception e){
System.out.println("Error decrypting: " + e.toString());
}
return null;
}
}
Then there's the class that handles that cute little swing window.
package MemoEncryptor;import javax.swing.;
import java.awt.;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class GuiHandler implements ActionListener{
JFrame frame = new JFrame("Symmetric Key Memo Encryptor");
final JTextField keyin = new JTextField("Put the encryption key here. These boxes resize to fit contents.");
final JTextField memoclear = new JTextField("Put memo cleartext here, or it will appear here when decrypting.");
final JTextField memocypher = new JTextField("Put memo cyphertext here, or it will appear here when encrypting");
final JButton encryptbutton = new JButton("Encrypt");
final JButton decryptbutton = new JButton("Decrypt");GuiHandler(){ init(); } public void init(){//place components on swing window, and set starting dimensions frame.setPreferredSize(new Dimension(500,150)); frame.setLayout(new FlowLayout()); frame.getContentPane().add(keyin); frame.getContentPane().add(memoclear); frame.getContentPane().add(memocypher); frame.getContentPane().add(encryptbutton); frame.getContentPane().add(decryptbutton); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); encryptbutton.addActionListener(this);//make buttons produce actions when clicked decryptbutton.addActionListener(this); } @Override public void actionPerformed(ActionEvent actionEvent) {//if an action is caught String keystring, cipherstring, clearstring; keystring = keyin.getText();//fill internal variables from textfields cipherstring = memocypher.getText(); clearstring = memoclear.getText(); if(actionEvent.getSource().equals(encryptbutton)){//detect which button was pressed and do cooresponding action System.out.println("Encrypt button pressed."); cipherstring = AES.encrypt(clearstring, keystring); } else if(actionEvent.getSource().equals(decryptbutton)){ System.out.println("Decrypt button pressed."); clearstring = AES.decrypt(cipherstring, keystring); } memocypher.setText(cipherstring);//post results to swing window memoclear.setText(clearstring); }}
Not sure why there's a subwindow in that code box, but moving on there's the tiny main class. This is the execution entry point.
package MemoEncryptor;public class Main {
public static void main(String[] args) {
GuiHandler window = new GuiHandler();//make a new GUI.
}
}