Java基于原理的原生矩阵实现的AES加密(不调库)

本文展示了AES加密的详细实现过程,包括AES-128-128的密钥扩展、轮密钥加、字节替换、行移位、列混合等步骤。代码涵盖从输入字符串到加密结果的完整流程,使用Java实现,同时提供了AES加密的测试用例。通过对每一轮的操作进行封装,便于理解和复用。
摘要由CSDN通过智能技术生成

前做一个小项目练手时,实现了几种加密或者hash过程展示,这里贴一下AES的。
先贴代码,具体细节描述后面有空再写。
注:AES原理不做赘述;此处实现的是原理,并没有考虑对称密码的模式;AES-128-128。

1、AES加密执行代码

package com.encryption.presentationTool.encryptionTool;

import com.encryption.presentationTool.VO.AESVO;
import com.encryption.presentationTool.assistantTool.codeTool;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * AES过程演示 ,数据按照 列 排序
 * 输入序列为:x1	x2	x3	x4	x5	x6	x7	x8	x9	x10	x11	x12	x13	x14	x15	x16
 * 矩阵排列为:
 * x1 	 x5	   x9	  x13
 * x2	 x6	   x10	  x14
 * x3 	 x7	   x11	  x15
 * x4	 x8	   x12	  x16
 *
 */

public class AES {
    static int Nr = 10;//轮数

    //定义S盒
    static int sbox[] = {0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30,
            0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D,
            0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72,
            0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5,
            0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18,
            0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
            0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6,
            0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC,
            0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0,
            0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
            0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38,
            0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C,
            0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64,
            0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
            0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A,
            0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95,
            0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C,
            0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E,
            0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B,
            0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35,
            0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69,
            0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
            0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D,
            0x0F, 0xB0, 0x54, 0xBB, 0x16,};//S盒表

    static int RCon[];//密钥的常量数组
    static int word[][];//轮密钥扩展后的数组,大小为 word[44][4]


    /**
     * 密钥数组扩展
     */
    public static void keyExpansion(int[] key) {
        RCon = new int[10];//轮常量为固定值
        RCon[0] = 0x01;
        RCon[1] = 0x02;
        RCon[2] = 0x04;
        RCon[3] = 0x08;
        RCon[4] = 0x10;
        RCon[5] = 0x20;
        RCon[6] = 0x40;
        RCon[7] = 0x80;
        RCon[8] = 0x1B;
        RCon[9] = 0x36;
        word = new int[44][4];//44组轮密钥
        int i, j;
        int temp[];

        for (i = 0; i < 4; i++) {
            for (j = 0; j < 4; j++) {
                word[i][j] = key[j * 4 + i]; //把初始密钥放入数组
            }
        }

        /** 通过密钥计算规则计算余下数组
         *
         *1.如果i不是4的倍数,那么第i列由如下等式确定:
         *W[i]=W[i-4]⨁W[i-1]
         *2.如果i是4的倍数,那么第i列由如下等式确定:
         *W[i]=W[i-4]⨁T(W[i-1])
         *其中,T是一个有点复杂的函数。函数T由3部分组成:字循环(每次循环一位)、字节代换(s盒)和轮常量异或。
         */

        for (i = 4; i < 44; i++) {
            temp = word[i - 1];//看作W[i-1]
            if (i % 4 == 0) { //i为4的倍数 进入函数运算 W[i-1]=T(W[i-1])
                temp = subWord(rotWord(temp));
                temp[0] = temp[0] ^ RCon[i / 4 - 1];
            }
            for (j = 0; j < 4; j++) {
                word[i][j] = word[i - 4][j] ^ temp[j];//相当于W[i]=W[i-4]⨁W[i-1]
            }
        }

    }

    //密钥扩展中的移位
    public static int[] rotWord(int[] word) {
        int[] rot = new int[4];
        int i;
        for (i = 0; i < 4; i++) {
            rot[i] = word[(i + 1) % 4];
        }
        return rot;
    }

    //密钥扩展中的4个字节的代换(4个字节为一组) 例如 A2 BE C4 D5
    public static int[] subWord(int[] word) {
        int sub[] = new int[4];
        int i;
        for (i = 0; i < 4; i++) {
            sub[i] = subByte(word[i]);
        }
        return sub;
    }

    //S盒的单个字节代换
    public static int subByte(int w) {
        int x = w / 16;
        int y = w % 16;
        return sbox[x * 16 + y];
    }

    //轮密钥加
    public static int[] addRoundKey(int[] text, int round) {
        int[] add = new int[16];
        int i, j;
        for (i = 0; i < 4; i++) {
            for (j = 0; j < 4; j++) {
                //System.out.print(Integer.toHexString(word[4 * round + i][j]) + ",");//第round轮的轮密钥
                add[4 * j + i] = text[4 * j + i] ^ word[4 * round + i][j]; //逐比特异或
            }
            //System.out.println();
        }
        return add;
    }

    //行移位(循环移位)规则:第0行移0位  .....  第3行移3位
    public static int[] shiftRows(int[] text) {
        int[] shift = new int[16];
        int i, j;
        for (i = 0; i < 4; i++) {
            for (j = 0; j < 4; j++) {
                if ((4 * i + j + i) == 8 || (4 * i + j + i) == 12 || (4 * i + j + i) == 13 || (4 * i + j + i) > 15) {

                    shift[4 * i + j] = text[(4 * i + j + i) - 4];
                } else {

                    shift[4 * i + j] = text[4 * i + j + i];
                }

            }
        }
        return shift;
    }


    //列混合
    public static int[] mixColumn(int[] text) {
        int[] mix = new int[16];
        //列混合的固定矩阵
        int[] mass = {2, 3, 1, 1,
                        1, 2, 3, 1,
                        1, 1, 2, 3,
                        3, 1, 1, 2
        };
        int i, j, u;
        for (i = 0; i < 16; i++) {
            u = 0;
            for (j = 0; j < 4; j++) {
                u = u ^ fieldMulit(mass[(i / 4) * 4 + j], text[4 * j + i % 4]);
            }
            mix[i] = u;
        }
        return mix;
    }


    //列混合中需要使用的矩阵相乘
    public static int fieldMulit(int x, int y) {
        String xString = Integer.toBinaryString(x);
        int i, j, mul = 0, tem = y;
        for (i = 0; i < xString.length(); i++) {
            if (xString.charAt(i) == '1') {
                for (j = 1; j < xString.length() - i; j++) {
                    tem = tem << 1; //左移
                    if (tem > 255) {
                        tem = tem % 256;
                        tem = tem ^ 0x1b;
                    }
                }
                mul = mul ^ tem;
                tem = y;
            }
        }
        return mul;
    }

    public static void printText(int[] text){
        int i;
        for (i = 0; i < 16; i++) {
            System.out.print(Integer.toHexString(text[i]) + " ");
            if (i % 4 == 3) {
                System.out.println();
            }
        }
    }

    /**
     * AES的执行函数,封装了所有操作,只需要传入原文和密钥,返回AESVO类型的集成的数据对象
     * @param input 原文
     * @param k 密钥
     * @return AESVO
     */
    public static AESVO aesDoEncrypt(String input,String k){
        int[] text = new codeTool().strToAsciiHex(input);
        int[] key = new codeTool().strToAsciiHex(k);

        //base64转码
        codeTool codeTool = new codeTool();

        AESVO aesvo = new AESVO();
        aesvo.setInput(codeTool.asciiHexToStr(text));
        aesvo.setKey(codeTool.asciiHexToStr(key));
        aesvo.setInputArray(text);
        aesvo.setKeyArray(key);
        List<com.encryption.presentationTool.entity.AES> aesList = new ArrayList<com.encryption.presentationTool.entity.AES>();

        com.encryption.presentationTool.encryptionTool.AES.keyExpansion(key);//密钥扩展
        int i, r = 0;
        System.out.println("初始的轮密钥加结果为:\n");
        text = com.encryption.presentationTool.encryptionTool.AES.addRoundKey(text, 0);//初始轮密钥加
        System.out.println(Arrays.toString(text) + "\n");
        com.encryption.presentationTool.encryptionTool.AES.printText(text);
        aesvo.setFirstAddRoundKey(text);

        r++;
        // 迭代10轮
        for (; r <= Nr; r++) {
            com.encryption.presentationTool.entity.AES aes = new com.encryption.presentationTool.entity.AES();
            System.out.println("迭代的第" + r + "轮:\n");
            aes.setTime(r);
            for (i = 0; i < 16; i++) {
                text[i] = com.encryption.presentationTool.encryptionTool.AES.subByte(text[i]);// 字节替代
            }
            System.out.println("迭代的第" + r + "轮的字节代替结果为:" + Arrays.toString(text));
            com.encryption.presentationTool.encryptionTool.AES.printText(text);
            aes.setSubBytes(text);

            text = com.encryption.presentationTool.encryptionTool.AES.shiftRows(text); // 行移位
            System.out.println("迭代的第" + r + "轮的行移位结果为:" + Arrays.toString(text));
            com.encryption.presentationTool.encryptionTool.AES.printText(text);
            aes.setShiftRows(text);


            if (r != 10) {// 注意:AES加密最后一轮没有列混合
                text = com.encryption.presentationTool.encryptionTool.AES.mixColumn(text);// 列混合
                System.out.println("迭代的第" + r + "轮的列混合结果为:" + Arrays.toString(text));
                com.encryption.presentationTool.encryptionTool.AES.printText(text);
                aes.setMixColumns(text);
            }

            text = com.encryption.presentationTool.encryptionTool.AES.addRoundKey(text, r);// 轮密钥加
            System.out.println("迭代的第" + r + "轮的轮密钥加结果为:" + Arrays.toString(text));
            aes.setAddRoundKey(text);
            aesList.add(aes);
//            printText(text);
        }
        aesvo.setAesList(aesList);

        //输出加密结果
        System.out.println("最后的加密结果为:\n");
        com.encryption.presentationTool.encryptionTool.AES.printText(text);
        aesvo.setFinalArray(text);

        try {
            System.out.println(codeTool.asciiToBase64Str(text));
            aesvo.setFinalStr(codeTool.asciiToBase64Str(text));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println("\n");
        System.out.println(aesvo.toString());


        return aesvo;
    }

}

2、AES各轮结果的封装VO

package com.encryption.presentationTool.VO;

import com.encryption.presentationTool.entity.AES;

import java.util.Arrays;
import java.util.List;

/**
 * AES的视图映射,便于封装数据返回前端
 */

public class AESVO {
    //原文
    private String input;
    //原文的16进制矩阵
    private int[] inputArray;
    //密钥
    private String key;
    //密文的16进制矩阵
    private int[] keyArray;
    //初始的轮密钥加结果
    private int[] firstAddRoundKey;
    //十轮加密过程的结果
    private List<AES> aesList;
    //最终的的矩阵形式的加密结果
    private int[] finalArray;
    //最终的经过base64变幻后的字符串形式的加密结果
    private String finalStr;

    public String getInput() {
        return input;
    }

    public void setInput(String input) {
        this.input = input;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public int[] getInputArray() {
        return inputArray;
    }

    public void setInputArray(int[] inputArray) {
        this.inputArray = inputArray;
    }

    public int[] getKeyArray() {
        return keyArray;
    }

    public void setKeyArray(int[] keyArray) {
        this.keyArray = keyArray;
    }

    public int[] getFirstAddRoundKey() {
        return firstAddRoundKey;
    }

    public void setFirstAddRoundKey(int[] firstAddRoundKey) {
        this.firstAddRoundKey = firstAddRoundKey;
    }

    public List<AES> getAesList() {
        return aesList;
    }

    public void setAesList(List<AES> aesList) {
        this.aesList = aesList;
    }

    public int[] getFinalArray() {
        return finalArray;
    }

    public void setFinalArray(int[] finalArray) {
        this.finalArray = finalArray;
    }

    public String getFinalStr() {
        return finalStr;
    }

    public void setFinalStr(String finalStr) {
        this.finalStr = finalStr;
    }

    @Override
    public String toString() {
        return "AESVO{" + "\n" +
                "input='" + input + '\'' + "\n" +
                "key='" + key + '\'' + "\n" +
                ", inputArray=" + Arrays.toString(inputArray) + "\n" +
                ", keyArray=" + Arrays.toString(keyArray) + "\n" +
                ", firstAddRoundKey=" + Arrays.toString(firstAddRoundKey) + "\n" +
                ", aesList=" + "\n" + aesList + "\n" +
                ", finalArray=" + Arrays.toString(finalArray) + "\n" +
                ", finalStr='" + finalStr + '\'' + "\n" +
                '}';
    }
}

3、字符串转码函数

package com.encryption.presentationTool.assistantTool;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Base64;

import static java.lang.Integer.toBinaryString;
import static java.lang.Integer.toHexString;

/**
 * 字符取ASCII码,
 */
public class codeTool {

    //低位
    private final static int[] hexArrayDw = {0x00, 0x01, 0x02, 0x03, 0x04,
            0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
    //高位
    private final static int[] hexArrayUp = {0x00, 0x10, 0x20, 0x30, 0x40,
            0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0};

    /**
     * 字符串转为16进制的ASCII码int型数组
     * @param input 字符串类型的输入数据(待加密的原文)
     * @return int[]
     */
    public static int[] strToAsciiHex(String input){
        int[] text = new int[input.length()];
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            Integer s = Integer.valueOf(c);
            System.out.println(toHexString(s).toUpperCase());
            if (s < 0) {
                s = s + 256;
            }
            int d1 = s / 16;
            int d2 = s % 16;

            //求该字符的ASCII码对应的16进制数
            text[i] =  hexArrayUp[d1] ^ hexArrayDw[d2] & 0xFF ;
        }
        return  text;
    }
    /**
     * 字符串转为16进制的ASCII码String
     * @param input 字符串类型的输入数据(待计算的原文)
     * @return int[]
     */
    public  String strToAsciiHexStr(String input){
        String str = "";
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            int s = (int) c;
            str += Integer.toHexString(s);
        }
        return  str;
    }

    /**
     * int[]转为16进制的ASCII码String
     * @param input
     * @return int[]
     */
    public  String[] intToAsciiHexStr(int[] input){
        String[] str = new String[input.length];
        for (int i = 0; i < input.length; i++) {
            str[i]= intToHex(input[i]);
        }
        return  str;
    }

    /**
     * 16进制的ASCII码转回字符
     * @param  text 16进制的数组
     * @return String
     */
    public static String asciiHexToStr(int[] text){
        StringBuilder stringBuilder = new StringBuilder();
        for (int i : text) {
            stringBuilder.append((char)i);
        }
        return stringBuilder.toString();
    }

    /**
     * 10进制转16进制
     * @param a
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String intToHex(int a){
        return String.format("%02X",a);
    }

    //加密后转回ASCII码会出现乱码问题,经过base64转为可读字符串
    public  static String asciiToBase64Str(int[] text) throws UnsupportedEncodingException {
        StringBuilder out = new StringBuilder();
        for (int i =0;i<16;i++)
            out.append((char)text[i]);
        return Base64.getEncoder().encodeToString(out.toString().getBytes("utf-8"));
    }

}

4、test测试

package com.encryption.presentationTool.encryptionTool;

import com.encryption.presentationTool.VO.AESVO;
import com.encryption.presentationTool.assistantTool.codeTool;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class AESTest {
    static int Nr = 10;//轮数


    public static void main(String[] args) {

        String a = "abcdxyzU1234nhjk";
        int[] text = new codeTool().strToAsciiHex(a);
        String k = "1234567891234567";
        int[] key = new codeTool().strToAsciiHex(k);

        //base64转码
        codeTool codeTool = new codeTool();

        AESVO aesvo = new AESVO();
        aesvo.setInput(codeTool.asciiHexToStr(text));
        aesvo.setKey(codeTool.asciiHexToStr(key));
        aesvo.setInputArray(text);
        aesvo.setKeyArray(key);
        List<com.encryption.presentationTool.entity.AES> aesList = new ArrayList<com.encryption.presentationTool.entity.AES>();

        AES.keyExpansion(key);//密钥扩展
        int i, r = 0;
        System.out.println("初始的轮密钥加结果为:\n");
        text = AES.addRoundKey(text, 0);//初始轮密钥加
        System.out.println(Arrays.toString(text) + "\n");
        AES.printText(text);
        aesvo.setFirstAddRoundKey(text);

        r++;
        // 迭代10轮
        for (; r <= Nr; r++) {
            com.encryption.presentationTool.entity.AES aes = new com.encryption.presentationTool.entity.AES();
            System.out.println("迭代的第" + r + "轮:\n");
            for (i = 0; i < 16; i++) {
                text[i] = AES.subByte(text[i]);// 字节替代
            }
            System.out.println("迭代的第" + r + "轮的字节代替结果为:" + Arrays.toString(text));
            AES.printText(text);
            aes.setSubBytes(text);



            text = AES.shiftRows(text); // 行移位
            System.out.println("迭代的第" + r + "轮的行移位结果为:" + Arrays.toString(text));
            AES.printText(text);
            aes.setShiftRows(text);


            if (r != 10) {// 注意:AES加密最后一轮没有列混合
                text = AES.mixColumn(text);// 列混合
                System.out.println("迭代的第" + r + "轮的列混合结果为:" + Arrays.toString(text));
                AES.printText(text);
                aes.setMixColumns(text);
            }

            text = AES.addRoundKey(text, r);// 轮密钥加
            System.out.println("迭代的第" + r + "轮的轮密钥加结果为:" + Arrays.toString(text));
            aes.setAddRoundKey(text);
            aesList.add(aes);
//            printText(text);
        }
        aesvo.setAesList(aesList);

        //输出加密结果
        System.out.println("最后的加密结果为:\n");
        AES.printText(text);
        aesvo.setFinalArray(text);



        try {
            System.out.println(codeTool.asciiToBase64Str(text));
            aesvo.setFinalStr(codeTool.asciiToBase64Str(text));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println("\n");
        System.out.println(aesvo.toString());


    }
}

5、结合thymeleaf在web端展示

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值