天天看點

des算法java模拟實作已同步github項目:url:https://github.com/EricLi404/Java-Demos/tree/master/Des-Demogit:https://github.com/EricLi404/Java-Demos.git

大二下學期應用密碼學課程設計

已同步github項目:

url:https://github.com/EricLi404/Java-Demos/tree/master/Des-Demo

git:https://github.com/EricLi404/Java-Demos.git

實作了des算法,具體的每一步的輸出都有記錄,沒有加入工作模式,支援加密的輸入為英文和數字混合的字元串,填充方式采用的無限填充0的做法。下面是源碼。

// 主類,含有一些調試資訊,各種輸出

package cryptology;

import java.util.Scanner;

/**
 * Created by leif on 2016/3/26 0026.
 */
public class des {
    public static void main(String[] args) {
        System.out.println("**********************************************************");
        System.out.println("                      DES加解密分步示範                      ");
        System.out.println("**********************************************************");
        System.out.println();
        @SuppressWarnings("resource")
        Scanner in = new Scanner(System.in);
        System.out.print("請輸入明文(支援任意長度字母數字組合):");
        String mmmmmm = in.nextLine();
        System.out.print("請輸入密鑰(支援任意格式輸入):");
        String kkkkkk = in.nextLine();
        String[] M = util.all2string(mmmmmm);
        char[] K = util.keypre(kkkkkk);
        descore descore = new descore();
        String mimi = descore.en(M, K);
        String demimi = descore.de(util.all222string(mimi), K);
        String demimistring = util.byte2string(demimi);
        System.out.println("*************************************************");
        System.out.println("**********************結果***********************");
        System.out.println("明文:"+mmmmmm);
        System.out.println("------------------------------------------------------------");
        System.out.println("加密結果:");
        System.out.println("二進制:"+ mimi);
        System.out.println("十六進制:"+util.two2hex(mimi));
        System.out.println("------------------------------------------------------------");
        System.out.println("解密結果:");
        System.out.println("二進制:"+demimi);
        System.out.println("十六進制:"+util.two2hex(demimi));
        System.out.println("編碼後:"+demimistring);




    }


}
           
// 核心算法類
package cryptology;

/**
 * Created by leif on 2016/3/26 0026.
 */
public class descore {

    /**
     * 初始置換
     * @param M char[64]
     * @return char[56]
     */
    private char[] initReplace(char[] M){
        char[] tM = new char[];
        for (int i = ; i < ; i++){
            tM[i] = M[data.IP[i]-];
        }
        return tM;
    }

    /**
     * 密鑰置換 1
     * @param K char[64]
     * @return char[56]
     */
    private char[] keyReplace1(char[] K){
        char[] tK = new char[];
        for (int i = ; i < ; i++){
            tK[i] = K[data.PC_1[i]-];
        }
        return tK;
    }

    /**
     * 生成子密鑰
     * @param K char[56]
     * @param offset 左移位數 int
     * @return char[56]
     */
    private char[] loopKey(char[] K, int offset){
        String k1 = new String();
        String k2 = new String();
        String k = new String(K);
        k1 = (k.substring(,)+k.substring(,)).substring(offset,offset+);
        k2 = (k.substring(,)+k.substring(,)).substring(offset,offset+);
        return (k1+k2).toCharArray();
    }

    /**
     *  密鑰置換2
     * @param K char[56]
     * @return char[48]
     */
    private char[] keyReplace2(char[] K){
        char[] tK = new char[];
        for (int i = ; i < ; i++){
            tK[i] = K[data.PC_2[i]-];
        }
        return tK;
    }

    /**
     *  生成16輪的輪密鑰
     * @param K char[64]
     * @return
     */
    private char[][] getKey(char[] K){
        char[][] tK = new char[][];
        char[][] ttK = new char[][];
        char[] k1 = new char[];
        k1 = keyReplace1(K);
        tK[] = loopKey(k1,data.LeftMove[]);
        for (int i = ; i < ; i++){
            tK[i] = loopKey(tK[i-],data.LeftMove[i]);
        }
        for(int i = ; i < ; i++){
            ttK[i] = keyReplace2(tK[i]);
        }
        return ttK;
    }

    /**
     * E 表置換(拓展置換)
     * @param R char[32]
     * @return char[48]
     */
    private char[] eReplace(char[] R){
        char[] tR = new char[];
        for (int i = ;i < ; i++){
            tR[i] = R[data.E[i]-];
        }
        return tR;
    }

    /**
     *  xor異或操作
     * @param tR char[48]
     * @param K char[48] 輪密鑰
     * @return
     */
    private char[] xor(char[] tR, char[] K){
        String x = new String();
        for (int i = ; i < tR.length; i++){
            x += tR[i] ^ K[i];
        }
        return x.toCharArray();
    }


    /**
     * s 盒置換
     * @param xorR char[48]
     * @return char[32]
     */
    private char[] sReplace(char[] xorR){
        char[][] tR = new char[][];
/*        String  nn = new String(R);
        System.out.println(nn+nn.length());*/
        String sr = new String();
        for (int i = ; i < ; i++){
            for (int j = ; j < ; j++){
                tR[i][j] = xorR[i*+j];
            }
            int p = util.two2ten(String.valueOf(tR[i][])+String.valueOf(tR[i][]));
            int q = util.two2ten(String.valueOf(tR[i][])+String.valueOf(tR[i][])+String.valueOf(tR[i][])+String.valueOf(tR[i][]));
             sr += String.format("%04d",Integer.parseInt(Integer.toBinaryString(data.S_Box[i][p][q])));
//            sr += String.format("%04d",Integer.parseInt(Integer.toBinaryString(data.S_Box[i][(tR[i][0] << 1) + tR[i][5]][(tR[i][1] << 3) + (tR[i][2] << 2) + (tR[i][3] << 1) + tR[i][4]])));
        }
        return sr.toCharArray();
    }

    /**
     * p 表置換
     * @param sR char[32]
     * @return char[32]
     */
    private char[] pReplace(char[] sR){
        char[] pR = new char[];
        for (int i = ; i < ; i++){
            pR[i] = sR[data.P[i]-];
        }
        return pR;
    }

    /**
     *  終結置換
     * @param R char[64]
     * @return char[64]
     */
    private char[] init_1Replace(char[] R){
        char[] tR = new char[];
        for (int i = ; i < ; i++){
            tR[i] = R[data.IP_1[i]-];
        }
        return tR;
    }

    /**
     *  輪置換
     * @param R char[32]
     * @param K char[32]
     * @return char[32]
     */
    public char[] core(char[] R, char[] K){
        char[] eR = eReplace(R);
        System.out.println("Etable置換結果---"+new String(eR)+"-----"+util.two2hex(new String(eR)));
        System.out.println("輪密鑰---"+new String(K)+"-----"+util.two2hex(new String(K)));
        char[] xorR = xor(eR,K);
        System.out.println("xor-1結果---"+new String(xorR)+"-----"+util.two2hex(new String(xorR)));
        char[] sR = sReplace(xorR);
        System.out.println("Sbox置換結果---"+new String(sR)+"-----"+util.two2hex(new String(sR)));
        char[] pR = pReplace(sR);
        System.out.println("Ptable置換結果---"+new String(pR)+"-----"+util.two2hex(new String(pR)));
        @SuppressWarnings("unused")
        String pp = new String(pR);
        return pR;
    }

    public String enCode(char[] M, char[] K){
        System.out.println("#########################");
        System.out.println(" =====  === == ==  = =   開始加密");
        System.out.println("比特流為---"+new String(M)+"-----"+util.two2hex(new String(M)));
        System.out.println("密鑰為---"+new String(K)+"-----"+util.two2hex(new String(K)));
        char[][] L = new char[][];
        char[][] R = new char[][];
        char[][] key = new char[][];
        char[] res = new char[];
        char[] r = new char[];
        M = initReplace(M);
        System.out.println("IP置換結果---"+new String(M)+"-----"+util.two2hex(new String(M)));
        key = getKey(K);
        for (int i = ; i < ; i++){
            L[][i] = M[i];
            R[][i] = M[i+];
        }

        for (int i = ; i < ; i++){
            System.out.println("===================第 "+i+" 輪==================");
            char[] xorR = xor(L[i-],core(R[i-],key[i-]));
            System.out.println("xor-2結果"+new String(xorR)+"-----"+util.two2hex(new String(xorR)));
            for (int j = ; j < ; j++){
                L[i][j] = R[i-][j];
                R[i][j] = xorR[j];
            }
        }

        for (int i = ; i < ; i++){
            res[i] = R[][i];
            res[i+] = L[][i];
        }
        r = init_1Replace(res);
        String rr = new String(r);
        System.out.println("終結置換結果---"+new String(rr)+"-----"+util.two2hex(new String(rr)));
        return rr;
    }


    public String deCode(char[] M, char[] K){
        System.out.println("#########################");
        System.out.println(" =====  === == ==  = =   開始解密");
        System.out.println("比特流為---"+new String(M)+"-----"+util.two2hex(new String(M)));
        System.out.println("密鑰為---"+new String(K)+"-----"+util.two2hex(new String(K)));
        char[][] L = new char[][];
        char[][] R = new char[][];
        char[][] key = new char[][];
        char[] res = new char[];
        char[] r = new char[];
        M = initReplace(M);
        System.out.println("IP置換結果---"+new String(M)+"-----"+util.two2hex(new String(M)));
        key = getKey(K);
        for (int i = ; i < ; i++){
            L[][i] = M[i];
            R[][i] = M[i+];
        }
        for (int i = ; i < ; i++){
            System.out.println("===================第 "+i+" 輪==================");
            char[] xorR = xor(L[i-],core(R[i-],key[-i]));
            System.out.println("xor-2結果"+new String(xorR)+"-----"+util.two2hex(new String(xorR)));
            for (int j = ; j < ; j++){
                L[i][j] = R[i-][j];
                R[i][j] = xorR[j];
            }
        }
        for (int i = ; i < ; i++){
            res[i] = R[][i];
            res[i+] = L[][i];
        }
        r = init_1Replace(res);
        String rr = new String(r);
        return rr;
    }

    public String en(String[] mm, char[] kk) {
        String mi = "";
        for(int i = ; i < mm.length; i++){
            char[] charrr = mm[i].toCharArray();
            mi += enCode(charrr, kk);
        }
        return mi;
    }

    public String de(String[] mm, char[] kk) {
        String mi = "";
        for(int i = ; i < mm.length; i++){
            char[] charrr = mm[i].toCharArray();
            mi += deCode(charrr, kk);
        }
        return mi;
    }
}
           
// des算法置換過程需要用到的一些置換表

package cryptology;

/**
 * Created by leif on 2016/3/26 0026.
 */
public class data {
        // 聲明常量位元組數組
    static int length = ;

    public static int getLength() {
        return length;
    }
    public static void setLength(int length) {
        data.length = length;
    }
    /**
     * 初始置換
     */
    static final int[] IP = {
                , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , 
        }; // 64

    /**
     *
     */
    static final int[] IP_1 = {
                , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , 
        }; // 64


    /**
     * 密鑰置換  1
     */
    static final int[] PC_1 = {
                , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , , , , , , , , , ,
                , 
        }; // 56

    /**
     *  密鑰置換  2
     */
    static final int[] PC_2 = {
                , , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , , 
        }; // 48

    /**
     *  E表置換(将密鑰的右32置換為48)
     */
    static final int[] E = {
                , , , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , , , , , , , , ,
                , , , , , , , , , , 
        }; // 48

        static final int[] P = {
                , , , , , , , , , , , , , , , , , ,
                , , , , , , , , , , , , , 
        }; // 32
        static final int[][][] S_Box = {
                {
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  }
                },
                { // S_Box[1]
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  }
                },
                { // S_Box[2]
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  }
                },
                { // S_Box[3]
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  }
                },
                { // S_Box[4]
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  }
                },
                { // S_Box[5]
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  }
                },
                { // S_Box[6]
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  }
                },
                { // S_Box[7]
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  },
                        { , , , , , , , , , , , , , , ,  }
                } // S_Box[8]
        };
        static final int[] LeftMove = {
                , , , , , , , , , , , , , , , 
        }; // 左移位置清單
}
           
// 系統裡用到的一些公共的功能性函數

package cryptology;

import java.util.HashMap;

/**
 * Created by leif on 2016/6/21.
 */
public class util {
    /**
     *  二進制轉十進制
     * @param two 二進制 string
     * @return 十進制 int
     */
    public static int two2ten(String two){
        String s = two;
        int x = ;
        int pow = ;
        for (int i = s.length() - ; i >= ; i--) {
            x += Math.pow(, pow) * (s.charAt(i) == '1' ?  : );
            pow ++;
        }
        return x;
    }


    /**
     *  二進制轉十六進制
     * @param two 二進制 string
     * @return 十六進制 int
     */
    public static String two2hex(String bString){
        if (bString == null || bString.equals("") || bString.length() %  != )  
            return null;  
        StringBuffer tmp = new StringBuffer();  
        int iTmp = ;  
        for (int i = ; i < bString.length(); i += )  
        {  
            iTmp = ;  
            for (int j = ; j < ; j++)  
            {  
                iTmp += Integer.parseInt(bString.substring(i + j, i + j + )) << ( - j - );  
            }  
            tmp.append(Integer.toHexString(iTmp));  
        }  
        return tmp.toString();  
    }  


    /**
     *  将64位int數組轉化為64位char數組
     * @param mm int[64]
     * @return char[64]
     */
    public static char[] int64tochar64(int[] mm){
        @SuppressWarnings("unused")
        char[] g = new char[];
        String gg = new String();
        for (int i = ; i < ; i++){
            gg += mm[i];
        }
        return gg.toCharArray();
    }

    public static HashMap<Integer,char[]> preMI(String mmmmmm){
        String lmmmmmm = "";
        for(int i = ; i < mmmmmm.length(); i++){
            lmmmmmm += Integer.toBinaryString(Integer.parseInt(mmmmmm.substring(i,i+)));
        }
        HashMap<Integer, char[] > tmmm = new HashMap<>();
        char mmmmm[] = lmmmmmm.toCharArray();
        char rm[] = new char[];
        int j = ;
        for(int i = ; i < lmmmmmm.length(); i++){
            rm[i%] = mmmmm[i];
            if (i %  == ) {
                tmmm.put(j, rm);
                j++;
            }
        }
        return tmmm;
    }


    /**
     * 明文初始化處理,将每一位轉為一個64bit長度的string
     * @param all
     * @return
     */
    public static String[] all2string(String all)  {
        byte byteall[] = all.getBytes();
        String allstring[] = new String[all.length()];
        for(int i = ; i < byteall.length; i++){
            allstring[i] =   String.format("%064d", Integer.parseInt(Integer.toBinaryString(byteall[i])));
        }
        return allstring;
    }

    /**
     * 密文解密預處理,将密文每64bit截取成一個string
     * @param all
     * @return
     */
    public static String[] all222string(String all)  {
        String allstring[] = new String[all.length()/];
        for(int i = ; i < allstring.length; i++){
            allstring[i] =   all.substring(i*,(i+)*);
        }
        return allstring;
    }

    /**
     * 将解密結果的byte轉為string,還原密文
     * @param all
     * @return
     */
    public static String byte2string(String all)  {
        byte allstring[] = new byte[all.length()/];
        for(int i = ; i < allstring.length; i++){
            allstring[i] =   (byte) two2ten(all.substring(i*,(i+)*).substring(, ));
        }
        return new String(allstring);
    }

    /**
     * 将任意格式的密鑰擷取hash值,格式化為char[64]
     * @param k
     * @return
     */
    public static char[] keypre(String k) {
        String ha = String.format("%08d", k.hashCode());
        String kk = "";
        for(int i = ; i < ; i++){
            kk += String.format("%08d", Integer.parseInt(Integer.toBinaryString(Integer.parseInt(ha.substring(i, i+)))));
        }
        return kk.toCharArray();
    }
}