密碼學(xué)第一次作業(yè)DES算法

內(nèi)容###

編程統(tǒng)計(jì)DES算法中明文(或密鑰)改變1位,2位。。。64位的情況下,密文位數(shù)的變化量情況具體要求: 編程實(shí)現(xiàn)
1。在密鑰不變情況下,明文改變1位,2位。。。64位,觀察并統(tǒng)計(jì)密文位數(shù)變化規(guī)律。
2。在明文不變情況下,密鑰改變1位,2位。。。64(56)位,觀察并統(tǒng)計(jì)密文位數(shù)變化規(guī)律。
為了使統(tǒng)計(jì)局有客觀性,上述每種情況可以重復(fù)多次,然后求平均值。
編程語言不限,建議采用java 或 C#等高級(jí)語言,因?yàn)檫@些語言中有內(nèi)置的DES算法包,如果采用C/C++則需要自己到網(wǎng)上搜索DES算法庫,
提交方式:將程序源代碼和運(yùn)行結(jié)果截圖以電子文檔的形式提交。

電子版作業(yè)上交要求###

注意:每個(gè)人的郵件標(biāo)題和附件文件名要帶上自己的編號(hào)203 姓名馮光平,學(xué)號(hào)3114006176,比如 001_31012xxx_張三_信息安全第X次作業(yè) 。這樣便于管理。注意:直接發(fā)送到我的QQ郵箱,不要通過通過QQ傳輸。
特別要注意,附件的文件名也要采用上述命名格式,不要使用“文檔1.docx”等默認(rèn)文件名,如果包含多個(gè)文件,請(qǐng)先用壓縮...

源代碼###

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class des {
     private static byte[][] b;

    /**
     * 加密方法
     * @param datasource 明文
     * @param password 秘鑰
     * @return 密文
     */
    public static byte[] desCrypto(byte[] datasource, String password) {
        try{
            SecureRandom random = new SecureRandom();
            DESKeySpec desKey = new DESKeySpec(password.getBytes());
            //創(chuàng)建一個(gè)密匙工廠,然后用它把DESKeySpec轉(zhuǎn)換成
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey securekey = keyFactory.generateSecret(desKey);
            //Cipher對(duì)象實(shí)際完成加密操作
            Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
            //用密匙初始化Cipher對(duì)象
            cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
            //現(xiàn)在,獲取數(shù)據(jù)并加密
            //正式執(zhí)行加密操作
            return cipher.doFinal(datasource);
        }catch(Throwable e){
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 初始化輔助數(shù)組 b是需要初始化的數(shù)組
     */
    public static void initBytes() {
        //64代表的是含有1-64個(gè)1的串,8代表8個(gè)字節(jié)(64位)
        b = new byte[64][8];
        b[0][0] = -128; // 10000000
        for(int i = 1; i < 64; i++) {
            for(int j = 0; j < 8; j++) {
                b[i][j] = b[i-1][j];
            }
            int k = i/8;
            int z = (i+1)%8; z = z == 0 ? 8 : z;
            b[i][k] ^= (byte) Math.pow(2, (8-z));
        }
    }
    
    /**
     * 循環(huán)右移一個(gè)byte數(shù)組
     * @param num 右移位數(shù)
     * @param b 數(shù)組
     * @return 右移后數(shù)組
     */
    public static byte[] bytesMoveToRight(int num , byte[] b) {
        byte[] bytes = b;
        for(int i = 0; i < num; i++) { //每次循環(huán)右移一位,實(shí)現(xiàn)比較簡(jiǎn)單,但是效率比較慢
            byte low = (byte)(bytes[bytes.length-1] & 1); //記錄最后一個(gè)字節(jié)的最低1位
            for(int j = 0; j < bytes.length; j++) { //從第一個(gè)字節(jié)開始
                byte loww = (byte)(bytes[j] & 1); //記錄最低一位
                bytes[j] = (byte)(bytes[j]>>1&127); //右移一位,高位補(bǔ)0,可以用>>>代替,但是不知道為啥我的開發(fā)環(huán)境>>>失效了
                bytes[j] = (byte) (bytes[j] ^ (low<<7) ); //把高位補(bǔ)上之前記錄的最低1位
                low = loww; //替換成新的最低1位
            }
        }
        return bytes;
    }
    
    /**
     * 求兩個(gè)字節(jié)數(shù)組的二進(jìn)制中不同的位數(shù)
     * @param m 
     * @param n
     * @return 返回不同的位數(shù)的個(gè)數(shù)
     */
    public static int countBitDiff(byte[] m, byte[] n) {
        if(m.length != n.length) return -1;

        byte[] ans = new byte[m.length];
        for(int i = 0; i < m.length; i++) { //異或操作
            ans[i] =(byte) (m[i] ^ n[i]);
        }
        int count = 0;
        for(int i = 0; i < ans.length; i++) { //統(tǒng)計(jì)1的個(gè)數(shù)
            while(ans[i] != 0){
                ans[i] &= (byte)(ans[i] -1);
                count++;
            }
        }
        return count;
    }
    
    public static void main(String[] args) {
        //初始化輔助數(shù)組
        initBytes();
        //初始明文
        String word = "AAAAAAAA";
        printTo8Binary( word.getBytes());
        //初始秘鑰
        String password = "12345678";
        printTo8Binary( password.getBytes());
        //加密
        byte[] result = desCrypto(word.getBytes(),password);
        printTo8Binary(result);

        /**改變明文位數(shù)**/
        for(int i = 1; i <= 64; i++) { //改變1-64位
            System.out.print("明文改變"+i+"位: ");
            byte[] origin = word.getBytes(); //原始明文
            int digits = 0; //改變位數(shù)
            for(int j = 0; j < 10; j++) { //10種情況取平均
                byte[] now = new byte[8]; //現(xiàn)在明文
                for(int k = 0; k < origin.length; k++) { //用輔助數(shù)組進(jìn)行變位(i-1位)
                    now[k] = (byte)(origin[k] ^ b[i-1][k]);
                }
                bytesMoveToRight(1 , b[i-1]); //右移一下輔助數(shù)組,供下種情況使用
//                printTo8Binary("改變"+(j+1)+"后明文: " , now);
                //加密
                byte[] r = desCrypto(now,password);
//                printTo8Binary("改變"+(j+1)+"后密文: " , r);
                digits += countBitDiff(r , result);//和原始密文比較,記錄改變位數(shù)
//                System.out.println("密文改變了"+countBitDiff(r , result)+"位");
            }
            System.out.println("密文平均改變了"+(double)digits/10.0+"位");
        }

        /**改變秘鑰位數(shù)**/
        for(int i = 1; i <= 64; i++) { //改變1-64位
            System.out.print("秘鑰改變"+i+"位: ");
            byte[] origin = password.getBytes();//原始秘鑰
            int digits = 0; //改變位數(shù)
            for(int j = 0; j < 10; j++) { //10種情況取平均
                byte[] now = new byte[8]; //現(xiàn)在秘鑰
                for(int k = 0; k < origin.length; k++) { //用輔助數(shù)組進(jìn)行變位(i-1位)
                    now[k] = (byte)(origin[k] ^ b[i-1][k]);
                }
                bytesMoveToRight(1 , b[i-1]); //右移一下輔助數(shù)組,供下種情況使用
//                printTo8Binary("改變后秘鑰: " , now);
                //加密
                byte[] r = desCrypto(now,password);
//                printTo8Binary("改變后密文: " , r);
                digits += countBitDiff(r , result);//和原始密文比較,記錄改變位數(shù)
            }
            System.out.println("密文平均改變了"+(double)digits/10.0+"位");
        }
    }
    
    /**
     * 把byte數(shù)組類型轉(zhuǎn)換為8位二進(jìn)制類型字符串輸出
     * @param tByte 字節(jié)數(shù)組
     * @return
     */
    public static void printTo8Binary( byte[] tByte) {
        for(int i=0; i<tByte.length; i++) {
            String tString = Integer.toBinaryString((tByte[i] & 0xFF) + 0x100).substring(1);
            System.out.print(tString + " ");
        }
        System.out.println();
    }
    
    /**
     * 字節(jié)循環(huán)右移
     * @param num 右移位數(shù)
     * @param b 原字節(jié)
     * @return
     */
    public static byte cycleToRight(int num , byte b) {
        byte low = (byte) (b & (byte)(Math.pow(2 , num) - 1)); //記錄低num位
        byte temp = (byte)~( (byte)(Math.pow(2 , num) - 1) << (8 - num) );
        byte result = (byte) (b >> num & temp); //右移num位,高num位補(bǔ)0,同>>>
        result ^= low << (8 - num);
        return result;
    }
}

結(jié)果截圖###

結(jié)果截圖一
結(jié)果截圖二
結(jié)果截圖三
結(jié)果截圖四
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 0x01 目錄 常見編碼: ASCII編碼 Base64/32/16編碼 shellcode編碼 Quoted-p...
    H0f_9閱讀 13,503評(píng)論 2 17
  • 本文主要介紹移動(dòng)端的加解密算法的分類、其優(yōu)缺點(diǎn)特性及應(yīng)用,幫助讀者由淺入深地了解和選擇加解密算法。文中會(huì)包含算法的...
    蘋果粉閱讀 11,679評(píng)論 5 29
  • 這篇文章主要講述在Mobile BI(移動(dòng)商務(wù)智能)開發(fā)過程中,在網(wǎng)絡(luò)通信、數(shù)據(jù)存儲(chǔ)、登錄驗(yàn)證這幾個(gè)方面涉及的加密...
    雨_樹閱讀 3,039評(píng)論 0 6
  • CTF中那些腦洞大開的編碼和加密 0x00 前言 正文開始之前先閑扯幾句吧,玩CTF的小伙伴也許會(huì)遇到類似這樣的問...
    查無此人asdasd閱讀 6,457評(píng)論 0 19
  • 姓名:李俊秀 公司:寧波大發(fā)化纖有限公司 期數(shù):六項(xiàng)精進(jìn)259期學(xué)員 組別:感謝一組 【日精進(jìn)打卡第41天】 【知...
    花語花香9閱讀 204評(píng)論 0 0

友情鏈接更多精彩內(nèi)容