import java.util.Arrays;
import java.util.*;
import java.io.*;
class theKey implements java.io.Serializable {
    protected int[]  p; //The permutation
    protected byte[] m; //The mask
}
public class Akeystore16 {
    protected int[]  p;
    protected    byte[] m;

    public Akeystore16(String keyfile){
        try {
            ObjectInputStream in = new ObjectInputStream(new FileInputStream(keyfile));
            theKey tK=(theKey)(in.readObject());
            in.close();
            p=tK.p;
            m=tK.m;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private  byte[] permute(byte[] s, int[] p ){
        byte top=(byte)240; //not used in this version
        byte bottom=(byte)15;
        byte[] start=new byte[16];
        for (int i=0;i<8;i++) {
            start[2*i]=getTop(s[i]);
            start[2*i+1]=(byte)(s[i]&bottom);
        }
        byte[] encode16=new byte[16];
        for (int i=0;i<16;i=i+1) {
            encode16[i]=start[p[i]];
        }
        byte[] encoded=new byte[8];
        for (int i=0;i<8;i++) {
            encoded[i]=(byte)((encode16[2*i]<<4)+encode16[2*i+1]);
        }
        return encoded;
    }
    private byte[] mask(byte[] theBytes,byte[] theMask){
        byte[] theEncodedBytes=new byte[8];
        for (int i=0;i<8;i=i+1) {
            theEncodedBytes[i]=(byte)(theBytes[i]^theMask[i]);
        }
        return theEncodedBytes;
    }

    public String Encode(String s){
        byte[] theBytes=new byte[s.length()];;
        try {
            theBytes = s.getBytes( "ISO-8859-1");
        } catch (Exception e) {
            System.out.println("can't do that");
        }
        byte[] theMaskedBytes=mask(theBytes,m);
        byte[] ThePermutedBytes=permute(theMaskedBytes,p);
        byte[] theNewBytes=mask(ThePermutedBytes,m);
        try {
            return new String(theNewBytes, "ISO-8859-1");
        } catch (Exception e) {
            System.out.println("can't do that either");
        }
        return "bah";
    }
    public String Decode(String s){
        return Encode(s);
    }
    public byte getTop(byte tester){
        //byte shifted=0;
        int the_part=0;
        int all=0;
        for (int i=4;i<8;i++) {
            the_part=(GetBit(tester,i))?(int)Math.pow(2,(i-4)) :0;
            // Is the bit in position i 1 or 0
            // If a 1 add 2 to the i-4.
            all=all+the_part;
        }
        return(byte)all ;
    }
    static boolean GetBit(byte thebyte, int position){
        return(1 == ((thebyte >> position) & 1));
    }
}