import java.util.Scanner;
public class DESDemo {
public static String msg;
public static String keys;
static int pbox[][]={
new int[]{ 16 , 7 , 20, 21},
new int[]{29 , 12 , 28 , 17},
new int[]{ 1, 15, 23, 26},
new int[]{5 , 18 , 31 , 10},
new int[]{ 2 , 8, 24, 14},
new int[]{32, 27 , 3 , 9},
new int[]{ 19, 13 , 30, 6},
new int[]{22 , 11 , 4 , 25}
};
static int sbox[][][] = {
new int[][]{
new int[]{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
new int[]{0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
new int[]{4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
new int[]{15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}
},
new int[][]{
new int[]{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
new int[]{3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
new int[]{0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
new int[]{13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}
},
new int[][]{
new int[]{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
new int[]{13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
new int[]{13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
new int[]{1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}
},
new int[][]{
new int[]{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
new int[]{13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
new int[]{10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
new int[]{3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}
},
new int[][]{
new int[]{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
new int[]{14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
new int[]{4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
new int[]{11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}
},
new int[][]{
new int[]{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
new int[]{10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
new int[]{9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
new int[]{4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}
},
new int[][]{
new int[]{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
new int[]{13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
new int[]{1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
new int[]{6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}
},
new int[][]{
new int[]{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
new int[]{1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
new int[]{7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
new int[]{2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}
}
};
static int pc1[][] = {
new int[]{57, 49, 41, 33, 25, 17, 9},
new int[]{1, 58, 50, 42, 34, 26, 18},
new int[]{10, 2, 59, 51, 43, 35, 27},
new int[]{19, 11, 3, 60, 52, 44, 36},
new int[]{63, 55, 47, 39, 31, 23, 15},
new int[]{7, 62, 54, 46, 38, 30, 22},
new int[]{14, 6, 61, 53, 45, 37, 29},
new int[]{21, 13, 5, 28, 20, 12, 4},};
static int pc2[][] = {
new int[]{14, 17, 11, 24, 1, 5},
new int[]{3, 28, 15, 6, 21, 10},
new int[]{23, 19, 12, 4, 26, 8},
new int[]{16, 7, 27, 20, 13, 2},
new int[]{41, 52, 31, 37, 47, 55},
new int[]{30, 40, 51, 45, 33, 48},
new int[]{44, 49, 39, 56, 34, 53},
new int[]{46, 42, 50, 36, 29, 32}
};
static int ip1[][] = {
new int[]{58, 50, 42, 34, 26, 18, 10, 2},
new int[]{60, 52, 44, 36, 28, 20, 12, 4},
new int[]{62, 54, 46, 38, 30, 22, 14, 6},
new int[]{64, 56, 48, 40, 32, 24, 16, 8},
new int[]{57, 49, 41, 33, 25, 17, 9, 1},
new int[]{59, 51, 43, 35, 27, 19, 11, 3},
new int[]{61, 53, 45, 37, 29, 21, 13, 5},
new int[]{63, 55, 47, 39, 31, 23, 15, 7}
};
/*
static int keydiscard[][] = {
new int[]{1,2,3,4,5,6,7},
new int[]{9,10,11,12,13,14,15},
new int[]{17,18,19,20,21,22,23},
new int[]{25,26,27,28,29,30,31},
new int[]{33,34,35,36,37,38,39},
new int[]{41,42,43,44,45,46,47},
new int[]{49,50,51,52,53,54,55},
new int[]{57,58,59,60,61,62,63}
};
*/
static int final_p[][]={
new int[]{ 40 , 8 , 48 , 16 , 56 , 24, 64, 32},
new int[]{39 , 7 , 47 , 15 , 55 , 23 , 63 , 31},
new int[]{ 38 , 6 , 46 , 14 , 54 , 22, 62, 30},
new int[]{37 , 5 , 45 , 13 , 53 , 21 , 61 , 29},
new int[]{36 , 4 , 44 , 12 , 52 ,20 , 60 , 28},
new int[]{35 , 3 , 43 , 11 , 51 , 19 , 59 , 27},
new int[]{34 , 2 , 42 , 10 , 50 , 18 , 58 , 26},
new int[]{33 , 1 , 41 , 9 , 49 , 17, 57 , 25}
};
static int ebit[][] = {
new int[]{32, 1, 2, 3, 4, 5},
new int[]{4, 5, 6, 7, 8, 9},
new int[]{8, 9, 10, 11, 12, 13},
new int[]{12, 13, 14, 15, 16, 17},
new int[]{16, 17, 18, 19, 20, 21},
new int[]{20, 21, 22, 23, 24, 25},
new int[]{24, 25, 26, 27, 28, 29},
new int[]{28, 29, 30, 31, 32, 1},};
static int lshround[] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
public static int binToDec(String s)
{
int i = 0;
int mul = 1;
int p = 0;
for (int c = s.length() - 1; c >= 0; c--, p++) {
mul = (int) Math.pow(2, p);
if (s.charAt(c) == '1') {
i += mul;
}
}
return i;
}
public static String lShift(String s, int i) throws Exception {
if (s.length() < i) {
throw new Exception("unable to do left shift");
}
String st = s;
for (int c = 0; c < i; c++) {
st = st.substring(1, st.length()) + st.charAt(0);
}
return st;
}
static String fourbits[];
public static String XOR(String s1, String s2) {
String op = "";
for (int c = 0; c < s1.length(); c++) {
char c1 = s1.charAt(c);
char c2 = s2.charAt(c);
if (c1 == c2) {
op += "0";
} else {
op += "1";
}
}
return op;
}
public static boolean isHexFormat(String s)
{
String hexchars="0123456789ABCDEF";
for(int i=0;i<s.length();i++)
if(hexchars.indexOf(s.charAt(i))==-1)
return false;
return true;
}
public static void main(String[] args) throws Exception
{
// key discarding process
System.out.print("Enter message: ");
Scanner sc=new Scanner(System.in);
String original_hex_msg=sc.next().toUpperCase();
if(original_hex_msg.length()<16)
throw new Exception("DES is block cipher your message should be minimum 16 hex char.");
if(!isHexFormat(original_hex_msg))
throw new Exception("Message must be in hex format");
System.out.print("Enter key: ");
String origin_key=sc.next().toUpperCase();
if(origin_key.length()<16)
throw new Exception("Key must be minimum 16 Hex digits.");
if(!isHexFormat(origin_key))
throw new Exception("Key must be in hex format");
msg="";
for(int i=0;i<original_hex_msg.length();i++)
msg+=hexToBinary(original_hex_msg.charAt(i));
keys="";
for(int i=0;i<origin_key.length();i++)
keys+=hexToBinary(origin_key.charAt(i));
String key56bit=initPermutation(pc1,keys);
String leftkey=key56bit.substring(0,key56bit.length()/2);
String rightkey=key56bit.substring(key56bit.length()/2,key56bit.length());
String old_left_key=leftkey;
String old_right_key=rightkey;
String key[]=new String[16];
for(int i=0;i<lshround.length;i++)
{
old_left_key=new String(leftkey);
old_right_key=new String(rightkey);
leftkey=lShift(old_left_key,lshround[i]);
rightkey=lShift(rightkey,lshround[i]);
key[i]=initPermutation(pc2,leftkey+rightkey);
//System.out.println(key[i]+" "+lshround[i]+" "+i);
}
String sboxkey="";
String ip_=initPermutation(ip1,msg);
String leftmsg=ip_.substring(0,ip_.length()/2);
String rightmsg=ip_.substring(ip_.length()/2,ip_.length());
for(int i=0;i<16;i++)
{
sboxkey="";
String temp=rightmsg;
String expandedkey=initPermutation(ebit,rightmsg);
String xoredkey=XOR(key[i],expandedkey);
fourbits = new String[8];
for (int ic = 0; ic < 8; ic++)
{
fourbits[ic] = xoredkey.substring(ic * 6, ic * 6 + 6);
String rf = "" + fourbits[ic].charAt(0) + fourbits[ic].charAt(5) + "";
String cf = fourbits[ic].substring(1, 5);
//System.out.println(fourbits[ic] + " " + binToDec(rf) + " " + binToDec(cf));
sboxkey+=IntToBin(sbox[ic][binToDec(rf)][binToDec(cf)]);
}
String pboxkey=initPermutation(pbox,sboxkey);
rightmsg=XOR(leftmsg,pboxkey);
leftmsg=temp;
System.gc();
}
String fpx=initPermutation(final_p,(rightmsg+leftmsg));
//System.out.println("Message: "+original_hex_msg);
//System.out.println("Key : "+origin_key);
//System.out.println("final permutation value: "+fpx);
String cipher="";
for(int i=0;i<fpx.length();i+=4)
{
String sx=fpx.substring(i,i+4);
//System.out.println(sx);
cipher+=binaryToHex(sx);
}
System.out.println("Calculated Cipher: "+cipher);
}
public static char binaryToHex(String s)
{
switch(s)
{
case "0000": return '0';
case "0001": return '1';
case "0010": return '2';
case "0011": return '3';
case "0100": return '4';
case "0101": return '5';
case "0110": return '6';
case "0111": return '7';
case "1000": return '8';
case "1001": return '9';
case "1010": return 'A';
case "1011": return 'B';
case "1100": return 'C';
case "1101": return 'D';
case "1110": return 'E';
case "1111": return 'F';
default:return ' ';
}
}
public static String initPermutation(int pc[][], String s) {
String news = "";
for (int x[] : pc) {
for (int y : x) {
news += s.charAt(y - 1);
}
}
return news;
}
public static String hexToBinary(char n)
{
switch(n)
{
case '0': return "0000";
case '1': return "0001";
case '2': return "0010";
case '3': return "0011";
case '4': return "0100";
case '5': return "0101";
case '6': return "0110";
case '7': return "0111";
case '8': return "1000";
case '9': return "1001";
case 'A': return "1010";
case 'B': return "1011";
case 'C': return "1100";
case 'D': return "1101";
case 'E': return "1110";
case 'F': return "1111";
default:return "wrong"+n;
}
}
public static String IntToBin(int n)
{
switch(n)
{
case 0: return "0000";
case 1: return "0001";
case 2: return "0010";
case 3: return "0011";
case 4: return "0100";
case 5: return "0101";
case 6: return "0110";
case 7: return "0111";
case 8: return "1000";
case 9: return "1001";
case 10: return "1010";
case 11: return "1011";
case 12: return "1100";
case 13: return "1101";
case 14: return "1110";
case 15: return "1111";
default:return "wrong"+n;
}
}
}