1、基本密码部件,S盒置换,非线性变换τ,L变换,T变换
public class BasicComponents { private int[][] SBOX={{0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05}, {0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99}, {0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62}, {0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6}, {0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8}, {0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35}, {0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87}, {0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e}, {0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1}, {0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3}, {0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f}, {0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51}, {0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8}, {0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0}, {0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84}, {0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48} }; //S盒置换,输入8位,输出8位,输入一个两位的16进制数 int S_Box(int n){ if(n<0||n>255){ System.out.println("S盒输入错误"); return 0; } int j = n%16; //j为第二位的数 int i = (n-j)/16; //i为第一位的数 //System.out.println("i:" + i + ",j:" + j); int result = SBOX[i][j]; return result; } //非线性变换τ,4个S盒并行置换,输入32位,输出32位,输入4个两位的16进制数 int[] PIChange(int[] n1){ if(n1.length!=4){ System.out.println("τ变换输入错误"); return null; } for(int i=0;i<4;i++){ if(n1[i]<0||n1[i]>255){ System.out.println("τ变换输入错误"); return null; } } int[] res = new int[4]; for(int i=0;i<4;i++){ res[i] = S_Box(n1[i]); } return res; } //L变换,32位输入,32位输出,输入4个两位的16进制数 int[] LChange(int[] n1){ if(n1.length!=4){ System.out.println("L变换输入错误"); return null; } for(int i=0;i<4;i++){ if(n1[i]<0||n1[i]>255){ System.out.println("L变换输入错误"); return null; } } Tools tool = new Tools(); String res = ""; String B = tool.HexToStr(n1); res = tool.XOR(B, tool.loopleftmove(B, 2)); res = tool.XOR(res, tool.loopleftmove(B, 10)); res = tool.XOR(res, tool.loopleftmove(B, 18)); res = tool.XOR(res, tool.loopleftmove(B, 24)); int[] result = tool.BinToIntArray(res); return result; } //T变换 int[] TChange(int[] n1){ int[] result = new int[4]; result = PIChange(n1); result = LChange(result); return result; } //L'变换,32位输入,32位输出,输入4个两位的16进制数 int[] L_1Change(int[] n1){ if(n1.length!=4){ System.out.println("L变换输入错误"); return null; } for(int i=0;i<4;i++){ if(n1[i]<0||n1[i]>255){ System.out.println("L变换输入错误"); return null; } } Tools tool = new Tools(); String res = ""; String B = tool.HexToStr(n1); res = tool.XOR(B, tool.loopleftmove(B, 13)); res = tool.XOR(res, tool.loopleftmove(B, 23)); int[] result = tool.BinToIntArray(res); return result; } //T'变换 int[] T_1Change(int[] n1){ int[] result = new int[4]; result = PIChange(n1); result = L_1Change(result); return result; } public static void main(String[] args){ BasicComponents bc = new BasicComponents(); int[] n = {0x11,0x12,0x13,0x14}; int[] m = bc.PIChange(n); for(int i=0;i<4;i++){ System.out.println(m[i]); } } }
2、轮函数
public class WheelFunction { //轮函数方法,输入128位,输出32位,输入4个32位字的数据和一个32位的轮密钥,输出一个32位字 int[] F(int[] tn0, int[] tn1, int[] tn2, int[] tn3, int[] rk){ if(tn0.length!=4||tn1.length!=4||tn2.length!=4||tn3.length!=4||rk.length!=4){ System.out.println("轮函数输入错误"); return null; } Tools tool = new Tools(); BasicComponents bc = new BasicComponents(); String str = ""; str = tool.XOR(tool.HexToStr(tn1), tool.HexToStr(tn2)); str = tool.XOR(str, tool.HexToStr(tn3)); str = tool.XOR(str, tool.HexToStr(rk)); int[] res = new int[4]; res = tool.BinToIntArray(str); res = bc.TChange(res); str = tool.HexToStr(res); str = tool.XOR(tool.HexToStr(tn0), str); res = tool.BinToIntArray(str); return res; } }
3、密钥拓展算法
public class KeyExpansion { private String FK0 = "a3b1bac6"; private String FK1 = "56aa3350"; private String FK2 = "677d9197"; private String FK3 = "b27022dc"; private String[] CK = {"00070e15","1c232a31","383f464d","545b6269", "70777e85","8c939aa1","a8afb6bd","c4cbd2d9", "e0e7eef5","fc030a11","181f262d","343b4249", "50575e65","6c737a81","888f969d","a4abb2b9", "c0c7ced5","dce3eaf1","f8ff060d","141b2229", "30373e45","4c535a61","686f767d","848b9299", "a0a7aeb5","bcc3cad1","d8dfe6ed","f4fb0209", "10171e25","2c333a41","484f565d","646b7279" }; //输入加密密钥4个32位字,输出轮密钥 String[] wheelKey(String[] MK){ Tools tool = new Tools(); BasicComponents bc = new BasicComponents(); String[] k = new String[36]; //k中存的是32位的比特串 String[] rk = new String[32]; String tmk = tool.HexToStr(tool.HexToIntArray(MK[0])); String tfk = tool.HexToStr(tool.HexToIntArray(FK0)); k[0] = tool.XOR(tmk, tfk); tmk = tool.HexToStr(tool.HexToIntArray(MK[1])); tfk = tool.HexToStr(tool.HexToIntArray(FK1)); k[1] = tool.XOR(tmk, tfk); tmk = tool.HexToStr(tool.HexToIntArray(MK[2])); tfk = tool.HexToStr(tool.HexToIntArray(FK2)); k[2] = tool.XOR(tmk, tfk); tmk = tool.HexToStr(tool.HexToIntArray(MK[3])); tfk = tool.HexToStr(tool.HexToIntArray(FK3)); k[3] = tool.XOR(tmk, tfk); for(int i=0;i<32;i++){ String ts = ""; ts = tool.XOR(k[i+1], k[i+2]); ts = tool.XOR(ts, k[i+3]); ts = tool.XOR(ts, tool.HexToStr(tool.HexToIntArray(CK[i]))); ts = tool.HexToStr(bc.T_1Change(tool.BinToIntArray(ts))); ts = tool.XOR(k[i], ts); k[i+4] = ts; rk[i] = tool.IntArrayToStr(tool.BinToIntArray(ts)); } return rk; } }
4、加密算法
import java.util.ArrayList; //加密算法 public class Encrypt { private String plaintext; //明文 private String[] MK; //密钥 public Encrypt(){ } public Encrypt(String plaintext, String[] MK){ this.plaintext = plaintext; this.MK = MK; } //加密入口,接受一个String类型的明文,将其依次转换成4个int数组放入encryptProcess中加密,获得输出,输出最后结果 public ArrayList<int[]> encryptEntrance(){ KeyExpansion ke = new KeyExpansion(); String[] rk = ke.wheelKey(MK); //根据密钥拓展得出轮密钥 Tools tool = new Tools(); plaintext = tool.fillNumber(plaintext); ArrayList<int[]> res = new ArrayList<int[]>(); for(int n=0;n<plaintext.length()/16;n++){ ArrayList<int[]> t = new ArrayList<int[]>(); ArrayList<int[]> tres = new ArrayList<int[]>(); String s = plaintext.substring(n*16, (n+1)*16); t = tool.StrToList(s); tres = encryptProcess(t.get(0),t.get(1),t.get(2),t.get(3),rk); res.add(tres.get(0)); res.add(tres.get(1)); res.add(tres.get(2)); res.add(tres.get(3)); } return res; } //加密过程,输入128位明文,4个长度为4的int数组(每一个元素为一个两位的十六进制数),输入轮密钥,输出128位密文 ArrayList<int[]> encryptProcess(int[] n0, int[] n1, int[] n2,int[] n3, String[] rk){ if(n0.length!=4||n1.length!=4||n2.length!=4||n3.length!=4){ System.out.println("encrypt输入错误"); return null; } Tools tool = new Tools(); WheelFunction wf = new WheelFunction(); ArrayList<int[]> x = new ArrayList<int[]>(); x.add(n0); x.add(n1); x.add(n2); x.add(n3); for(int i=0;i<32;i++){ int[] trk = tool.HexToIntArray(rk[i]); x.add(wf.F(x.get(i), x.get(i+1), x.get(i+2), x.get(i+3), trk)); } ArrayList<int[]> res = new ArrayList<int[]>(); res.add(x.get(35)); res.add(x.get(34)); res.add(x.get(33)); res.add(x.get(32)); return res; } public String getPlaintext() { return plaintext; } public void setPlaintext(String plaintext) { this.plaintext = plaintext; } public String[] getMK() { return MK; } public void setMK(String[] mK) { MK = mK; } }
5、解密算法
import java.util.ArrayList; public class Decrypt { private ArrayList<int[]> ciphertext; //密文 private String[] MK; //密钥 public Decrypt(){ } public Decrypt(ArrayList<int[]> ciphertext, String[] MK){ this.ciphertext = ciphertext; this.MK = MK; } //解密入口 public String decryptEntrance(){ KeyExpansion ke = new KeyExpansion(); String[] rk = ke.wheelKey(MK); //根据密钥拓展得出轮密钥 Tools tool = new Tools(); String res = ""; for(int n=0;n<ciphertext.size()/4;n++){ ArrayList<int[]> tal = new ArrayList<int[]>(); tal = decryptProcess(ciphertext.get(n*4),ciphertext.get(n*4+1),ciphertext.get(n*4+2),ciphertext.get(n*4+3),rk); res += tool.ListToStr(tal); } res = tool.restore(res); return res; } //解密过程,输入128位密文,4个长度为4的int数组(每一个元素为一个两位的十六进制数),输入轮密钥,输出128位明文 ArrayList<int[]> decryptProcess(int[] n0, int[] n1, int[] n2,int[] n3, String[] rk){ if(n0.length!=4||n1.length!=4||n2.length!=4||n3.length!=4){ System.out.println("decrypt输入错误"); return null; } Tools tool = new Tools(); WheelFunction wf = new WheelFunction(); ArrayList<int[]> x = new ArrayList<int[]>(); x.add(n0); x.add(n1); x.add(n2); x.add(n3); for(int i=0;i<32;i++){ int[] trk = tool.HexToIntArray(rk[31-i]); x.add(wf.F(x.get(i), x.get(i+1), x.get(i+2), x.get(i+3), trk)); } ArrayList<int[]> res = new ArrayList<int[]>(); res.add(x.get(35)); res.add(x.get(34)); res.add(x.get(33)); res.add(x.get(32)); return res; } public void setCiphertext(ArrayList<int[]> ciphertext) { this.ciphertext = ciphertext; } public ArrayList<int[]> getCiphertext() { return ciphertext; } public String[] getMK() { return MK; } public void setMK(String[] mK) { MK = mK; } }
6、工具类
import java.util.ArrayList; public class Tools { //将0到255之间int类型的数转换为8位二进制的String类型表示 public String IntToBin(int i){ if(i<0||i>255){ System.out.println("IntToStr输入错误"); return null; } String str = ""; for(int n=7;n>=0;n--){ int t = 1<<n; //1<<n等于2的n次方 if(i>=t){ str = str + "1"; i = i-t; }else{ str = str + "0"; } } return str; } //把8位String类型的二进制表示转换为int类型的数 public int BinToInt(String str){ if(str.length()!=8){ System.out.println("BinToInt输入错误"); return 0; } int result = 0; for(int i=0;i<8;i++){ if(str.charAt(i)=='1'){ result += 1<<(7-i); } } return result; } //把一个包含4个两位十六进制数的数组转换成32位(二进制表示)的字符串 public String HexToStr(int[] n1){ String res = ""; for(int i=0;i<n1.length;i++){ res += IntToBin(n1[i]); } return res; } //将一个32位的比特串转换成一个int数组 public int[] BinToIntArray(String str){ if(str.length()!=32){ System.out.println("BinToIntArray输入错误"); return null; } int[] result = new int[4]; result[0] = BinToInt(str.substring(0, 8)); result[1] = BinToInt(str.substring(8, 16)); result[2] = BinToInt(str.substring(16, 24)); result[3] = BinToInt(str.substring(24, 32)); return result; } //循环左移n位方法 public String loopleftmove(String str,int n){ if(n>32){ return null; } String s1,s2,res; s1 = str.substring(0, n); s2 = str.substring(n,32); res = s2 + s1; return res; } //String类型的异或运算,相同为零,不同为一 public String XOR(String str1,String str2){ if(str1.length()!=str2.length()){ System.out.println("XOR方法输入错误,参数长度不同"); return null; } String res = ""; for(int i=0;i<str1.length();i++){ if(str1.charAt(i)==str2.charAt(i)){ res += "0"; }else{ res += "1"; } } return res; } //将String表示的4个两位十六进制数转换成一个int数组 public int[] HexToIntArray(String str){ if(str.length()!=8){ System.out.println("HexToIntArray输入错误"); return null; } int[] res = new int[4]; for(int i=0;i<4;i++){ int sum = 0; if(str.charAt(2*i)>=48&&str.charAt(2*i)<=57){ sum += (str.charAt(2*i)-48)*16; }else{ sum += (str.charAt(2*i)-87)*16; } if(str.charAt(2*i+1)>=48&&str.charAt(2*i+1)<=57){ sum += str.charAt(2*i+1)-48; }else{ sum += str.charAt(2*i+1)-87; } res[i] = sum; } return res; } //将一个长度为4的int数组装换成String类型的十六进制表示 public String IntArrayToStr(int[] n1){ if(n1.length!=4){ System.out.println("IntArrayToStr输入错误"); return null; } String res = ""; for(int i=0;i<4;i++){ res += IntToHex(n1[i]); } return res; } //将一个int数转换成一个两位的十六进制数 public String IntToHex(int i){ String res = ""; //第一位数是n,第二位是变换后的i int n=15; for(;n>=0;n--){ if(n*16<=i){ i = i-n*16; break; } } if(n>9){ res = res + (char)(n+87); }else{ res = res + n; } if(i>9){ res = res + (char)(i+87); }else{ res = res + i; } return res; } //若str不能整除16则用" "补齐位数 public String fillNumber(String str){ int m = str.length()%16; if(m!=0){ for(int n=0;n<(16-m%16);n++){ str += " "; } } return str; } //若str末尾有" ",则将末尾的" "全都去掉 public String restore(String str){ while(str.charAt(str.length()-1)==' '){ str = str.substring(0, str.length()-1); } return str; } //将一个16位的字符串转化成4个长度为4的int数组存入ArrayList中 public ArrayList<int[]> StrToList(String str){ if(str.length()!=16){ System.out.println("StrToList输入错误"); return null; } ArrayList<int[]> res = new ArrayList<int[]>(); for(int n=0;n<4;n++){ int[] t = new int[4]; t[0] = str.charAt(n*4); t[1] = str.charAt(n*4+1); t[2] = str.charAt(n*4+2); t[3] = str.charAt(n*4+3); res.add(t); } return res; } //将ArrayList中的数提出来转换为String public String ListToStr(ArrayList<int[]> al){ String res = ""; for(int n=0;n<4;n++){ int[] t = al.get(n); for(int i=0;i<4;i++){ res += (char)t[i]; } } return res; } public static void main(String[] args){ Tools tool = new Tools(); String s = "abcdABCDjigi1234"; ArrayList<int[]> a = tool.StrToList(s); System.out.println(tool.ListToStr(a)); } }