chat.menu.CryptMenu.java Source code

Java tutorial

Introduction

Here is the source code for chat.menu.CryptMenu.java

Source

/*
This file is part of JSChat.
    
JSChat is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
JSChat is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with JSChat.  If not, see <http://www.gnu.org/licenses/>.
*/
package chat.menu;

import chat.State;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.misc.BASE64Encoder;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.security.*;
import java.util.HashMap;
import java.util.Map;

import static java.security.Security.addProvider;

/** Utilities Menu */
public class CryptMenu extends JMenu {
    chat.Gui mainFrame;
    /** Used for file encryption */
    static public Key publicKey, privateKey, sessionKey;

    public static Cipher getAsymmetricCipher() throws Exception {
        return Cipher.getInstance("RSA", "BC");// RSA/ECB/PKCS1Padding,RSA
    }

    public static SecretKey getSecretKey(byte[] keyBytes) throws Exception {
        return new SecretKeySpec(keyBytes, "RC4");
    }

    public static Cipher[] getStreamCiphers(SecretKey sessionKey) throws Exception {
        Cipher encrypter = Cipher.getInstance("RC4", "BC");
        encrypter.init(Cipher.ENCRYPT_MODE, sessionKey);
        Cipher decrypter = Cipher.getInstance("RC4", "BC");
        decrypter.init(Cipher.DECRYPT_MODE, sessionKey);
        return new Cipher[] { encrypter, decrypter };
    }

    public static SecretKey getFileSessionKey(byte[] keyBytes) throws Exception {
        byte[] bytes = new byte[32];
        int halfDiff = keyBytes.length - bytes.length;
        System.arraycopy(keyBytes, halfDiff, bytes, 0, bytes.length);
        return new SecretKeySpec(bytes, "AES");
    }

    public static Cipher[] getBlockCiphers() throws Exception {
        Cipher encrypter = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
        Cipher decrypter = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
        return new Cipher[] { encrypter, decrypter };
    }

    /** Used for file encryption */
    public Key symmetricKey, asymmetricKey;
    private int bufSize = 8192;
    int asymmetricStrength = 1024;
    int symmetricStrength = 128;
    IvParameterSpec ivSpec = new IvParameterSpec(new byte[64]);

    JMenuItem secureChannel = new JMenuItem("Secure Channel");
    JMenuItem keyStorePassword = new JMenuItem("Enter KeyStore Password");
    JMenuItem generateKeyStore = new JMenuItem("Generate KeyStore");
    JMenuItem loadKeyStore = new JMenuItem("Load KeyStore");
    JMenuItem exportPublicKey = new JMenuItem("Export Public Key");
    JMenuItem importPublicKey = new JMenuItem("Import Public Key");
    JMenuItem loadPublicKeyFromKS = new JMenuItem("Load Public Key");

    JMenuItem encryptPrivFile = new JMenuItem("Encrypt File (Private)");
    JMenuItem decryptPrivFile = new JMenuItem("Decrypt File (Private)");
    JMenuItem encryptPubFile = new JMenuItem("Encrypt File (Public)");
    JMenuItem decryptPubFile = new JMenuItem("Decrypt File (Public)");

    JMenuItem generateSKey = new JMenuItem("Generate Symmetric Key");
    JMenuItem loadSymmetricKey = new JMenuItem("Load Symmetric Key");
    JMenuItem decryptSFile = new JMenuItem("Decrypt file");
    JMenuItem encryptSFile = new JMenuItem("Encrypt file");
    JMenuItem getSHA = new JMenuItem("Message Digest (SHA-1)");
    JMenuItem getMD5 = new JMenuItem("Message Digest (MD5)");
    JMenuItem getBase64 = new JMenuItem("Base 64");

    public CryptMenu(final chat.Gui mainFrame) {
        super("Crypt");

        addProvider(new BouncyCastleProvider());
        this.mainFrame = mainFrame;

        secureChannel.setEnabled(false);
        add(secureChannel);
        secureChannel.addActionListener(mainFrame);

        add(keyStorePassword);
        keyStorePassword.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                new PwdDialog(mainFrame);
            }

            class PwdDialog extends PasswordDialog {
                public PwdDialog(JFrame parent) {
                    super(parent);
                }

                @Override
                public void doClose() {
                    if (pwdField.getPassword().length > 0) {
                        State.password = pwdField.getPassword();
                        keyStorePassword.setEnabled(false);
                        generateKeyStore.setEnabled(true);
                        loadKeyStore.setEnabled(true);
                    }
                    super.doClose();
                }
            }
        });

        generateKeyStore.setEnabled(false);
        add(generateKeyStore);
        generateKeyStore.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    System.out.println("Initializing the KeyPairGenerator...");
                    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
                    kpg.initialize(asymmetricStrength, new SecureRandom());
                    System.out.println("Generating the key pair...");
                    KeyPair pair = kpg.genKeyPair();
                    Map<String, Key> keyStore = new HashMap<String, Key>();
                    keyStore.put("myPrivateKey", pair.getPrivate());
                    keyStore.put("myPublicKey", pair.getPublic());

                    saveKeyStore(keyStore);
                } catch (Exception exc) {
                    exc.printStackTrace();
                }
            }
        });

        loadKeyStore.setEnabled(false);
        add(loadKeyStore);
        loadKeyStore.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {

                    Cipher cipher = CryptMenu.getBlockCiphers()[1];
                    cipher.init(Cipher.DECRYPT_MODE, State.getKeyFromPassword());
                    CipherInputStream cis = new CipherInputStream(new FileInputStream("jschat.keyStore"), cipher);

                    ObjectInput in = new ObjectInputStream(cis);
                    State.keyStore = (Map<String, Key>) in.readObject();
                    in.close();
                    privateKey = State.keyStore.get("myPrivateKey");
                    exportPublicKey.setEnabled(true);
                    importPublicKey.setEnabled(true);
                    loadPublicKeyFromKS.setEnabled(true);
                } catch (Exception exc) {
                    exc.printStackTrace();
                }
            }
        });

        loadPublicKeyFromKS.setEnabled(false);
        add(loadPublicKeyFromKS);
        loadPublicKeyFromKS.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                new SelKeyDialog(mainFrame, State.keyStore.keySet().toArray(new String[] {}));
            }

            class SelKeyDialog extends SelectKeyDialog {
                public SelKeyDialog(JFrame parent, String[] list) {
                    super(parent, list);
                }

                @Override
                public void doClose() {
                    String selectedItem = (String) jComboBox.getSelectedItem();
                    if (selectedItem != null) {
                        publicKey = State.keyStore.get(selectedItem);
                        if (privateKey != null) {
                            mainFrame.localKeysLoaded();
                            secureChannel.setEnabled(true);
                        }
                        encryptPubFile.setEnabled(true);
                        decryptPubFile.setEnabled(true);
                    }
                    super.doClose();
                }
            }
        });

        exportPublicKey.setEnabled(false);
        add(exportPublicKey);
        exportPublicKey.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("public.key"));
                    out.writeObject(State.keyStore.get("myPublicKey"));
                    out.close();
                } catch (Exception exc) {
                    exc.printStackTrace();
                }
            }
        });

        importPublicKey.setEnabled(false);
        add(importPublicKey);
        importPublicKey.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
                    fc.setDialogTitle("Load Public Key");
                    int returnValue = fc.showOpenDialog(mainFrame.getContentPane());
                    if (returnValue == JFileChooser.APPROVE_OPTION) {
                        try {
                            ObjectInputStream in = new ObjectInputStream(new FileInputStream(fc.getSelectedFile()));
                            publicKey = (Key) in.readObject();
                            in.close();

                            State.keyStore.put(fc.getSelectedFile().getName(), publicKey);
                            saveKeyStore(State.keyStore);
                        } catch (Exception exc) {
                            exc.printStackTrace();
                        }
                    }
                } catch (Exception exc) {
                    exc.printStackTrace();
                }
            }
        });

        addSeparator();

        encryptPrivFile.setEnabled(false);
        add(encryptPrivFile);
        encryptPrivFile.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                enCodeIt("RSA", true, privateKey);
            }
        });

        decryptPrivFile.setEnabled(false);
        add(decryptPrivFile);
        decryptPrivFile.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                enCodeIt("RSA", false, privateKey);
            }
        });

        encryptPubFile.setEnabled(false);
        add(encryptPubFile);
        encryptPubFile.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                enCodeIt("RSA", true, publicKey);
            }
        });

        decryptPubFile.setEnabled(false);
        add(decryptPubFile);
        decryptPubFile.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                enCodeIt("RSA", false, publicKey);
            }
        });

        addSeparator();

        add(generateSKey);
        generateSKey.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
                fc.setDialogTitle("Save symmetric key as");
                int returnValue = fc.showSaveDialog(mainFrame.getContentPane());
                if (returnValue == JFileChooser.APPROVE_OPTION) {
                    try {
                        KeyGenerator generator = KeyGenerator.getInstance("AES", "BC");
                        generator.init(symmetricStrength, new SecureRandom());
                        symmetricKey = generator.generateKey();
                        FileOutputStream fos = new FileOutputStream(fc.getSelectedFile());
                        fos.write(symmetricKey.getEncoded());
                        fos.close();
                    } catch (Exception exc) {
                        exc.printStackTrace();
                    }
                }
            }
        });

        add(loadSymmetricKey);

        loadSymmetricKey.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
                fc.setDialogTitle("Load Symmetric Key");
                int returnValue = fc.showOpenDialog(mainFrame.getContentPane());
                if (returnValue == JFileChooser.APPROVE_OPTION) {
                    try {
                        FileInputStream fis = new FileInputStream(fc.getSelectedFile());
                        byte[] keyBytes = new byte[(int) fc.getSelectedFile().length()];
                        int offSet = 0;
                        int numRead;
                        while (offSet != keyBytes.length
                                && (numRead = fis.read(keyBytes, offSet, keyBytes.length - offSet)) != -1) {
                            offSet += numRead;
                            System.out.println("Read " + numRead);
                        }
                        fis.close();
                        System.out.println("Read in key");
                        SecretKeyFactory skf = SecretKeyFactory.getInstance("AES", "BC");
                        symmetricKey = skf.generateSecret(new SecretKeySpec(keyBytes, "AES"));
                        System.out.println("Converted to AESKey");
                        encryptSFile.setEnabled(true);
                        decryptSFile.setEnabled(true);
                    } catch (Exception exc) {
                        exc.printStackTrace();
                    }
                }
            }
        });

        encryptSFile.setEnabled(false);
        add(encryptSFile);
        encryptSFile.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                enCodeIt("AES/CBC/PKCS5Padding", true, symmetricKey, ivSpec);
                /*
                               JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
                               fc.setDialogTitle("Choose file to encrypt");
                               int returnValue = fc.showOpenDialog(mainFrame.getContentPane());
                               if (returnValue==JFileChooser.APPROVE_OPTION) {
                                  try {
                 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding","BC");
                 IvParameterSpec spec = new IvParameterSpec(iv);
                 cipher.init(Cipher.ENCRYPT_MODE, symmetricKey, spec);
                 FileInputStream fis = new FileInputStream(fc.getSelectedFile());
                 FileOutputStream fos = new FileOutputStream(fc.getSelectedFile()+".enc");
                 CipherOutputStream cos = new CipherOutputStream(fos, cipher);
                 byte[] buf = new byte[bufSize];
                 int numRead;
                 while ((numRead=fis.read(buf))!=-1)
                    cos.write(buf,0,numRead);
                 fis.close();
                 cos.close();
                                  } catch (Exception exc) {
                 exc.printStackTrace();
                                  }
                               }
                */
            }
        });

        decryptSFile.setEnabled(false);
        add(decryptSFile);
        decryptSFile.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                enCodeIt("AES/CBC/PKCS5Padding", false, symmetricKey, ivSpec);
                /*
                               JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
                               fc.setDialogTitle("Choose file to decrypt");
                               int returnValue = fc.showOpenDialog(mainFrame.getContentPane());
                               if (returnValue==JFileChooser.APPROVE_OPTION) {
                                  try {
                 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding","BC");
                 IvParameterSpec spec = new IvParameterSpec(iv);
                 cipher.init(Cipher.DECRYPT_MODE, symmetricKey, spec);
                 FileInputStream fis = new FileInputStream(fc.getSelectedFile());
                 FileOutputStream fos = new FileOutputStream(fc.getSelectedFile()+".dec");
                 CipherOutputStream cos = new CipherOutputStream(fos, cipher);
                 byte[] buf = new byte[bufSize];
                 int numRead;
                 while ((numRead=fis.read(buf))!=-1)
                    cos.write(buf,0,numRead);
                 fis.close();
                 cos.close();
                                  } catch (Exception exc) {
                 exc.printStackTrace();
                                  }
                               }
                */
            }
        });

        addSeparator();

        add(getSHA);
        getSHA.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
                fc.setDialogTitle("Choose file");
                int returnValue = fc.showOpenDialog(mainFrame.getContentPane());
                if (returnValue == JFileChooser.APPROVE_OPTION) {
                    try {
                        MessageDigest md = MessageDigest.getInstance("SHA-1", "BC");
                        FileInputStream fis = new FileInputStream(fc.getSelectedFile());
                        DigestInputStream dis = new DigestInputStream(fis, md);
                        byte[] buf = new byte[bufSize];
                        while (dis.read(buf) != -1)
                            ;
                        byte[] raw = md.digest();
                        fis.close();

                        new SelectDialog(mainFrame, "SHA-1", false, "SHA-1", fc.getSelectedFile(), "sha", raw);
                    } catch (Exception exc) {
                        exc.printStackTrace();
                    }
                }
            }
        });

        add(getMD5);
        getMD5.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
                fc.setDialogTitle("Choose file");
                int returnValue = fc.showOpenDialog(mainFrame.getContentPane());
                if (returnValue == JFileChooser.APPROVE_OPTION) {
                    try {
                        MessageDigest md = MessageDigest.getInstance("MD5", "BC");
                        FileInputStream fis = new FileInputStream(fc.getSelectedFile());
                        DigestInputStream dis = new DigestInputStream(fis, md);
                        byte[] buf = new byte[bufSize];
                        while (dis.read(buf) != -1)
                            ;
                        byte[] raw = md.digest();
                        fis.close();

                        new SelectDialog(mainFrame, "MD5", false, "MD5", fc.getSelectedFile(), "md5", raw);
                    } catch (Exception exc) {
                        exc.printStackTrace();
                    }
                }
            }
        });

        add(getBase64);
        getBase64.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
                fc.setDialogTitle("Choose file");
                int returnValue = fc.showOpenDialog(mainFrame.getContentPane());
                if (returnValue == JFileChooser.APPROVE_OPTION) {
                    try {
                        FileInputStream fis = new FileInputStream(fc.getSelectedFile());
                        OutputStreamWriter osw = new OutputStreamWriter(
                                new FileOutputStream(fc.getSelectedFile() + ".b64"), "UTF8");
                        BASE64Encoder enc = new BASE64Encoder();
                        String base64;
                        byte[] bufRead;
                        byte[] buf = new byte[bufSize];
                        int numRead;
                        while ((numRead = fis.read(buf)) != -1) {
                            bufRead = new byte[numRead];
                            System.arraycopy(buf, 0, bufRead, 0, numRead);
                            base64 = enc.encode(bufRead);
                            osw.write(base64);
                        }
                        fis.close();
                        osw.close();
                    } catch (Exception exc) {
                        exc.printStackTrace();
                    }
                }
            }
        });
    }

    private void saveKeyStore(Map<String, Key> keyStore) throws Exception {
        Cipher cipher = CryptMenu.getBlockCiphers()[0];
        cipher.init(Cipher.ENCRYPT_MODE, State.getKeyFromPassword());
        CipherOutputStream cos = new CipherOutputStream(new FileOutputStream("jschat.keyStore"), cipher);
        ObjectOutputStream out = new ObjectOutputStream(cos);
        out.writeObject(keyStore);
        out.close();
    }

    void enCodeIt(String algorithm, boolean encrypt, Key key) {
        enCodeIt(algorithm, encrypt, key, null);
    }

    void enCodeIt(String algorithm, boolean encrypt, Key key, IvParameterSpec ivSpec) {
        JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
        fc.setDialogTitle("Choose file to " + (encrypt ? "encrypt." : "decrypt."));
        int returnValue = fc.showOpenDialog(mainFrame.getContentPane());
        if (returnValue == JFileChooser.APPROVE_OPTION) {
            try {
                Cipher cipher = Cipher.getInstance(algorithm, "BC");
                int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
                if (ivSpec != null)
                    cipher.init(mode, key, ivSpec);
                else
                    cipher.init(mode, key);
                FileInputStream fis = new FileInputStream(fc.getSelectedFile());
                FileOutputStream fos = new FileOutputStream(fc.getSelectedFile() + (encrypt ? ".enc" : ".dec"));
                CipherOutputStream cos = new CipherOutputStream(fos, cipher);
                byte[] buf = new byte[bufSize];
                int numRead;
                while ((numRead = fis.read(buf)) != -1)
                    cos.write(buf, 0, numRead);
                fis.close();
                cos.close();
            } catch (Exception exc) {
                exc.printStackTrace();
            }
        }
    }
}