内容###
编程统计DES算法中明文(或密钥)改变1位,2位。。。64位的情况下,密文位数的变化量情况具体要求: 编程实现
1。在密钥不变情况下,明文改变1位,2位。。。64位,观察并统计密文位数变化规律。
2。在明文不变情况下,密钥改变1位,2位。。。64(56)位,观察并统计密文位数变化规律。
为了使统计局有客观性,上述每种情况可以重复多次,然后求平均值。
编程语言不限,建议采用java 或 C#等高级语言,因为这些语言中有内置的DES算法包,如果采用C/C++则需要自己到网上搜索DES算法库,
提交方式:将程序源代码和运行结果截图以电子文档的形式提交。
电子版作业上交要求###
注意:每个人的邮件标题和附件文件名要带上自己的编号203 姓名冯光平,学号3114006176,比如 001_31012xxx_张三_信息安全第X次作业 。这样便于管理。注意:直接发送到我的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());
//创建一个密匙工厂,然后用它把DESKeySpec转换成
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);
//现在,获取数据并加密
//正式执行加密操作
return cipher.doFinal(datasource);
}catch(Throwable e){
e.printStackTrace();
}
return null;
}
/**
* 初始化辅助数组 b是需要初始化的数组
*/
public static void initBytes() {
//64代表的是含有1-64个1的串,8代表8个字节(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));
}
}
/**
* 循环右移一个byte数组
* @param num 右移位数
* @param b 数组
* @return 右移后数组
*/
public static byte[] bytesMoveToRight(int num , byte[] b) {
byte[] bytes = b;
for(int i = 0; i < num; i++) { //每次循环右移一位,实现比较简单,但是效率比较慢
byte low = (byte)(bytes[bytes.length-1] & 1); //记录最后一个字节的最低1位
for(int j = 0; j < bytes.length; j++) { //从第一个字节开始
byte loww = (byte)(bytes[j] & 1); //记录最低一位
bytes[j] = (byte)(bytes[j]>>1&127); //右移一位,高位补0,可以用>>>代替,但是不知道为啥我的开发环境>>>失效了
bytes[j] = (byte) (bytes[j] ^ (low<<7) ); //把高位补上之前记录的最低1位
low = loww; //替换成新的最低1位
}
}
return bytes;
}
/**
* 求两个字节数组的二进制中不同的位数
* @param m
* @param n
* @return 返回不同的位数的个数
*/
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++) { //统计1的个数
while(ans[i] != 0){
ans[i] &= (byte)(ans[i] -1);
count++;
}
}
return count;
}
public static void main(String[] args) {
//初始化辅助数组
initBytes();
//初始明文
String word = "AAAAAAAA";
printTo8Binary( word.getBytes());
//初始秘钥
String password = "12345678";
printTo8Binary( password.getBytes());
//加密
byte[] result = desCrypto(word.getBytes(),password);
printTo8Binary(result);
/**改变明文位数**/
for(int i = 1; i <= 64; i++) { //改变1-64位
System.out.print("明文改变"+i+"位: ");
byte[] origin = word.getBytes(); //原始明文
int digits = 0; //改变位数
for(int j = 0; j < 10; j++) { //10种情况取平均
byte[] now = new byte[8]; //现在明文
for(int k = 0; k < origin.length; k++) { //用辅助数组进行变位(i-1位)
now[k] = (byte)(origin[k] ^ b[i-1][k]);
}
bytesMoveToRight(1 , b[i-1]); //右移一下辅助数组,供下种情况使用
// printTo8Binary("改变"+(j+1)+"后明文: " , now);
//加密
byte[] r = desCrypto(now,password);
// printTo8Binary("改变"+(j+1)+"后密文: " , r);
digits += countBitDiff(r , result);//和原始密文比较,记录改变位数
// System.out.println("密文改变了"+countBitDiff(r , result)+"位");
}
System.out.println("密文平均改变了"+(double)digits/10.0+"位");
}
/**改变秘钥位数**/
for(int i = 1; i <= 64; i++) { //改变1-64位
System.out.print("秘钥改变"+i+"位: ");
byte[] origin = password.getBytes();//原始秘钥
int digits = 0; //改变位数
for(int j = 0; j < 10; j++) { //10种情况取平均
byte[] now = new byte[8]; //现在秘钥
for(int k = 0; k < origin.length; k++) { //用辅助数组进行变位(i-1位)
now[k] = (byte)(origin[k] ^ b[i-1][k]);
}
bytesMoveToRight(1 , b[i-1]); //右移一下辅助数组,供下种情况使用
// printTo8Binary("改变后秘钥: " , now);
//加密
byte[] r = desCrypto(now,password);
// printTo8Binary("改变后密文: " , r);
digits += countBitDiff(r , result);//和原始密文比较,记录改变位数
}
System.out.println("密文平均改变了"+(double)digits/10.0+"位");
}
}
/**
* 把byte数组类型转换为8位二进制类型字符串输出
* @param tByte 字节数组
* @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();
}
/**
* 字节循环右移
* @param num 右移位数
* @param b 原字节
* @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;
}
}
结果截图###
结果截图一
结果截图二
结果截图三
结果截图四