一.SDES加密算法
SDES的算法如上图所示,作者将其分为三个部分讲解:
1.子密钥的产生2.加密部分
2.1 对于输入的8位明文P=(p1,p2,p3,4,p5,p6,p7,p8),首先做一次IP置换得到P1=(k2,k6,k3,k1,k4,k8,k5,k7),IP置换相当于对P进行矩阵的乘法,对应矩阵为:
IP的逆变换IPI可以同样可以看成是矩阵的乘法,对应的矩阵为:
2.2 得到P1以后开始,进入Fk函数进行处理,这是SDES加密的核心部分,也是最为复杂的部分,对应的fk函数为:
(3) S0&S1是指对E/P变换的8位结果的高低4位,分别做S盒变换得到两个2位数,然后合并成新的4位数,其中S0和S1分别为:
S0用于对高4位做变换,S1用于对低4位做变换,变换的过程为将4位的输入数的第0位(设为a),第3位(设为b)结合成新的数i,结合方式为i=a*2+b,以同样的方式将4位输入数的第2位,第4位结合成新的数j,然后用Sij(就是S盒中的S[i][j],两位数,最大为3)取代原来的4位数,例如:S0(1,1,0,1)=S0[2][1]=1=(01),红色标记处。
(4)连接S0得到2位和S1得到2位,得到4位数,并做P4变换,P4变换的结果为P4(p1,p2,3,4)=(p2,p4,p3,p1)
(5)上述操作都是在输入明文的R部分做的,操作完成后与L进行异或,得到新的4位数,最后于原始的R合并成8位中间态。fk函数对应的细节,如下图所示:
图2 fk函数细节二.SDES算法实现
/*********************************************************** *作者: chw1989 *日期:2012.4.5 *邮箱:[email protected] ***********************************************************/ public class SDES{ static int SubKey1=0; static int SubKey2=0; static int P10[]=new int[]{3,5,2,7,4,10,1,9,8,6}; static int P8[]=new int[]{6,3,7,4,8,5,10,9}; static int P4[]=new int[]{2,4,3,1}; static int IP8[]=new int[]{2,6,3,1,4,8,5,7}; static int IP8I[]=new int[]{4,1,3,5,7,2,8,6}; static int EP[]=new int[]{4,1,2,3,2,3,4,1}; static int S0[][]={ {1,0,3,2}, {3,2,1,0}, {0,2,1,3}, {3,1,3,2}, }; static int S1[][]={ {0,1,2,3}, {2,0,1,3}, {3,0,1,0}, {2,1,0,3}, }; //通过连续位操作进行数据变换,区别于C++版本的通过矩阵乘的方式实现数据变换 static int Transformation(int FromNuber,int P_Vector[],int NumberLen){ int ToNumber=0; for(int i=0;i<P_Vector.length;i++){ ToNumber<<=1; ToNumber|=(FromNuber>>(NumberLen-P_Vector[i]))&1; } return ToNumber; } static void SetKey(int Key){ int WorkKey,LKey,RKey; WorkKey=Transformation(Key,P10,10); LKey=WorkKey>>5;//右移5位取出高(左)5位的值 RKey=WorkKey & 0x1f;//和"0000011111"做与运算,可以取出低(左)5位的值 //循环左移1位,相当于先右移4位,取出最高位,然后与"0000001111"做与运算, //并右移1位,最后做或运算,即可得到循环右移1位的结果 LKey=(LKey>>4) | ((LKey & 0xf)<<1);//循环左移1位 RKey=(RKey>>4) | ((RKey & 0xf)<<1);//循环左移1位 WorkKey=(LKey<<5) | RKey; SubKey1=Transformation(WorkKey,P8,10); LKey=WorkKey>>5;//右移5位取出高(左)5位的值 RKey=WorkKey&0x1f;//和"0000011111"做与运算,可以取出低(左)5位的值 LKey=(LKey>>3) | ((LKey & 0x7)<<2);//循环左移2位 RKey=(RKey>>3) | ((RKey & 0x7)<<2);//循环左移2位 WorkKey=(LKey<<5) | RKey;//合并左右5位 SubKey2=Transformation(WorkKey,P8,10); } static int Fk(int InputText,int SubKey){//Fk函数 int LText,RText,WorkText; WorkText=Transformation((InputText & 0xf),EP,4);//EP,4位到8位的转化函数 WorkText^=SubKey;//与子密钥做异或操作 LText=WorkText>>4;//取出高4位 RText=WorkText & 0xf;//取出低4位 //下面是两个S盒变换 LText=S0[((LText & 0x8)>>2) | (LText & 1)][(LText>>1) & 0x3]; RText=S1[((RText & 0x8)>>2) | (RText & 1)][(RText>>1) & 0x3]; //合并成4位 WorkText=LText<<2 | RText; WorkText=Transformation(WorkText,P4,4);//4位变换 LText=InputText>>4; RText=InputText & 0xf; WorkText=LText^WorkText;//左4位与中间值做异或 WorkText<<=4; WorkText|=RText;//合并成8位 return WorkText; } static int SW(int FromNumber){//高4位与低4位交换 return(((FromNumber & 0xf)<<4) | (FromNumber>>4)); } static int Cipher(int FromText){//加密函数 int ToText; ToText=Transformation(FromText,IP8,8); ToText=Fk(ToText,SubKey1); ToText=SW(ToText); ToText=Fk(ToText,SubKey2); ToText=Transformation(ToText,IP8I,8); return ToText; } static int InvCipher(int FromText){//解密函数 int ToText; ToText=Transformation(FromText,IP8,8); ToText=Fk(ToText,SubKey2); ToText=SW(ToText); ToText=Fk(ToText,SubKey1); ToText=Transformation(ToText,IP8I,8); return ToText; } public static void main(String[] args){//测试函数 int a='a'; SetKey(1017); System.out.println(a); int b=Cipher(a); System.out.println(b); int c=InvCipher(b); System.out.println(c); } }
三.运行截图
四.总结
SDES密钥长度只有10位,相对来说是非常短的,遍历一遍可能只需要零点几秒的时间,不能用于实际的加密工作,但是该算法适合于教学和加密算法入门学习之用。