DES加密算法(Java实现)

2021.3.29
信息安全课上要求算一个DES的一个流程。
实在不想用手算,于是用Java语言实现了分解功能,特此记录。
算法步骤参考博客:
点击此处
上面博客的图可以说是非常清晰了。

package entrypt_homework;

public class DES {

    //起始置换表 长度8X8
    public int[] innitial = new int[]{
            58,50,42,34,26,18,10,2,
            60,52,44,36,28,20,12,4,
            62,54,46,38,30,22,14,6,
            64,56,48,40,32,24,16,8,
            57,49,41,33,25,17,9,1,
            59,51,43,35,27,19,11,3,
            61,53,45,37,29,21,13,5,
            63,55,47,39,31,23,15,7
    };

    //扩展置换表E  长度6X8
    public int[] expandTbE = new int[]{
            32,1,2,3,4,5,
            4,5,6,7,8,9,
            8,9,10,11,12,13,
            12,13,14,15,16,17,
            16,17,18,19,20,21,
            20,21,22,23,24,25,
            24,25,26,27,28,29,
            28,29,30,31,32,1
    };


    //生成子密钥 pc1表 长度7X8
    public int[] pc1 = new int[]{
            57,49,41,33,25,17,9,
            1,58,50,42,34,26,18,
            10,2,59,51,43,35,27,
            19,11,3,60,52,44,36,
            63,55,47,39,31,23,15,
            7,62,54,46,38,30,22,
            14,6,61,53,45,37,29,
            21,13,5,28,20,12,4
    };

    //生成子秘钥 pc2表 长度6X8
    public int[] pc2 = new int[]{
            14,17,11,24,1,5,
            3,28,15,6,21,10,
            23,19,12,4,26,8,
            16,7,27,20,13,2,
            41,52,31,37,47,55,
            30,40,51,45,33,48,
            44,49,39,56,34,53,
            46,42,50,36,29,32
    };


    //生成子秘钥 循环左移轮次表 长度 16
    public int[] leftRoundTable = new int[]{
      1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
    };


    //S1盒
    public int[][] s1 = new int[][]{
            {14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7} ,
            {0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8} ,
            {4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0} ,
            {15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13}
    };

    //s2盒
    public int[][] s2 = new int[][]{
            {15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10} ,
            {3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5} ,
            {0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15} ,
            {13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9}
    };

    //s3盒
    public int[][] s3 = new int[][]{
            {10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8} ,
            {13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1} ,
            {13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7} ,
            {1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12}
    };

    //s4盒
    public int[][] s4 = new int[][]{
            {7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15} ,
            {13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9} ,
            {10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4} ,
            {3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14}
    };

    //s5盒
    public int[][] s5 = new int[][]{
            {2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9} ,
            {14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6} ,
            {4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14} ,
            {11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3}
    };

    //s6盒
    public int[][] s6 = new int[][]{
            {12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11} ,
            {10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8} ,
            {9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6} ,
            {4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13}
    };

    //s7
    public int[][] s7 = new int[][]{
            {4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1} ,
            {13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6} ,
            { 1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2} ,
            {6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12}
    };

    //s8
    public int[][] s8 = new int[][]{
            {13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7} ,
            {1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2} ,
            {7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8} ,
            {2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}
    };

    //P盒 长度为32
    public int[] pbox = new int[]{
            16,7,20,21,
            29,12,28,17,
            1,15,23,26,
            5,18,31,10,
            2,8,24,14,32,
            27,3,9,19,13,
            30,6,22,11,4,25
    };

    //逆置置换表
    public int[] end = new int[]{
            40,8,48,16,56,24,64,32,
            39,7,47,15,55,23,63,31,
            38,6,46,14,54,22,62,30,
            37,5,45,13,53,21,61,29,
            36,4,44,12,52,20,60,28,
            35,3,43,11,51,19,59,27,
            34,2,42,10,50,18,58,26,
            33,1,41,9,49,17,57,25
    };


    /**
     * 起始置换,根据置换表,将明文进行置换,记得置换表的数字要减1
     * @param plainText
     * @return
     */
    public String innitialPermutation(String plainText){
        char[] plainTextCh = plainText.toCharArray();
        char[] permutation = new char[64];
        for(int i = 0; i<64 ;i++){
            permutation[i] = plainTextCh[innitial[i]-1];
        }
        String initPlaintext = String.valueOf(permutation);
        return initPlaintext;
    }


    /**
     * DES加密,生成子密钥,返回第X轮次的子秘钥。<br/> 因为字符串都是从0开始,所以pc里面的数字都要减1
     * @param key  秘钥的字符串
     * @param round 生成子秘钥的轮次
     * @return
     */
    public String roundKeyGenerate(String key,int round){
        char[] keyCh = key.toCharArray();
        char[] generateOne = new char[56];
        for(int i = 0;i<56;i++){
            generateOne[i] = keyCh[pc1[i]-1];
        }
        key = String.valueOf(generateOne);
        String c0 = key.substring(0,28);
        String d0 = key.substring(28,56);

        int bitCount = leftRoundTable[round];
        c0 = c0.substring(0+bitCount,28) + c0.substring(0,bitCount);
        d0 = d0.substring(0+bitCount,28) + d0.substring(0, bitCount);

        String subKey = c0+d0;
        char[] subKeyCh = subKey.toCharArray();
        char[] generateTwo = new char[48];
        for(int i = 0;i<48;i++){
            generateTwo[i] = subKeyCh[pc2[i]-1];
        }
        subKey = String.valueOf(generateTwo);
        return subKey;
    }


    /**
     * 扩展置换E,同样的,记得置换表里面的数字-1
     * @param Ri  传入Ri
     * @return
     */
    public String expandChange(String Ri){
        char[] RiCh = Ri.toCharArray();
        char[] exRiCh = new char[48];
        for(int i =0; i<48;i++){
            exRiCh[i] = RiCh[expandTbE[i]-1];
        }
        String ERi = String.valueOf(exRiCh);
        return ERi;
    }


    /**
     * ERi 和 Ki 进行异或运算
     * @param ERi
     * @param Ki
     * @return
     */
    public String xorCul(String ERi,String Ki){
        char[] ERiCh = ERi.toCharArray();
        char[] KiCh = Ki.toCharArray();
        char[] resCh = new char[48];
        for(int i = 0; i<48; i++){
            if(ERiCh[i] == KiCh[i]){
                resCh[i] = '0';
            }else{
                resCh[i] = '1';
            }
        }
        String result = String.valueOf(resCh);
        return result;
    }


    /**
     * S盒运算,48位得到对照表得到32位
     * @param oxrRes 异或运算得到的结果
     * @return
     */
    public String sboxCul(String oxrRes){
        String s1Str = oxrRes.substring(0,6);
        String s2Str = oxrRes.substring(6,12);
        String s3Str = oxrRes.substring(12,18);
        String s4Str = oxrRes.substring(18,24);
        String s5Str = oxrRes.substring(24,30);
        String s6Str = oxrRes.substring(30,36);
        String s7Str = oxrRes.substring(36,42);
        String s8Str = oxrRes.substring(42,48);

        StringBuilder sb = new StringBuilder();
        String column = "";
        String row = "";
        int colNum = 0;
        int rowNum = 0;
        int boxNum = 0;
        String res = "";
        for(int i = 0;i<8;i++){
            switch (i){
                case 0:
                    row = s1Str.substring(0,1) + s1Str.substring(5, 6);
                    column = s1Str.substring(1,5);
                    colNum = Integer.parseUnsignedInt(column, 2);
                    rowNum = Integer.parseUnsignedInt(row,2);
                    boxNum = s1[rowNum][colNum];
                    break;
                case 1:
                    row = s2Str.substring(0,1) + s1Str.substring(5, 6);
                    column = s2Str.substring(1,5);
                    colNum = Integer.parseUnsignedInt(column, 2);
                    rowNum = Integer.parseUnsignedInt(row,2);
                    boxNum = s2[rowNum][colNum];
                    break;
                case 2:
                    row= s3Str.substring(0,1) + s3Str.substring(5, 6);
                    column= s3Str.substring(1,5);
                    colNum = Integer.parseUnsignedInt(column, 2);
                    rowNum = Integer.parseUnsignedInt(row,2);
                    boxNum = s3[rowNum][colNum];
                    break;
                case 3:
                    row = s4Str.substring(0,1) + s4Str.substring(5, 6);
                    column = s4Str.substring(1,5);
                    colNum = Integer.parseUnsignedInt(column, 2);
                    rowNum = Integer.parseUnsignedInt(row,2);
                    boxNum = s4[rowNum][colNum];
                    break;
                case 4:
                    row = s5Str.substring(0,1) + s5Str.substring(5, 6);
                    column = s5Str.substring(1,5);
                    colNum = Integer.parseUnsignedInt(column, 2);
                    rowNum = Integer.parseUnsignedInt(row,2);
                    boxNum = s5[rowNum][colNum];
                    break;
                case 5:
                    row = s6Str.substring(0,1) + s6Str.substring(5, 6);
                    column = s6Str.substring(1,5);
                    colNum = Integer.parseUnsignedInt(column, 2);
                    rowNum = Integer.parseUnsignedInt(row,2);
                    boxNum = s6[rowNum][colNum];
                    break;
                case 6:
                    row = s7Str.substring(0,1) + s7Str.substring(5, 6);
                    column = s7Str.substring(1,5);
                    colNum = Integer.parseUnsignedInt(column, 2);
                    rowNum = Integer.parseUnsignedInt(row,2);
                    boxNum = s7[rowNum][colNum];
                    break;
                case 7:
                    row = s8Str.substring(0,1) + s8Str.substring(5, 6);
                    column = s8Str.substring(1,5);
                    colNum = Integer.parseUnsignedInt(column, 2);
                    rowNum = Integer.parseUnsignedInt(row,2);
                    boxNum = s8[rowNum][colNum];
                    break;
            }
            //补0
            res = Integer.toBinaryString(boxNum);
            if(res.length() != 4){
                for(int k = res.length(); k<4; k++){
                    res = "0" + res;
                }
            }
            sb.append(res);
        }
        String sboxRes = sb.toString();
        return sboxRes;
    }


    /**
     * P盒转换
     * @param sboxRes sbox的输出结果
     * @return
     */
    public String pboxCul(String sboxRes){
        char[] sboxResCh = sboxRes.toCharArray();
        char[] pboxResCh = new char[32];
        for(int i = 0;i<32;i++){
            pboxResCh[i] = sboxResCh[pbox[i]-1];
        }
        String pboxRes = String.valueOf(pboxResCh);
        return  pboxRes;
    }

    /**
     * 迭代最后一步的异或操作,算出Ri+1
     * @param pboxRes
     * @param Li
     * @return
     */
    public String xorCul2(String pboxRes,String Li){
        char[] pboxResCh = pboxRes.toCharArray();
        char[] LiCh = Li.toCharArray();
        char[] resCh = new char[32];
        for(int i = 0; i<32; i++){
            if(pboxResCh[i] == LiCh[i]){
                resCh[i] = '0';
            }else{
                resCh[i] = '1';
            }
        }
        String result = String.valueOf(resCh);
        return result;
    }

    /**
     * 终止转换(未实现)
     * @return 返回最终结果
     */
    public String endPermutation(){
        String endResult = null;
        return endResult;
    }


    //明文:00000001 00100011 01000101 01100111 10001001 10101011 11001101 11101111
    //秘钥:00000001 00100011 01000101 01100111 10001001 10101011 11001101 11101111
    public static void main(String[] args) {
        String plainText = "0000000100100011010001010110011110001001101010111100110111101111";
        String key = "0000000100100011010001010110011110001001101010111100110111101111";
        DES des = new DES();
        //计算初始置换
        String initPlainText = des.innitialPermutation(plainText);
        System.out.println("明文初始置换结果为:"+initPlainText);
        //计算L0和R0
        String L0 = initPlainText.substring(0,32);
        String R0 = initPlainText.substring(32,64);
        System.out.println("L0为:"+L0);
        System.out.println("R0为:"+R0);
        //E(R0)
        String ER0 = des.expandChange(R0);
        String k1 = des.roundKeyGenerate(key, 0);
        System.out.println("E(R0)为:"+ER0);
        System.out.println("k1为:"+k1);
        // E(R0) 异或 k1
        String xorRes1 = des.xorCul(ER0, k1);
        System.out.println("E(R0) 异或 k1 结果为:"+xorRes1);
        //S盒运算
        String sboxRes = des.sboxCul(xorRes1);
        System.out.println("S盒运算结果为:"+sboxRes);
        //P盒置换
        String pboxRes = des.pboxCul(sboxRes);
        System.out.println("P盒置换结果为:"+pboxRes);

        String R1 = des.xorCul2(pboxRes, L0);
        System.out.println("R1为:"+R1);
        System.out.println("L1为:"+R0);
    }

}




  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值