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));
}
}