首页 > 编程语言 > 详细

Des加密算法 java部分实现

时间:2017-03-23 21:46:10      阅读:222      评论:0      收藏:0      [点我收藏+]

Des算法 java实现(js)

 

  1. 获取明文和密钥 ,并且通过2进制转换,存储为01串,保存在int[64]的数组中(本文省略该步骤,和最后的还原步骤)
  2. 流程如下:

    (1)先了解变换,沙盒先后了解均可(变换和沙盒在下面做特殊说明)

    (2)将明文m进行ip变换,获得ipm

    (3)通过k获取16个子密钥key[0-15],每个子密钥48位->(过程如下)

      ->64位k密钥通过pc1变换缩小为48位

      ->均分为c[0] ,d[0].执行移位操作等得到c[1-16] d[1-16]

        移位操作为循环左移

        16次移位中,1,2,9,16循环左移一位,其他左移2位

        移位之后进行合并得到c[i+1] d[i+1]

        (比如c[0]d[0]均左移1位得到c[1]d[1])

        C[i] d[i] 合并后经过pc2变换得到key[i-1],即子密钥

        (备注: 如k[0-15]由c[1-16]和d[1-16]合并变换而来)

      (4)将ipm分为2部分,即l[0],r[0].

      (5)确定f函数值->

        ->将输入的r[i], 开始为r[0],32位通过E变换,膨胀为48位

        ->膨胀后的结果与k[i]做异或

        ->48位通过沙盒s,缩小为32位(沙盒变换,做特殊说明)

        ->进行p变换

        ->通过上面步骤可以得到r[0],l[0] , key[0-15] f[0]

          R[i+1] = l[i] 异或 f[i]

          L[i+1] = r[i]

          即: 变换右边为左边与函数f的异或,赋值左边等于右边

          每得到一个新的右边r[i],将可以与已知k[i]确定f[i]函数值使得算法延续

          进行16次,得到r[0-16] l[0-16]

          将r[16]和l[16]合并,经过ip1变换得到密文e

          (注意最后一次合并,右边放左边了,其他合并都正常)

3.特殊说明

  1> 变换. 一定位数的数组,将位置打乱,甚至有些重复出现,有些不再出现,由此产生一个新数组的过程,被我称为变换。

    举例: int[] a = {5,6,7}

    变换矩阵为 { 2, 1, 1,0}

    那么取{  a[2],a[1] , a[1] ,a[0] }为新数组,即{7,6,6,5 } 为产生的新数组(当然,des操作中数组值只有0和1,变换后长度不确定)

  2 >沙盒

    效果: 48位缩小为32位,并且数据发生变化

    操作:均分为8份,8份每份长为6个01串 ,如s0-s5

    计算x =s0*2+s5;

      y= s4+s3*2+s2*4+s1*8;

      每个6位通过上面计算后都在自己的沙盒中找沙盒中x行y列值

      将该值转为4位2进制01串

      将8个4位2进制合并编程32位

package com;

/**
 * 
 * @author 黎锦燊
 * @qq:303058345
 */@tel 15927404406
public class Change {
	//这是一些变换表
	int[] m = 
		{
				0,1,1,0,1,1,0,0,
				0,1,1,0,0,1,0,1,
				0,1,1,0,0,0,0,1,
				0,1,1,1,0,0,1,0,
				0,1,1,0,1,1,1,0,
				0,1,1,0,1,0,0,1,
				0,1,1,0,1,1,1,0,
				0,1,1,0,0,1,1,1
		};
	int[] k =
		{
				0,1,1,0,0,0,1,1,
				0,1,1,0,1,1,1,1,
				0,1,1,0,1,1,0,1,
				0,1,1,1,0,0,0,0, 
				0,1,1,1,0,1,0,1,
				0,1,1,1,0,1,0,0,
				0,1,1,0,0,1,0,1,
				0,1,1,1,0,0,1,0
		};
	int[] ip = {  57,49,41,33,25,17,9,1,  
  59,51,43,35,27,19,11,3,  
  61,53,45,37,29,21,13,5,  
  63,55,47,39,31,23,15,7,  
  56,48,40,32,24,16,8,0,  
  58,50,42,34,26,18,10,2,  
  60,52,44,36,28,20,12,4,  
  62,54,46,38,30,22,14,6};   
	int[] ip1 = {39,7,47,15,55,23,63,31,  
	           38,6,46,14,54,22,62,30,  
	           37,5,45,13,53,21,61,29,  
	           36,4,44,12,52,20,60,28,  
	           35,3,43,11,51,19,59,27,  
	           34,2,42,10,50,18,58,26,  
	           33,1,41,9,49,17,57,25,  
	           32,0,40,8,48,16,56,24};  
	int[] E= {31, 0, 1, 2, 3, 4,  
   3,  4, 5, 6, 7, 8,  
   7,  8,9,10,11,12,  
   11,12,13,14,15,16,  
   15,16,17,18,19,20,  
   19,20,21,22,23,24,  
   23,24,25,26,27,28,  
   27,28,29,30,31, 0};  
	int[] P = {15,6,19,20,28,11,27,16,  
   0,14,22,25,4,17,30,9,  
   1,7,23,13,31,26,2,8,  
   18,12,29,5,21,10,3,24};  
	int S[][][] =//S1  
      {{{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}},  
          //S2  
        {{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}},  
        //S3  
        {{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}},  
        //S4  
        {{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}},  
        //S5  
        {{2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9},  
        {14,11,2,12,4,7,13,1,5,0,15,10,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}},  
        //S6  
        {{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}},  
        //S7  
        {{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}},  
        //S8  
        {{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}}};  
	int[] pc1 = {56,48,40,32,24,16,8,  
        0,57,49,41,33,25,17,  
        9,1,58,50,42,34,26,  
        18,10,2,59,51,43,35,  
        62,54,46,38,30,22,14,  
        6,61,53,45,37,29,21,  
        13,5,60,52,44,36,28,  
        20,12,4,27,19,11,3};  
	int[] pc2 = {13,16,10,23,0,4,2,27,  
        14,5,20,9,22,18,11,3,  
        25,7,15,6,26,19,12,1,  
        40,51,30,36,46,54,29,39,  
        50,44,32,47,43,48,38,55,  
        33,52,45,41,49,35,28,31};  
	
	//key[0]对应key1 ,即k[0-15]对应k1-k16
	
	//产生密钥过程
	public int[][] getKey()
	{
		out("key     ->");
		display(k);
		int[][] key= new int[16][];
		int first0[] = new int[56];
		int second[] = new int[48];
		
		int[][] c=new int[17][];
		int[][] d=new int[17][];
		//通过pc1,变换位置
		first0= change(k,pc1);
		out("first0  ->");
		display(first0);
		
		c[0]= split(first0)[0];
		d[0]=split(first0)[1];
		for(int i=1;i<=16;i++)
		{
			if(i==1 || i==2 ||i==9 ||i==16)
	        {
	        	//循环左移一位  
	        	c[i]=moveleft(c[i-1],1) ;
	        	d[i]=moveleft(d[i-1],1) ;
	        } 
	        else
	        {
	        	//循环左移两位 
	        	c[i]=moveleft(c[i-1],2) ;
	        	d[i]=moveleft(d[i-1],2) ;
	        }
		}
		
		for(int i=1;i<=16;i++)
		{
			second=add(c[i],d[i]);
			key[i-1]=change(second,pc2);
		}
		return key;
	}
	
	//加密过程
	public void DES()
	{
		out("m------->");
		display(m);
		//1.将明文m通过ip变换,获得ipm.
		int[] ipm = change(m,ip);
		out("ipm----->");
		display(ipm);
		//1.1 获得子密钥
		int[][] key=getKey();
		for(int i=0;i<16;i++)
		{
			out("key["+i+"]--->");
			display(key[i]);
		}
		System.out.println("get the right childkey");
		
		//2.将ipm分为2部分,即l0,r0
		int[][] l=new int[17][];
		int[][] r=new int[17][];
		l[0]=split(ipm)[0];
		r[0]=split(ipm)[1];
		int[][] f=new int[16][32];
		for(int i=0;i<16;i++)
		{
			f[i]=functionf(r[i], key[i]);
			out("f["+i+"]-->");
			display(f[i]);
			r[i+1]=exclusiveOr(l[i],f[i]);
			l[i+1]=r[i];
		}
		
		for(int i=0;i<17;i++)
		{
			out("l["+i+"]--->");
			display(l[i]);
			out("r["+i+"]--->");
			display(r[i]);
		}
		
		
		int[] result = new int[64];
		result = add(r[16],l[16]);
		result = change(result,ip1);
		out("-------------->");
		display(result);
	}
	
	//异或运算
	public int[] exclusiveOr(int[] l,int[] f)
	{
			int [] result = new int[l.length];
			for(int i=0;i<l.length;i++)
			{
				result[i]=l[i]^f[i];
			}
		return result;
	}
	
	//将一个6位数组s ,通过第b个沙河,变成一个长度为4的数组
	public int[] functionS(int[] s, int b)
	{
		int[] result = new int[4];
		int x =s[0]*2+s[5];
		int y= s[4]+s[3]*2+s[2]*4+s[1]*8;
		out(S[b][x][y]+"-");
		result=intToHex(S[b][x][y],4);
		return result;
	}
	
	//将一个int s 转换为2进制,保存再长度为b的数组中,数组存储0/1,输出会发现倒序
	public int[] intToHex(int s ,  int b)
	{
		int[] result = new int[b];
		for(int i=0;i<b;i++)
		{
			result[b-i-1]= s%2; 
			s=s/2;
		}
		return  result;
	}
	
	//将32位,与48密钥处理得到32位
	public int[] functionf(int[] r, int[] k)
	{
		//将输入r0 32位膨胀为48位
		int[] result = new int[32];
		int[] the = new int[48];
		the = change(r,E);
		
		//膨胀后与k1异或
		int[] the1 = exclusiveOr(the, k);
		//将48位数组拆分位8个6位
		int[][] th = new int[8][];
		 th[0]=split(split(split(the1)[0])[0])[0];
		 th[1]=split(split(split(the1)[0])[0])[1];
		 th[2]=split(split(split(the1)[0])[1])[0];
		 th[3]=split(split(split(the1)[0])[1])[1];
		 th[4]=split(split(split(the1)[1])[0])[0];
		 th[5]=split(split(split(the1)[1])[0])[1];
		 th[6]=split(split(split(the1)[1])[1])[0];
		 th[7]=split(split(split(the1)[1])[1])[1];
		//通过沙河 进行s变换,缩位32位
		 int[][] ts = new int[8][4];
		 for(int i=0;i<8;i++)
		 {
			ts[i]= functionS(th[i], i);
		 }
		 int[] tu = new int[32];
		 int[] tk = ts[0];
		 for(int i=1;i<8;i++)
		 {
			 tk=add(tk,ts[i]);
		 }
		 tu=tk;
		//进行p变换,混乱位置
		result = change(tu,P);
		return result;		
	}
	
	//输出一个数组存储的数据
	public void display(int [] s)
	{
		for(int i=0;i<s.length;i++)
		{ System.out.print(s[i]);}
		System.out.println();
	}
	
	//输出一个不换行的字符串
	public void out(String s)
	{
		System.out.print(s);
	}
	
	//将数组old经过way矩阵位置置换
	public int[] change(int[] old , int[] way)
	{
		int[] now =new int[way.length];
		for(int i=0;i<way.length;i++)
		{
			now[i]=old[way[i]];
		}
		return now;
	}
	
	//将数组old分成2个保存再now[0]和now[1]中
	public int[][] split(int[] old)
	{
		int[][] now = new int[2][old.length/2];
		for(int i=0;i<old.length/2;i++)
		{
			now[0][i]=old[i];
			now[1][i]=old[i+old.length/2];
		}
		return now;
	}
	//将2个数组进行合并
	public int[] add(int[] left,int[] right)
	{
		int[] now = new int[left.length+right.length];
		for(int i=0;i<left.length;i++)
		{
			now[i]=left[i];
		}
		for(int i=left.length;i<right.length+left.length;i++)
		{
			now[i]=right[i-left.length];
		}
		return now;
	}
	
	//数组m循环左移k位
	public int[] moveleft(int[] m, int k)
	{
		int[] result= new int[m.length];
		int[] the = new int[k];
		for(int i=0;i<k;i++)
		{
			the[i] = m[i]; 
		}
		for(int i=0;i<m.length-k;i++)
		{
			result[i]=m[i+k];
		}
		for(int i=m.length-k;i<m.length;i++)
		{
			result[i]=the[i- (m.length-k)];
		}
		return result;
	}
	
	public static void main(String[] args)
	{
		Change c = new Change();
		c.DES();
	}
}

  

 

Des加密算法 java部分实现

原文:http://www.cnblogs.com/UseMyWay/p/des.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!