6轮DES差分攻击java实现(免费完整代码)

  • 具体步骤
  1. 获得S盒的差分对应表

在具体程序实现时可以建一个8*64*16的三维集合数组,经过如下算法,就可以生成差分分布表Sd(代码中“this.”指实例化后的操作对象),例如Sd[2][32][12]存放了第二个S盒输入差为32,输出差为12的所有可能输入值(输入值可能不止一个,也可能为空,所以Sd[i][j][k]本身是一个集合)。

差分对应表的一部分如下图所示,下图中S8表示第8个S盒,dSin表示S盒的输入差,dSout表示输出差,冒号后的值表示可能的输入值,该输入值为用十六进制表示的6比特值。

  1. 计算S盒的输入差与输出差(第六轮不交换)

如下图所示,dSin,dSout分别表示S盒的输入差和输出差,dSin是对第六轮密文差的右32比特做一个E盒扩展,dSout是将第六轮密文差的左32比特与特征值的右32比特进行异或,再进行一次逆P盒变换的结果。

  1. 设置特征值与候选S盒

取2个不同的特征值和候选S盒,才能算出完整的密钥。

  1. 过滤操作

根据第2步计算的S盒输入输出差查S盒的差分分布表,以获得S盒可能的输入值,如果有一个S盒的差分布表的输入值集合为空集,则该明密对一定是错误对,将不对对应的密钥值进行计数。 如果通过过滤,则找出对应的密钥集合,并对密钥集合中对应的密钥进行计数。

  1. 生成N个明密对,重复上述操作并统计最终的密钥结果
  • 运行结果

本次测试要计算的密钥K6值0x39,0x25,0x0d,0x3a,0x1a,0x21 , 0x13,0x09。当特征值设为0x40,0x08,0x00,0x00,0x04,0x00,0x00, 0x00时,不同明密对的统计结果如下图(其中k2:1b:2<- -- ->00:1表示第2个S盒对应的密钥集合中0x1b出现次数最多,出现了2次,0x00次之,出现了1次)。

 

从上图可以看到,在100对明密以内就得出了5个候选S盒对应的密钥,在之后的计算中,正确密钥的统计次数与错误密钥的统计次数的差距将会不断拉大。下图是输入10000对明密对后的统计结果,可以看到,正确密钥的统计次数都在错误密钥统计次数的2倍以上。

完整代码共有3个文件,其中DES_6R生成6轮DES加密的结果,其输入由随机生成。De_6R用于对密钥集合进行计数,testDe_6R用于测试。

DES_6R.java

package De_6R;

public class DES_6R {
	private byte[] key=null;
	private byte[][] ikey=null;
	private byte[] L0=null,R0=null;
	private byte[] Ln=null,Rn=null;
	private static byte[][] S= {{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},
								{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},
								{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},
								{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},
								{2,12,4,1,7,10,11,6,5,8,3,15,13,0,14,9,14,11,2,12,4,7,13,1,5,0,15,13,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},
								{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},
								{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},
								{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}};

	public DES_6R(String key) {
		setKey(key);
		setLR0();
	}
	public DES_6R(byte[] key) {
		setKey(key);
		setLR0();
	}
	public DES_6R() {
		setKey(new byte[0]);
		setLR0();
	}
	private byte[] PC1(byte[] in) {
		byte[] result=new byte[8];
		result[0]=(byte) (((in[7]>>1)&0x40)|((in[6]>>2)&0x20)|((in[5]>>3)&0x10)|((in[4]>>4)&0x08)|((in[3]>>5)&0x04)|((in[2]>>6)&0x02)|((in[1]>>7)&0x01));
		result[1]=(byte) (((in[0]>>1)&0x40)|((in[7]>>1)&0x20)|((in[6]>>2)&0x10)|((in[5]>>3)&0x08)|((in[4]>>4)&0x04)|((in[3]>>5)&0x02)|((in[2]>>6)&0x01));
		result[2]=(byte) (((in[1]   )&0x40)|((in[0]>>1)&0x20)|((in[7]>>1)&0x10)|((in[6]>>2)&0x08)|((in[5]>>3)&0x04)|((in[4]>>4)&0x02)|((in[3]>>5)&0x01));
		result[3]=(byte) (((in[2]<<1)&0x40)|((in[1]   )&0x20)|((in[0]>>1)&0x10)|((in[7]>>1)&0x08)|((in[6]>>2)&0x04)|((in[5]>>3)&0x02)|((in[4]>>4)&0x01));
		result[4]=(byte) (((in[7]<<5)&0x40)|((in[6]<<4)&0x20)|((in[5]<<3)&0x10)|((in[4]<<2)&0x08)|((in[3]<<1)&0x04)|((in[2]   )&0x02)|((in[1]>>1)&0x01));
		result[5]=(byte) (((in[0]<<5)&0x40)|((in[7]<<3)&0x20)|((in[6]<<2)&0x10)|((in[5]<<1)&0x08)|((in[4]   )&0x04)|((in[3]>>1)&0x02)|((in[2]>>2)&0x01));
		result[6]=(byte) (((in[1]<<4)&0x40)|((in[0]<<3)&0x20)|((in[7]<<1)&0x10)|((in[6]   )&0x08)|((in[5]>>1)&0x04)|((in[4]>>2)&0x02)|((in[3]>>3)&0x01));
		result[7]=(byte) (((in[2]<<3)&0x40)|((in[1]<<2)&0x20)|((in[0]<<1)&0x10)|((in[3]>>1)&0x08)|((in[2]>>2)&0x04)|((in[1]>>3)&0x02)|((in[0]>>4)&0x01));
		return result;
	}
	private byte[] PC2(byte[] in) {
		byte[] result=new byte[8];
		result[0]=(byte) (((in[1]<<5)&0x20)|((in[2]   )&0x10)|((in[1]   )&0x08)|((in[3]>>2)&0x04)|((in[0]>>5)&0x02)|((in[0]>>2)&0x01));
		result[1]=(byte) (((in[0]<<1)&0x20)|((in[3]<<4)&0x10)|((in[2]>>3)&0x08)|((in[0]<<1)&0x04)|((in[2]<<1)&0x02)|((in[1]>>4)&0x01));
		result[2]=(byte) (((in[3]   )&0x20)|((in[2]<<2)&0x10)|((in[1]<<1)&0x08)|((in[0]>>1)&0x04)|((in[3]>>1)&0x02)|((in[1]>>6)&0x01));
		result[3]=(byte) (((in[2]   )&0x20)|((in[0]<<4)&0x10)|((in[3]<<2)&0x08)|((in[2]<<1)&0x04)|((in[1]   )&0x02)|((in[0]>>5)&0x01));
		result[4]=(byte) (((in[5]<<4)&0x20)|((in[7]   )&0x10)|((in[4]>>1)&0x08)|((in[5]>>3)&0x04)|((in[6]>>1)&0x02)|((in[7]>>1)&0x01));
		result[5]=(byte) (((in[4]   )&0x20)|((in[5]<<2)&0x10)|((in[7]>>2)&0x08)|((in[6]>>2)&0x04)|((in[4]>>1)&0x02)|((in[6]>>1)&0x01));
		result[6]=(byte) (((in[6]>>0)&0x20)|((in[6]<<4)&0x10)|((in[5]   )&0x08)|((in[7]<<2)&0x04)|((in[4]   )&0x02)|((in[7]>>3)&0x01));
		result[7]=(byte) (((in[6]<<2)&0x20)|((in[5]<<4)&0x10)|((in[7]>>3)&0x08)|((in[5]>>4)&0x04)|((in[4]>>5)&0x02)|((in[4]>>3)&0x01));
		return result;
	}
	private byte[] shift(byte[] in,int n) {
		byte[] result=new byte[8];
		for(int i=0;i<8;i++) {
			if(i==3)result[3]=(byte) (((in[3]<<n)|(in[0]>>(7-n)))&0x7f);
			else if(i==7)result[7]=(byte) (((in[7]<<n)|(in[4]>>(7-n)))&0x7f);
			else result[i]=(byte) (((in[i]<<n)|(in[i+1]>>(7-n)))&0x7f);
		}
		return result;
	}
	private void geneKey() {
		this.ikey=new byte[6][8];
		byte[] PC1ShiftOut,PC2Out;
		int[] shiftCount= {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
		PC1ShiftOut=PC1(this.key);
		for(int i=0;i<6;i++) {
			PC1ShiftOut=shift(PC1ShiftOut, shiftCount[i]);
			PC2Out=PC2(PC1ShiftOut);
			System.arraycopy(PC2Out, 0, this.ikey[i], 0, 8);
		}
	}
	private byte[] E(byte[] in) {
		byte[] result=new byte[8];
		result[0]=(byte) (((in[3]<<5)&0x20)|((in[0]>>3)&0x10)|((in[0]>>3)&0x08)|((in[0]>>3)&0x04)|((in[0]>>3)&0x02)|((in[0]>>3)&0x01));
		result[1]=(byte) (((in[0]<<1)&0x20)|((in[0]<<1)&0x10)|((in[0]<<1)&0x08)|((in[0]<<1)&0x04)|((in[0]<<1)&0x02)|((in[1]>>7)&0x01));
		result[2]=(byte) (((in[0]<<5)&0x20)|((in[1]>>3)&0x10)|((in[1]>>3)&0x08)|((in[1]>>3)&0x04)|((in[1]>>3)&0x02)|((in[1]>>3)&0x01));
		result[3]=(byte) (((in[1]<<1)&0x20)|((in[1]<<1)&0x10)|((in[1]<<1)&0x08)|((in[1]<<1)&0x04)|((in[1]<<1)&0x02)|((in[2]>>7)&0x01));
		result[4]=(byte) (((in[1]<<5)&0x20)|((in[2]>>3)&0x10)|((in[2]>>3)&0x08)|((in[2]>>3)&0x04)|((in[2]>>3)&0x02)|((in[2]>>3)&0x01));
		result[5]=(byte) (((in[2]<<1)&0x20)|((in[2]<<1)&0x10)|((in[2]<<1)&0x08)|((in[2]<<1)&0x04)|((in[2]<<1)&0x02)|((in[3]>>7)&0x01));
		result[6]=(byte) (((in[2]<<5)&0x20)|((in[3]>>3)&0x10)|((in[3]>>3)&0x08)|((in[3]>>3)&0x04)|((in[3]>>3)&0x02)|((in[3]>>3)&0x01));
		result[7]=(byte) (((in[3]<<1)&0x20)|((in[3]<<1)&0x10)|((in[3]<<1)&0x08)|((in[3]<<1)&0x04)|((in[3]<<1)&0x02)|((in[0]>>7)&0x01));
		return result;
	}
	private byte[] S(byte[] in) {
		byte[] result=new byte[8];
		for(int i=0;i<8;i++) {
			int t=(in[i]&0x20)|((in[i]&0x01)<<4)|((in[i]>>1)&0xf);
			result[i]=S[i][t];
		}
		return result;
	}
	private byte[] P(byte[] in) {
		byte[] result=new byte[4];
		result[0]=(byte) (((in[3]<<7)&0x80)|((in[1]<<5)&0x40)|((in[4]<<5)&0x20)|((in[5]<<1)&0x10)|((in[7]   )&0x08)|((in[2]<<2)&0x04)|((in[6]<<1)&0x02)|((in[4]>>3)&0x01));
		result[1]=(byte) (((in[0]<<4)&0x80)|((in[3]<<5)&0x40)|((in[5]<<4)&0x20)|((in[6]<<2)&0x10)|((in[1]   )&0x08)|((in[4]   )&0x04)|((in[7]   )&0x02)|((in[2]>>2)&0x01));
		result[2]=(byte) (((in[0]<<5)&0x80)|((in[1]<<6)&0x40)|((in[5]<<5)&0x20)|((in[3]<<2)&0x10)|((in[7]<<3)&0x08)|((in[6]<<1)&0x04)|((in[0]   )&0x02)|((in[2]>>3)&0x01));
		result[3]=(byte) (((in[4]<<6)&0x80)|((in[3]<<3)&0x40)|((in[7]<<3)&0x20)|((in[1]<<2)&0x10)|((in[5]<<1)&0x08)|((in[2]<<1)&0x04)|((in[0]<<1)&0x02)|((in[6]>>3)&0x01));
		return result;
	}
	private byte[] XOR(byte[] in,byte[] ikey) {
		byte[] result=new byte[in.length];
		for(int i=0;i<in.length;i++)
			result[i]=(byte) (in[i]^ikey[i]);
		return result;
	}
	public void Excute() {
		byte[] Li=new byte[4];
		byte[] Ri=new byte[4];
		byte[] Xo;
		System.arraycopy(L0, 0, Li, 0, 4);
		System.arraycopy(R0, 0, Ri, 0, 4);
		for(int i=0;i<6;i++) {
			Xo=XOR(E(Ri), this.ikey[i]);
			Xo=XOR(P(S(Xo)),Li);
			Li=Ri;
			Ri=Xo;
		}
		Ln=Ri;
		Rn=Li;
	}
	
	public void Excute(byte[] L0,byte[] R0) {
		setLR0(L0,R0);
		Excute();
	}
	public void showInfo() {
		showKey();
		showIkey();
		showPlain();
		showCipher();
	}
	public void showIkeyN() {
		System.out.print("K5: ");
		for(int i=0;i<8;i++)
			System.out.print(String.format("%02x ",this.ikey[5][i]));
		System.out.println(); 
	}
	public void showIkey() {
		int i,j;
		for(i=0;i<6;i++) {
			System.out.print(String.format("K%d: ", i));
			for(j=0;j<8;j++)
				System.out.print(String.format("%02x ",this.ikey[i][j]));
			System.out.println(); 
		}
	}
	public void showKey() {
		int i;
		System.out.print("Key:\n  Hex:");
		for(i=0;i<8;i++)
			System.out.print(String.format("%02x ",this.key[i]));
		System.out.print("\n  CH:");
		String strKey=new String(this.key);
		System.out.println(strKey);
	}
	public void showPlain() {
		System.out.print("Plain: ");
		for(int i=0;i<4;i++)
			System.out.print(String.format("0x%02x,",this.L0[i]));
		for(int i=0;i<4;i++)
			System.out.print(String.format("0x%02x,",this.R0[i]));
		System.out.println();
	}
	public void showCipher() {
		System.out.print("Cipher: ");
		for(int i=0;i<4;i++)
			System.out.print(String.format("0x%02x,",this.Ln[i]));
		for(int i=0;i<4;i++)
			System.out.print(String.format("0x%02x,",this.Rn[i]));
		System.out.println();
	}
	public void setKey(byte[] key) {
		this.key=new byte[8];
		int n=key.length>8?8:key.length;
		for(int i=0;i<n;i++)
			this.key[i] = key[i];
		geneKey();
	}
	public void setKey(String key) {
		setKey(key.getBytes());
	}
	public void setLR0() {
		this.L0=new byte[4];
		this.R0=new byte[4];
		for(int i=0;i<4;i++) {
			this.L0[i]=(byte) (Math.random()*256);
			this.R0[i]=(byte) (Math.random()*256);
		}
	}
	public void updateLR0(byte[] Eigen) {
		for(int i=0;i<4;i++) {
			this.L0[i]=(byte) (this.L0[i]^Eigen[i]);
			this.R0[i]=(byte) (this.R0[i]^Eigen[i+4]);
		}
	}
	public void setLR0(byte[] L0,byte[] R0) {
		this.L0=new byte[4];
		this.R0=new byte[4];
		int nL=L0.length>4?4:L0.length;
		for(int i=0;i<nL;i++)
			this.L0[i] = L0[i];
		int nR=R0.length>4?4:R0.length;
		for(int i=0;i<nR;i++)
			this.R0[i] = R0[i];
	}
	public void setLR0(byte[] LR0) {
		this.L0=new byte[4];
		this.R0=new byte[4];
		int nL=LR0.length>4?4:LR0.length;
		for(int i=0;i<nL;i++)
			this.L0[i] = LR0[i];
		int nR=LR0.length>8?4:(nL-4);
		for(int i=0;i<nR;i++)
			this.R0[i] = LR0[i+4];
	}
	public byte[] getLR0() {
		if(L0==null||R0==null)return null;
		byte[] LR0=new byte[8];
		System.arraycopy(L0, 0, LR0, 0, 4);
		System.arraycopy(R0, 0, LR0, 4, 4);
		return LR0;
	}
	public byte[] getLRn() {
		if(Ln==null||Rn==null)return null;
		byte[] LRn=new byte[8];
		System.arraycopy(Ln, 0, LRn, 0, 4);
		System.arraycopy(Rn, 0, LRn, 4, 4);
		return LRn;
	}
}

De_6R.java

package De_6R;

import java.util.HashSet;
import java.util.Set;

@SuppressWarnings("rawtypes")
public class De_6R {
	private byte[] dC=null;
	private byte[] Ex=null;
	private byte[] Eigen=null;
	private boolean[] Sel_S=null;
	private Set[][][] Sd=new HashSet[8][64][16];
	private Set[] Keyi=new HashSet[8];
	private int[][] KeyCount=new int[8][64];
	private static int[][] S= {
			{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},
			{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},
			{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},
			{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},
			{2,12,4,1,7,10,11,6,5,8,3,15,13,0,14,9,14,11,2,12,4,7,13,1,5,0,15,13,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},
			{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},
			{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},
			{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}};

	public De_6R() {
		init(new byte[8],new boolean[8]);
	}
	public De_6R(byte[] eigen,boolean[] sels) {
		init(eigen,sels);
	}
	
	private byte[] E(byte[] in) {
		byte[] result=new byte[8];
		result[0]=(byte) (((in[3]<<5)&0x20)|((in[0]>>3)&0x10)|((in[0]>>3)&0x08)|((in[0]>>3)&0x04)|((in[0]>>3)&0x02)|((in[0]>>3)&0x01));
		result[1]=(byte) (((in[0]<<1)&0x20)|((in[0]<<1)&0x10)|((in[0]<<1)&0x08)|((in[0]<<1)&0x04)|((in[0]<<1)&0x02)|((in[1]>>7)&0x01));
		result[2]=(byte) (((in[0]<<5)&0x20)|((in[1]>>3)&0x10)|((in[1]>>3)&0x08)|((in[1]>>3)&0x04)|((in[1]>>3)&0x02)|((in[1]>>3)&0x01));
		result[3]=(byte) (((in[1]<<1)&0x20)|((in[1]<<1)&0x10)|((in[1]<<1)&0x08)|((in[1]<<1)&0x04)|((in[1]<<1)&0x02)|((in[2]>>7)&0x01));
		result[4]=(byte) (((in[1]<<5)&0x20)|((in[2]>>3)&0x10)|((in[2]>>3)&0x08)|((in[2]>>3)&0x04)|((in[2]>>3)&0x02)|((in[2]>>3)&0x01));
		result[5]=(byte) (((in[2]<<1)&0x20)|((in[2]<<1)&0x10)|((in[2]<<1)&0x08)|((in[2]<<1)&0x04)|((in[2]<<1)&0x02)|((in[3]>>7)&0x01));
		result[6]=(byte) (((in[2]<<5)&0x20)|((in[3]>>3)&0x10)|((in[3]>>3)&0x08)|((in[3]>>3)&0x04)|((in[3]>>3)&0x02)|((in[3]>>3)&0x01));
		result[7]=(byte) (((in[3]<<1)&0x20)|((in[3]<<1)&0x10)|((in[3]<<1)&0x08)|((in[3]<<1)&0x04)|((in[3]<<1)&0x02)|((in[0]>>7)&0x01));
		return result;
	}
	
	private byte[] InvP(byte[] in) {
		byte[] result=new byte[8];
		result[0]=(byte) (((in[1]>>4)&0x08)|((in[2]>>5)&0x04)|((in[2]   )&0x02)|((in[3]>>1)&0x01));
		result[1]=(byte) (((in[1]   )&0x08)|((in[3]>>2)&0x04)|((in[0]>>5)&0x02)|((in[2]>>6)&0x01));
		result[2]=(byte) (((in[2]<<3)&0x08)|((in[1]<<2)&0x04)|((in[3]>>1)&0x02)|((in[0]>>2)&0x01));
		result[3]=(byte) (((in[3]>>3)&0x08)|((in[2]>>2)&0x04)|((in[1]>>5)&0x02)|((in[0]>>7)&0x01));
		result[4]=(byte) (((in[0]<<3)&0x08)|((in[1]   )&0x04)|((in[3]>>6)&0x02)|((in[0]>>5)&0x01));
		result[5]=(byte) (((in[0]>>1)&0x08)|((in[3]>>1)&0x04)|((in[1]>>4)&0x02)|((in[2]>>5)&0x01));
		result[6]=(byte) (((in[3]<<3)&0x08)|((in[1]>>2)&0x04)|((in[2]>>1)&0x02)|((in[0]>>1)&0x01));
		result[7]=(byte) (((in[0]   )&0x08)|((in[3]>>3)&0x04)|((in[1]   )&0x02)|((in[2]>>3)&0x01));
		return result;
	}
	private byte[] XOR(byte[] in,byte[] ikey) {
		byte[] result=new byte[in.length];
		for(int i=0;i<in.length;i++)
			result[i]=(byte) (in[i]^ikey[i]);
		return result;
	}
	@SuppressWarnings("unchecked")
	public void excDecode() {
		if(this.dC==null)return;
		
		byte[] dCL=new byte[4];
		byte[] dCR=new byte[4];
		byte[] dSout,dSin;
		System.arraycopy(dC, 0, dCL, 0, 4);
		System.arraycopy(dC, 4, dCR, 0, 4);
		dSin=E(dCR);
		dSout=InvP(XOR(dCL,this.Eigen));
		
		boolean isEmpty=false;
		for(int i=0;i<8;i++) {
			if(this.Sel_S[i])
			{
				isEmpty=true;
				this.Keyi[i].clear();
				for (Object set : this.Sd[i][dSin[i]][dSout[i]]) {
					isEmpty=false;
					int n=(int) (((Integer) set).byteValue()^this.Ex[i]);
					this.Keyi[i].add(n);
				}
			}
			if(isEmpty)break;
		}
		if(!isEmpty) {
			for(int i=0;i<8;i++)
				if(this.Sel_S[i]){
					for(Object ki:this.Keyi[i])
						this.KeyCount[i][(int) ki]++;
				}
		}
	}
	@SuppressWarnings("unchecked")
	public void init(byte[] eigen,boolean[] sels) {
		setEigen(eigen);
		this.Sel_S=sels;
		for(int i=0;i<8;i++)
			this.Keyi[i]=new HashSet<Integer>();
		for(int i=0;i<8;i++) 
			for(int j=0;j<64;j++)
				for(int k=0;k<16;k++) 
					this.Sd[i][j][k]=new HashSet<Integer>();
		for(int i=0;i<8;i++) 
			for(int j=0;j<64;j++)
				for(int k=0;k<64;k++) {
					int t1=(j&0x20)|((j&0x01)<<4)|((j>>1)&0xf);
					int t2=(k&0x20)|((k&0x01)<<4)|((k>>1)&0xf);
					this.Sd[i][j^k][S[i][t1]^S[i][t2]].add(j);
				}
	}
	
	public void setEigen(byte[] eigen) {
		this.Eigen=new byte[4];
		for(int i=0;i<4;i++)
			this.Eigen[i]=eigen[i+4];
	}
	public void setSels(boolean[] sels) {
		this.Sel_S=sels;
	}
	public void setC(byte[] C1,byte[] C2) {
		this.dC=new byte[8];
		byte[] RC1=new byte[4];
		System.arraycopy(C1, 4, RC1, 0, 4);
		this.Ex=E(RC1);
		for(int i=0;i<8;i++)
			this.dC[i]=(byte) (C1[i]^C2[i]);
	}
//	39 25 0d 3a 1a 21 13 09 
	public void showDC() {
		System.out.print("dP: ");
		for(int i=0;i<8;i++)
			System.out.print(String.format("%02x ",this.dC[i]));
		System.out.println();
	}
	public void ShowSd() {
		for(int i=0;i<8;i++) {
			for(int j=0;j<64;j++)
				for(int k=0;k<16;k++) {
					System.out.print("S"+(i+1)+" dSin="+j+" dSout="+k+": ");
					for (Object b : this.Sd[i][j][k].toArray())
						System.out.print(String.format("%02x ", ((Integer)b).byteValue()));
					System.out.println();
				}
			System.out.println();
		}
	}
	public void ShowKeyCount() {
		for(int i=0;i<8;i++) {
			System.out.print(String.format("K%d:", i));
			for(int j=0;j<64;j++) {
				if(j%8==0)System.out.println();
				System.out.print(String.format("%02x:%d\t",j, this.KeyCount[i][j]));
			}
			System.out.println();
		}
	}
	public void showIkeySel() {
		for(int i=0;i<8;i++) {
			if(this.Sel_S[i]) {
				int max=this.KeyCount[i][0];
				int max_1=max;
				int ki_max=0;
				int ki_max_1=0;
				for(int j=1;j<64;j++) {
					if(max<this.KeyCount[i][j]) {
						max_1=max;
						ki_max_1=ki_max;
						max=this.KeyCount[i][j];
						ki_max=j;
					}
				}
				if(ki_max==0) {
					max_1=this.KeyCount[i][1];
					ki_max_1=1;
					for(int j=2;j<64;j++)
						if(max_1<this.KeyCount[i][j]) {
							max_1=this.KeyCount[i][j];
							ki_max_1=j;
						}
				}
				System.out.printf("k%d:%02x:%d<-->%02x:%d\n", i+1,ki_max,max,ki_max_1,max_1);
			}
		}
		System.out.println();
	}
	public void showIkey() {
		for(int i=0;i<8;i++) {
			int max=this.KeyCount[i][0];
			int max_1=max;
			int ki_max=0;
			int ki_max_1=0;
			for(int j=1;j<64;j++) {
				if(max<this.KeyCount[i][j]) {
					max_1=max;
					ki_max_1=ki_max;
					max=this.KeyCount[i][j];
					ki_max=j;
				}
			}
			if(ki_max==0) {
				max_1=this.KeyCount[i][1];
				ki_max_1=1;
				for(int j=2;j<64;j++)
					if(max_1<this.KeyCount[i][j]) {
						max_1=this.KeyCount[i][j];
						ki_max_1=j;
					}
			}
			System.out.printf("k%d:%02x:%d<-->%02x:%d\n", i+1,ki_max,max,ki_max_1,max_1);
		}
		System.out.println();
	}
}

testDe_6R.java

package De_6R;

import java.util.Scanner;

public class testDe_6R {
	public static void main(String[] args) {
		DES_6R dx=new DES_6R("dbfd732ja");
		dx.showIkeyN();
		De_6R de=new De_6R();
		test(dx,de);
		System.out.println("最终结果:");
		de.showIkey();
	}
	public static void test(DES_6R dx,De_6R de) {
		byte[] Eigen1= {0x40,0x08,0x00,0x00,0x04,0x00,0x00,0x00};			//特征值1
		boolean[] Sel_S1= {false,true,false,false,true,true,true,true};
		byte[] Eigen2= {0x00,0x20,0x00,0x08,0x00,0x00,0x04,0x00};			//特征值2
		boolean[] Sel_S2= {true,false,true,true,false,false,false,false};
		
		Scanner scanner=new Scanner(System.in);
		System.out.print("请输入明密文对个数N:");
		int N=scanner.nextInt();
		scanner.close();
		
		de.setSels(Sel_S1);
		de.setEigen(Eigen1);
		Update(dx,de,Eigen1,N);
		
		de.setSels(Sel_S2);
		de.setEigen(Eigen2);
		Update(dx,de,Eigen2,N);
	}
	public static void Update(DES_6R dx,De_6R de,byte[] Eigen,int N) {
		byte[] C1,C2;
		for(int i=0;i<N;i++) {
			if(i>0&&i%(N/5)==0) {
				System.out.printf("%d对明密对统计结果:\n",i);
				de.showIkeySel();
			}
			dx.setLR0();
			dx.Excute();
			C1=dx.getLRn();
			dx.updateLR0(Eigen);
			dx.Excute();
			C2=dx.getLRn();
			
			de.setC(C1, C2);
			de.excDecode();
		}
		System.out.printf("%d对明密对统计结果:\n",N);
		de.showIkeySel();
	}
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

实无所得

随缘打赏吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值