import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.InvalidKeyException;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.crypto.Cipher;
import java.security.Key;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import java.io.ByteArrayOutputStream;

public class JavaSecretKeyPublicKeyDecryption {
    
    public JavaSecretKeyPublicKeyDecryption() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException,
            BadPaddingException, ClassNotFoundException, InvalidKeyException, IllegalBlockSizeException  {
        
        String algorithmName = "AES";
        Cipher cipher = Cipher.getInstance(algorithmName);
        
        // Read your private key
        ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream("BillsRSAPrivateKey"));
        PrivateKey privKey = (PrivateKey)keyIn.readObject();
        //System.out.println(privKey);
        keyIn.close();
        
        while(true) {
            String fileName = JOptionPane.showInputDialog("Enter (Encrypted) filename","GenerateRSAPublicPrivateKeyPair.java");
            if( fileName == null ) break;
            FileInputStream in = new FileInputStream("Encrypted" + fileName);
            
            // Read encrypted wrapped secretKey
            // Read wrapped key length and convert from hex
            String len = "";
            for(int i = 0; i < 4; i++ ) {
                byte byte1 = (byte)in.read();
                byte byte2 = (byte)in.read();
                len = (char)byte1 + "" + (char)byte2 + len;
            } // end for
            int inLen = Integer.parseInt(len,16);
            
            // Read wrapped key and convert from hex
            byte[] wrappedKey = new byte[inLen];
            String keyString = "";
            for( int i = 0; i < inLen; i++ ) {
                byte byte1 = (byte)in.read();
                byte byte2 = (byte)in.read();
                String hex = (char)byte1 + "" + (char)byte2;
                wrappedKey[i] = (byte)Integer.parseInt(hex,16);
            } // end while
            
            // Unwrap the secret key
            Cipher keyCipher = Cipher.getInstance("RSA");
            keyCipher.init(Cipher.UNWRAP_MODE,privKey);
            Key secretKey = keyCipher.unwrap(wrappedKey,algorithmName,Cipher.SECRET_KEY);
            
            // Decrypt File
            FileOutputStream out = new FileOutputStream("Decrypted" + fileName);
            cipher.init(Cipher.DECRYPT_MODE,secretKey);
            decryptFile(in,cipher,out);
            
            String code = getFile("Encrypted" + fileName);
            String decode = getFile("Decrypted" + fileName);
            
            // Show encrypted file and decrypted file
            String outString = "Coded message =\n"+code+ "\n\nDecoded message = \n"+decode;
            JTextArea outArea = new JTextArea(outString,30,60);
            JOptionPane.showMessageDialog(null,new JScrollPane(outArea));
        } // end while
        
    }// end JavaSecretKeyPublicKeyEncryption
    
    public static void main(String[] a) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException,
            BadPaddingException, ClassNotFoundException, InvalidKeyException, IllegalBlockSizeException {
        new JavaSecretKeyPublicKeyDecryption();
        System.exit(0);
    } // end main
    
    public void decryptFile(FileInputStream in, Cipher cipher, FileOutputStream out) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException,
            BadPaddingException, ClassNotFoundException, InvalidKeyException, IllegalBlockSizeException  {
        ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
        String encryptedString = "";
        int next;
        while( (next = in.read()) != -1 ) {
            if( (char)next == '\n' ) next = in.read();
            if( next == -1 ) break;
            byte nextByte1 = (byte)next;
            byte nextByte2 = (byte)in.read();
            String decodeByte = (char)nextByte1 + "" + (char)nextByte2;
            byteBuffer.write((byte)Integer.parseInt(decodeByte,16));
        } // end while
        byte[] messageBytes = byteBuffer.toByteArray();
        byte[] outBytes = cipher.doFinal(messageBytes);
        for( int i = 0; i < outBytes.length; i++ ) {
            out.write((byte)outBytes[i]);
        } // end for
        in.close();
        out.close();
    } // end decryptFile
    
    String getFile(String fileName) throws IOException {
        FileInputStream in = new FileInputStream(fileName);
        int next;
        StringBuffer message = new StringBuffer();
        while( (next = in.read()) != -1 ) {
            byte nextByte = (byte)next;
            message.append((char)nextByte);
        } // end while
        in.close();
        return message.toString();
    }  // end getMessage
    
    public String convertToHex(byte b) {
        String hex = Integer.toString(b&0xFF,16).toUpperCase();
        if( hex.length() == 1 ) hex = "0" + hex;
        return hex;
    } // end convertToHex
    
} // end JavaSecretKeyPublicKeyDecryption
