內(nèi)容###
編程統(tǒng)計DES算法中明文(或密鑰)改變1位旬盯,2位誊爹。。瓢捉。64位的情況下频丘,密文位數(shù)的變化量情況具體要求: 編程實現(xiàn)
1。在密鑰不變情況下泡态,明文改變1位搂漠,2位。某弦。桐汤。64位,觀察并統(tǒng)計密文位數(shù)變化規(guī)律靶壮。
2怔毛。在明文不變情況下,密鑰改變1位腾降,2位拣度。。螃壤。64(56)位抗果,觀察并統(tǒng)計密文位數(shù)變化規(guī)律。
為了使統(tǒng)計局有客觀性奸晴,上述每種情況可以重復多次冤馏,然后求平均值。
編程語言不限寄啼,建議采用java 或 C#等高級語言逮光,因為這些語言中有內(nèi)置的DES算法包代箭,如果采用C/C++則需要自己到網(wǎng)上搜索DES算法庫,
提交方式:將程序源代碼和運行結(jié)果截圖以電子文檔的形式提交涕刚。
電子版作業(yè)上交要求###
注意:每個人的郵件標題和附件文件名要帶上自己的編號203 姓名馮光平嗡综,學號3114006176,比如 001_31012xxx_張三_信息安全第X次作業(yè) 副女。這樣便于管理蛤高。注意:直接發(fā)送到我的QQ郵箱蚣旱,不要通過通過QQ傳輸碑幅。
特別要注意,附件的文件名也要采用上述命名格式塞绿,不要使用“文檔1.docx”等默認文件名沟涨,如果包含多個文件,請先用壓縮...
源代碼###
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)建一個密匙工廠异吻,然后用它把DESKeySpec轉(zhuǎn)換成
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(desKey);
//Cipher對象實際完成加密操作
Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
//用密匙初始化Cipher對象
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個1的串,8代表8個字節(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)右移一個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)右移一位诀浪,實現(xiàn)比較簡單棋返,但是效率比較慢
byte low = (byte)(bytes[bytes.length-1] & 1); //記錄最后一個字節(jié)的最低1位
for(int j = 0; j < bytes.length; j++) { //從第一個字節(jié)開始
byte loww = (byte)(bytes[j] & 1); //記錄最低一位
bytes[j] = (byte)(bytes[j]>>1&127); //右移一位,高位補0雷猪,可以用>>>代替睛竣,但是不知道為啥我的開發(fā)環(huán)境>>>失效了
bytes[j] = (byte) (bytes[j] ^ (low<<7) ); //把高位補上之前記錄的最低1位
low = loww; //替換成新的最低1位
}
}
return bytes;
}
/**
* 求兩個字節(jié)數(shù)組的二進制中不同的位數(shù)
* @param m
* @param n
* @return 返回不同的位數(shù)的個數(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)計1的個數(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ù)組進行變位(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ù)組進行變位(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位二進制類型字符串輸出
* @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位補0验夯,同>>>
result ^= low << (8 - num);
return result;
}
}
結(jié)果截圖###
結(jié)果截圖一
結(jié)果截圖二
結(jié)果截圖三
結(jié)果截圖四