迷你AES Java问题

时间:2019-03-28 11:51:57

标签: java encryption null

因此,在Java上为minu-AES运行某些代码时遇到一些问题。每次我运行代码时,都会在线程“ main”中给空异常java.lanf.stringIndexOutOfBoundsException:字符串索引超出范围:8

我想知道这是否可能是内存问题。 当前正在运行的netbeans 8.2

代码在实现类之前就起作用了。

package miniaestesting;

import java.util.*;

class Tables {


    public Tables() {
    }

    public HashMap fillSubTable(HashMap emptyTable, boolean isInverse) {
        if (isInverse == false) {
            emptyTable.put(0b0000, 0b1110);
            emptyTable.put(0b0001, 0b0100);
            emptyTable.put(0b0010, 0b1101);
            emptyTable.put(0b0011, 0b0001);
            emptyTable.put(0b0100, 0b0010);
            emptyTable.put(0b0101, 0b1111);
            emptyTable.put(0b0110, 0b1011);
            emptyTable.put(0b0111, 0b1000);
            emptyTable.put(0b1000, 0b0011);
            emptyTable.put(0b1001, 0b1010);
            emptyTable.put(0b1010, 0b0110);
            emptyTable.put(0b1011, 0b1100);
            emptyTable.put(0b1100, 0b0101);
            emptyTable.put(0b1101, 0b1001);
            emptyTable.put(0b1110, 0b0000);
            emptyTable.put(0b1111, 0b0111);
        }
        //Call the .put method, fill the HashMap with the NibbleSub table

        else {
            emptyTable.put(0b0000, 0b1110);
            emptyTable.put(0b0001, 0b0011);
            emptyTable.put(0b0010, 0b0100);
            emptyTable.put(0b0011, 0b1000);
            emptyTable.put(0b0100, 0b0001);
            emptyTable.put(0b0101, 0b1100);
            emptyTable.put(0b0110, 0b1010);
            emptyTable.put(0b0111, 0b1111);
            emptyTable.put(0b1000, 0b0111);
            emptyTable.put(0b1001, 0b1101);
            emptyTable.put(0b1010, 0b1001);
            emptyTable.put(0b1011, 0b0110);
            emptyTable.put(0b1100, 0b1011);
            emptyTable.put(0b1101, 0b0010);
            emptyTable.put(0b1110, 0b0000);
            emptyTable.put(0b1111, 0b0101);
        }

        return emptyTable;
    }

    public int[][] fillHexTable() {
        int[][] table = {
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF},
                {0, 2, 4, 6, 8, 0xA, 0xC, 0xE, 3, 1, 7, 5, 0xB, 9, 0xF, 0xD},
                {0, 3, 6, 5, 0xC, 0xF, 0xA, 9, 0xB, 8, 0xD, 0xE, 7, 4, 1, 2},
                {0, 4, 8, 0xC, 3, 7, 0xB, 0xF, 6, 2, 0xE, 0xA, 5, 1, 0xD, 9},
                {0, 5, 0xA, 0xF, 7, 2, 0xD, 8, 0xE, 0xB, 4, 1, 9, 0xC, 3, 6},
                {0, 6, 0xC, 0xA, 0xB, 0xD, 7, 1, 5, 3, 9, 0xF, 0xE, 8, 2, 4},
                {0, 7, 0xE, 9, 0xF, 8, 1, 6, 0xD, 0xA, 3, 4, 2, 5, 0xC, 0xB},
                {0, 8, 3, 0xB, 6, 0xE, 5, 0xD, 0xC, 4, 0xF, 7, 0xA, 2, 9, 1},
                {0, 9, 1, 8, 2, 0xB, 3, 0xA, 4, 0xD, 5, 0xC, 6, 0xF, 7, 0xE},
                {0, 0xA, 7, 0xD, 0xE, 4, 9, 3, 0xF, 5, 8, 2, 1, 0xB, 6, 0xC},
                {0, 0xB, 5, 0xE, 0xA, 1, 0xF, 4, 7, 0xC, 2, 9, 0xD, 6, 8, 3},
                {0, 0xC, 0xB, 7, 5, 9, 0xE, 2, 0xA, 6, 1, 0xD, 0xF, 3, 4, 8},
                {0, 0xD, 9, 4, 1, 0xC, 8, 5, 2, 0xF, 0xB, 6, 3, 0xE, 0xA, 7},
                {0, 0xE, 0xF, 1, 0xD, 3, 2, 0xC, 9, 7, 6, 8, 4, 0xA, 0xB, 5},
                {0, 0xF, 0xD, 2, 9, 6, 4, 8, 1, 0xE, 0xC, 3, 8, 7, 5, 0xA}
        };
        // Return the hex-multiplication table used in MixColumns
        return table;
    }
}


class Substitutions {
    private Tables tables;
    private HashMap<Integer, Integer> subTable;

    public Substitutions() {
        this.tables = new Tables();
        this.subTable = new HashMap<>();
    }

    public int keyNibbleSub(int nibble) {
        tables.fillSubTable(subTable, false); // Call a helper method to fill the HashMap with key-value pairs

        System.out.println(subTable.get(nibble)); // Get the substitution value for the nibble and return it
        return 5;
    }


    public int[][] nibbleSub(int[][] cipherState, boolean isInverse) {
        int[][] nextCipherState = new int[2][2]; // Declare and initialise empty 2x2 array

        tables.fillSubTable(subTable, isInverse); // Call a helper method to fill the HashMap with key-value pairs

        for (int row = 0; row < 1; row++) {
            for (int col = 0; col < 1; col++) {
                // For each element in block


                nextCipherState[row][col] = subTable.get(cipherState[row][col]);
                // Call the .get method on the HashMap, using the element as a key-lookup
                // Assign the returned element to the index in returnBlock
            }
        }
        return nextCipherState;
    }

    public int getKeyNibbleSub(int nibble) {
        return keyNibbleSub(nibble);
    }

    public int[][] getNibbleSub(int[][] cipherState, boolean isInverse) {
        return
                nibbleSub(cipherState, isInverse);
    }


}


class KeySet {
    //-----------------------------//Fields//-----------------------------//
    private int[][] key_0, key_1, key_2;
    private Substitutions substitutions;
    private Tables tables;

    //-----------------------------//Constructor//-----------------------------//
    public KeySet(int[][] startingKey) {
        this.substitutions = new Substitutions();
        this.key_0 = startingKey;
        this.key_1 = genKey(key_0, 1);
        this.key_2 = genKey(key_1, 2);

    }

    //-----------------------------//Methods//-----------------------------//
    private int[][] genKey(int[][] key, int roundConst) {
        int[][] newKey = new int[2][2]; // Declare an empty 2x2 array to store the new key
        newKey[0][0] = key[0][0] ^ substitutions.keyNibbleSub(key[1][1]) ^
                roundConst;
        // For the first nibble in the new key,
        // XOR the first value in the given key
        // with the nibbleSub of the final value in the given key
        //, and with the rounding constant variable
        newKey[0][1] = key[0][1] ^ newKey[0][0];
        newKey[1][0] = key[1][0] ^ newKey[0][1];
        newKey[1][1] = key[1][1] ^ newKey[1][0];
        // Generate the other three nibbles
        return newKey;
    }

    //----Getter methods for full implementation---//

    public int[][] getKey_0() {
        return key_0;
    }

    public int[][] getKey_1() {
        return key_1;
    }

    public int[][] getKey_2() {
        return key_2;
    }

}


class MiniAES {
    private KeySet keys;
    private String startingString;

    private String finalString;
    private int[][] character;
    private int[][] cipherState;

    private Substitutions substitutions;
    private Tables tables;

    public MiniAES(String startingString, String startKey) {
        this.substitutions = new Substitutions();
        this.tables = new Tables();
        this.startingString = startingString;
        this.keys = new KeySet(convertToArray(startKey));
    }

    public String encryptString() {
        //ystem.out.println(startingString);

        for (int i = 0; i < this.startingString.length() - 1; i++) {

            character =
                    convertToArray(Integer.toBinaryString(startingString.charAt(i)));

            cipherState = encryptChar(character);

            finalString = finalString + convertToString(cipherState);


        }

        return finalString;
    }

    public static String convertToString(int[][] array) {
        String[][] toFill = new String[2][2];
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[0].length; j++) {

                toFill[i][j] = Integer.toString(array[i][j]);

                while (toFill[i][j].length() <= 3) {
                    toFill[i][j] = "0" +
                            toFill[i][j];
                }
            }
        }

        String charAsBinaryString = toFill[0][0] + toFill[0][1] + toFill[1][0]
                + toFill[1][1];

        int asInteger = Integer.parseInt(charAsBinaryString, 2);
        String charAsString = Character.toString((char) asInteger);

        return charAsString;
    }

    public static int[][] convertToArray(String toConvert) {
        int[][] newBlock = new int[2][2];

        newBlock[0][0] = Integer.parseInt(toConvert.substring(0, 4));
        newBlock[0][1] = Integer.parseInt(toConvert.substring(4, 8));
        newBlock[1][0] = Integer.parseInt(toConvert.substring(8, 12));
        newBlock[1][1] = Integer.parseInt(toConvert.substring(12, 16));

        return newBlock;

    }

    private int[][] encryptChar(int[][] character) {
        addRoundKey(character, keys.getKey_0());
        cipherState = substitutions.nibbleSub(cipherState, false);

        shiftRows();
        mixColumns();

        addRoundKey(cipherState, keys.getKey_1());
        cipherState = substitutions.nibbleSub(cipherState, false);

        shiftRows();
        addRoundKey(cipherState, keys.getKey_2());

        return cipherState;
    }


    private void addRoundKey(int[][] cipherState, int[][] key) {
        int[][] nextCipherState = new int[2][2]; // Declare and initialise an empty 2x2 array

        for (int row = 0; row < cipherState.length; row++) {
            for (int col = 0; col < cipherState[0].length; col++) {
                // For each element in  cipherState
                nextCipherState[row][col] = cipherState[row][col] ^ key[row]
                        [col]; // XOR it with the corresponding element in key

                // Assign it to the same index in nextCipherState
            }
        }
        this.cipherState = nextCipherState;
    }

    private void shiftRows() {
        int[][] nextCipherState = new int[2][2]; // Declare and initialise new  array

        nextCipherState[0][0] = this.cipherState[0][0];
        nextCipherState[0][1] = this.cipherState[0][1];
        //Copy the values from cipherState into the top row of the new array

        nextCipherState[1][0] = this.cipherState[1][1];
        nextCipherState[1][1] = this.cipherState[1][0];
        //Copy the values from cipherState into the bottom row of the new array, in reverse order

        this.cipherState = nextCipherState;
    }

    private void mixColumns() {
        int[][] nextCipherState = new int[2][2]; // Declare and initialise empty 2x2 array

        nextCipherState[0][0] = hexSubstitution(this.cipherState[0][0],
                this.cipherState[1][0], 0);
        nextCipherState[1][0] = hexSubstitution(this.cipherState[0][0],
                this.cipherState[1][0], 1);
        nextCipherState[0][1] = hexSubstitution(this.cipherState[0][1],
                this.cipherState[1][1], 0);
        nextCipherState[01][1] = hexSubstitution(this.cipherState[0][1],
                this.cipherState[1][1], 1);

        this.cipherState = nextCipherState;
    }

    private int hexSubstitution(int topRowElement, int bottomRowElement, int
            constRow) {
        int[][] hexTable = tables.fillHexTable(); // Declare an empty 2d array and call the getHexTable() helper method to fill it
        // Due to the large size of the hex table, this is implemented for readability.
        int[][] constantMatrix = {
                {0b0011, 0b0010},
                {0b0010, 0b0011}}; // declare and fill the 2d array which stores the constant matrix

        int hexCol, XOR_operand_1, XOR_operand_2; // Declare variables

        hexCol = constantMatrix[constRow][0]; // Get index for the hex table  lookup
        XOR_operand_1 = hexTable[hexCol][topRowElement]; // Find the appropriate element in hexTable and assign to XOR_operand_1

        hexCol = constantMatrix[constRow][1]; // // Get index for the hex table lookup
        XOR_operand_2 = hexTable[hexCol][bottomRowElement]; // Find the appropriate elemen tin hexTable and assign to XOR_operand_2

        return XOR_operand_1 ^ XOR_operand_2; // XOR the two operands and return the result
    }


}

package miniaestesting;

public class MiniAESTesting {
    public static void main(String[] args) {


        int[][] startKey = {
                {0b0011, 0b1001},
                {0b0110, 0b0111}};


        MiniAES encryption1 = new MiniAES("Hello", "0010101100100011");
        System.out.println(encryption1.encryptString());
    }
}

0 个答案:

没有答案