Advertisement
Guest User

Untitled

a guest
Jan 20th, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.58 KB | None | 0 0
  1. import java.util.*;
  2. import java.util.concurrent.ThreadLocalRandom;
  3.  
  4. class DES {
  5. // Initial Permutation table
  6.  
  7. private static final byte[] IP = {
  8. 58, 50, 42, 34, 26, 18, 10, 2,
  9. 60, 52, 44, 36, 28, 20, 12, 4,
  10. 62, 54, 46, 38, 30, 22, 14, 6,
  11. 64, 56, 48, 40, 32, 24, 16, 8,
  12. 57, 49, 41, 33, 25, 17, 9, 1,
  13. 59, 51, 43, 35, 27, 19, 11, 3,
  14. 61, 53, 45, 37, 29, 21, 13, 5,
  15. 63, 55, 47, 39, 31, 23, 15, 7
  16. };
  17.  
  18. // Permuted Choice 1 table
  19. private static final byte[] PC1 = {
  20. 57, 49, 41, 33, 25, 17, 9,
  21. 1, 58, 50, 42, 34, 26, 18,
  22. 10, 2, 59, 51, 43, 35, 27,
  23. 19, 11, 3, 60, 52, 44, 36,
  24. 63, 55, 47, 39, 31, 23, 15,
  25. 7, 62, 54, 46, 38, 30, 22,
  26. 14, 6, 61, 53, 45, 37, 29,
  27. 21, 13, 5, 28, 20, 12, 4
  28. };
  29.  
  30. // Permuted Choice 2 table
  31. private static final byte[] PC2 = {
  32. 14, 17, 11, 24, 1, 5,
  33. 3, 28, 15, 6, 21, 10,
  34. 23, 19, 12, 4, 26, 8,
  35. 16, 7, 27, 20, 13, 2,
  36. 41, 52, 31, 37, 47, 55,
  37. 30, 40, 51, 45, 33, 48,
  38. 44, 49, 39, 56, 34, 53,
  39. 46, 42, 50, 36, 29, 32
  40. };
  41.  
  42. // Array to store the number of rotations that are to be done on each round
  43. private static final byte[] rotations = {
  44. 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
  45. };
  46.  
  47. // Expansion (aka P-box) table
  48. private static final byte[] E = {
  49. 32, 1, 2, 3, 4, 5,
  50. 4, 5, 6, 7, 8, 9,
  51. 8, 9, 10, 11, 12, 13,
  52. 12, 13, 14, 15, 16, 17,
  53. 16, 17, 18, 19, 20, 21,
  54. 20, 21, 22, 23, 24, 25,
  55. 24, 25, 26, 27, 28, 29,
  56. 28, 29, 30, 31, 32, 1
  57. };
  58.  
  59. // S-boxes (i.e. Substitution boxes)
  60. private static final byte[][] S = {{
  61. 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
  62. 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
  63. 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
  64. 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
  65. }, {
  66. 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
  67. 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
  68. 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
  69. 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
  70. }, {
  71. 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
  72. 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
  73. 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
  74. 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
  75. }, {
  76. 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
  77. 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
  78. 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
  79. 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
  80. }, {
  81. 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
  82. 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
  83. 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
  84. 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
  85. }, {
  86. 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
  87. 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
  88. 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
  89. 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
  90. }, {
  91. 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
  92. 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
  93. 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
  94. 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
  95. }, {
  96. 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
  97. 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
  98. 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
  99. 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
  100. }};
  101.  
  102. // Permutation table
  103. private static final byte[] P = {
  104. 16, 7, 20, 21,
  105. 29, 12, 28, 17,
  106. 1, 15, 23, 26,
  107. 5, 18, 31, 10,
  108. 2, 8, 24, 14,
  109. 32, 27, 3, 9,
  110. 19, 13, 30, 6,
  111. 22, 11, 4, 25
  112. };
  113.  
  114. // Final permutation (aka Inverse permutation) table
  115. private static final byte[] FP = {
  116. 40, 8, 48, 16, 56, 24, 64, 32,
  117. 39, 7, 47, 15, 55, 23, 63, 31,
  118. 38, 6, 46, 14, 54, 22, 62, 30,
  119. 37, 5, 45, 13, 53, 21, 61, 29,
  120. 36, 4, 44, 12, 52, 20, 60, 28,
  121. 35, 3, 43, 11, 51, 19, 59, 27,
  122. 34, 2, 42, 10, 50, 18, 58, 26,
  123. 33, 1, 41, 9, 49, 17, 57, 25
  124. };
  125.  
  126. // 28 bits each, used as storage in the KS (Key Structure) rounds to
  127. // generate round keys (aka subkeys)
  128. private static int[] C = new int[28];
  129. private static int[] D = new int[28];
  130.  
  131. // Decryption requires the 16 subkeys to be used in the exact same process
  132. // as encryption, with the only difference being that the keys are used
  133. // in reverse order, i.e. last key is used first and so on. Hence, during
  134. // encryption when the keys are first generated, they are stored in this
  135. // array. In case we wish to separate the encryption and decryption
  136. // programs, then we need to generate the subkeys first in order, store
  137. // them and then use them in reverse order.
  138. private static int[][] subkey = new int[16][48];
  139.  
  140. public static String stringToHex(String base) {
  141. StringBuffer buffer = new StringBuffer();
  142. int intValue;
  143. for (int x = 0; x < base.length(); x++) {
  144. int cursor = 0;
  145. intValue = base.charAt(x);
  146. String binaryChar = new String(Integer.toBinaryString(base.charAt(x)));
  147. for (int i = 0; i < binaryChar.length(); i++) {
  148. if (binaryChar.charAt(i) == '1') {
  149. cursor += 1;
  150. }
  151. }
  152. if ((cursor % 2) > 0) {
  153. intValue += 128;
  154. }
  155. buffer.append(Integer.toHexString(intValue) + "");
  156. }
  157.  
  158. return buffer.toString();
  159. }
  160.  
  161. public static void main(String args[]) {
  162. // System.out.println("Enter the input as a 16 character hexadecimal value:");
  163. System.out.println("Enter the input text:");
  164. String input1 = new Scanner(System.in).nextLine();
  165. System.out.println(input1);
  166. String input = DES.stringToHex(input1);
  167. System.out.println(input);
  168. System.out.println("----------");
  169. System.out.println(input.length());
  170. int inputBits[] = new int[4 * input.length()];
  171. // inputBits will store the 64 bits of the input as a an int array of
  172. // size 64. This program uses int arrays to store bits, for the sake
  173. // of simplicity. For efficient programming, use long data type. But
  174. // it increases program complexity which is unnecessary for this
  175. // context.
  176. for (int i = 0; i < input.length(); i++) {
  177. // For every character in the 16 bit input, we get its binary value
  178. // by first parsing it into an int and then converting to a binary
  179. // string
  180. String s = Integer.toBinaryString(Integer.parseInt(input.charAt(i) + "", input.length()));
  181.  
  182. // Java does not add padding zeros, i.e. 5 is returned as 111 but
  183. // we require 0111. Hence, this while loop adds padding 0's to the
  184. // binary value.
  185. while (s.length() < 4) {
  186. s = "0" + s;
  187. }
  188. // Add the 4 bits we have extracted into the array of bits.
  189. for (int j = 0; j < 4; j++) {
  190. inputBits[(4 * i) + j] = Integer.parseInt(s.charAt(j) + "");
  191. }
  192. }
  193.  
  194. // Similar process is followed for the 16 bit key
  195. // System.out.println("Enter the key as a 16 character hexadecimal value:");
  196. System.out.println("The key hexadecimal value:");
  197. int randomNum = 0;
  198. String zz;
  199. int hexKey[] = new int [input.length()];
  200. String hexKeyy[] = new String [input.length()];
  201. //System.out.println("random: " + randomNum);
  202. for (int i = 0; i < input.length() - 1; i++) {
  203. randomNum = ThreadLocalRandom.current().nextInt(0, 15 + 1);
  204. // System.out.print(randomNum + ", ");
  205. hexKey[i] = randomNum;
  206. // Integer.toHexString(hexKey[i]);
  207. randomNum = 0;
  208.  
  209. }
  210. System.out.println(Arrays.toString(hexKey));
  211. for (int i = 0; i < input.length() - 1; i++) {
  212. Integer.toHexString(hexKey[i]);
  213. zz = Integer.toHexString(hexKey[i]);
  214. hexKeyy[i] = DES.stringToHex(zz);
  215.  
  216. System.out.print(hexKeyy[i] +" ");
  217. }
  218. System.out.println(Arrays.toString(hexKey));
  219. String key = new Scanner(System.in).nextLine();
  220. int keyBits[] = new int[64];
  221. for (int i = 0; i < 16; i++) {
  222. String s = Integer.toBinaryString(Integer.parseInt(key.charAt(i) + "", 16));
  223. while (s.length() < 4) {
  224. s = "0" + s;
  225. }
  226. for (int j = 0; j < 4; j++) {
  227. keyBits[(4 * i) + j] = Integer.parseInt(s.charAt(j) + "");
  228. }
  229. }
  230.  
  231. // permute(int[] inputBits, int[] keyBits, boolean isDecrypt)
  232. // method is used here. This allows encryption and decryption to be
  233. // done in the same method, reducing code.
  234. System.out.println("\n+++ ENCRYPTION +++");
  235. int outputBits[] = permute(inputBits, keyBits, false);
  236. System.out.println("\n+++ DECRYPTION +++");
  237. permute(outputBits, keyBits, true);
  238. }
  239.  
  240. private static int[] permute(int[] inputBits, int[] keyBits, boolean isDecrypt) {
  241. // Initial permutation step takes input bits and permutes into the
  242. // newBits array
  243. int newBits[] = new int[inputBits.length];
  244. for (int i = 0; i < inputBits.length; i++) {
  245. newBits[i] = inputBits[IP[i] - 1];
  246. }
  247.  
  248. // 16 rounds will start here
  249. // L and R arrays are created to store the Left and Right halves of the
  250. // subkey respectively
  251. int L[] = new int[32];
  252. int R[] = new int[32];
  253. int i;
  254.  
  255. // Permuted Choice 1 is done here
  256. for (i = 0; i < 28; i++) {
  257. C[i] = keyBits[PC1[i] - 1];
  258. }
  259. for (; i < 56; i++) {
  260. D[i - 28] = keyBits[PC1[i] - 1];
  261. }
  262.  
  263. // After PC1 the first L and R are ready to be used and hence looping
  264. // can start once L and R are initialized
  265. System.arraycopy(newBits, 0, L, 0, 32);
  266. System.arraycopy(newBits, 32, R, 0, 32);
  267. System.out.print("\nL0 = ");
  268. displayBits(L);
  269. System.out.print("R0 = ");
  270. displayBits(R);
  271. for (int n = 0; n < 16; n++) {
  272. System.out.println("\n-------------");
  273. System.out.println("Round " + (n + 1) + ":");
  274. // newR is the new R half generated by the Fiestel function. If it
  275. // is encrpytion then the KS method is called to generate the
  276. // subkey otherwise the stored subkeys are used in reverse order
  277. // for decryption.
  278. int newR[] = new int[0];
  279. if (isDecrypt) {
  280. newR = fiestel(R, subkey[15 - n]);
  281. System.out.print("Round key = ");
  282. displayBits(subkey[15 - n]);
  283. } else {
  284. newR = fiestel(R, KS(n, keyBits));
  285. System.out.print("Round key = ");
  286. displayBits(subkey[n]);
  287. }
  288. // xor-ing the L and new R gives the new L value. new L is stored
  289. // in R and new R is stored in L, thus exchanging R and L for the
  290. // next round.
  291. int newL[] = xor(L, newR);
  292. L = R;
  293. R = newL;
  294. System.out.print("L = ");
  295. displayBits(L);
  296. System.out.print("R = ");
  297. displayBits(R);
  298. }
  299.  
  300. // R and L has the two halves of the output before applying the final
  301. // permutation. This is called the "Preoutput".
  302. int output[] = new int[64];
  303. System.arraycopy(R, 0, output, 0, 32);
  304. System.arraycopy(L, 0, output, 32, 32);
  305. int finalOutput[] = new int[64];
  306. // Applying FP table to the preoutput, we get the final output:
  307. // Encryption => final output is ciphertext
  308. // Decryption => final output is plaintext
  309. for (i = 0; i < 64; i++) {
  310. finalOutput[i] = output[FP[i] - 1];
  311. }
  312.  
  313. // Since the final output is stored as an int array of bits, we convert
  314. // it into a hex string:
  315. String hex = new String();
  316. for (i = 0; i < 16; i++) {
  317. String bin = new String();
  318. for (int j = 0; j < 4; j++) {
  319. bin += finalOutput[(4 * i) + j];
  320. }
  321. int decimal = Integer.parseInt(bin, 2);
  322. hex += Integer.toHexString(decimal);
  323. }
  324. if (isDecrypt) {
  325. System.out.print("Decrypted text: ");
  326.  
  327. } else {
  328. System.out.print("Encrypted text: ");
  329. }
  330. System.out.println(hex.toUpperCase());
  331. return finalOutput;
  332. }
  333.  
  334. private static int[] KS(int round, int[] key) {
  335. // The KS (Key Structure) function generates the round keys.
  336. // C1 and D1 are the new values of C and D which will be generated in
  337. // this round.
  338. int C1[] = new int[28];
  339. int D1[] = new int[28];
  340.  
  341. // The rotation array is used to set how many rotations are to be done
  342. int rotationTimes = (int) rotations[round];
  343. // leftShift() method is used for rotation (the rotation is basically)
  344. // a left shift operation, hence the name.
  345. C1 = leftShift(C, rotationTimes);
  346. D1 = leftShift(D, rotationTimes);
  347. // CnDn stores the combined C1 and D1 halves
  348. int CnDn[] = new int[56];
  349. System.arraycopy(C1, 0, CnDn, 0, 28);
  350. System.arraycopy(D1, 0, CnDn, 28, 28);
  351. // Kn stores the subkey, which is generated by applying the PC2 table
  352. // to CnDn
  353. int Kn[] = new int[48];
  354. for (int i = 0; i < Kn.length; i++) {
  355. Kn[i] = CnDn[PC2[i] - 1];
  356. }
  357.  
  358. // Now we store C1 and D1 in C and D respectively, thus becoming the
  359. // old C and D for the next round. Subkey is stored and returned.
  360. subkey[round] = Kn;
  361. C = C1;
  362. D = D1;
  363. return Kn;
  364. }
  365.  
  366. private static int[] fiestel(int[] R, int[] roundKey) {
  367. // Method to implement Fiestel function.
  368. // First the 32 bits of the R array are expanded using E table.
  369. int expandedR[] = new int[48];
  370. for (int i = 0; i < 48; i++) {
  371. expandedR[i] = R[E[i] - 1];
  372. }
  373. // We xor the expanded R and the generated round key
  374. int temp[] = xor(expandedR, roundKey);
  375. // The S boxes are then applied to this xor result and this is the
  376. // output of the Fiestel function.
  377. int output[] = sBlock(temp);
  378. return output;
  379. }
  380.  
  381. private static int[] xor(int[] a, int[] b) {
  382. // Simple xor function on two int arrays
  383. int answer[] = new int[a.length];
  384. for (int i = 0; i < a.length; i++) {
  385. answer[i] = a[i] ^ b[i];
  386. }
  387. return answer;
  388. }
  389.  
  390. private static int[] sBlock(int[] bits) {
  391. // S-boxes are applied in this method.
  392. int output[] = new int[32];
  393. // We know that input will be of 32 bits, hence we will loop 32/4 = 8
  394. // times (divided by 4 as we will take 4 bits of input at each
  395. // iteration).
  396. for (int i = 0; i < 8; i++) {
  397. // S-box requires a row and a column, which is found from the
  398. // input bits. The first and 6th bit of the current iteration
  399. // (i.e. bits 0 and 5) gives the row bits.
  400. int row[] = new int[2];
  401. row[0] = bits[6 * i];
  402. row[1] = bits[(6 * i) + 5];
  403. String sRow = row[0] + "" + row[1];
  404. // Similarly column bits are found, which are the 4 bits between
  405. // the two row bits (i.e. bits 1,2,3,4)
  406. int column[] = new int[4];
  407. column[0] = bits[(6 * i) + 1];
  408. column[1] = bits[(6 * i) + 2];
  409. column[2] = bits[(6 * i) + 3];
  410. column[3] = bits[(6 * i) + 4];
  411. String sColumn = column[0] + "" + column[1] + "" + column[2] + "" + column[3];
  412. // Converting binary into decimal value, to be given into the
  413. // array as input
  414. int iRow = Integer.parseInt(sRow, 2);
  415. int iColumn = Integer.parseInt(sColumn, 2);
  416. int x = S[i][(iRow * 16) + iColumn];
  417. // We get decimal value of the S-box here, but we need to convert
  418. // it into binary:
  419. String s = Integer.toBinaryString(x);
  420. // Padding is required since Java returns a decimal '5' as '111' in
  421. // binary, when we require '0111'.
  422. while (s.length() < 4) {
  423. s = "0" + s;
  424. }
  425. // The binary bits are appended to the output
  426. for (int j = 0; j < 4; j++) {
  427. output[(i * 4) + j] = Integer.parseInt(s.charAt(j) + "");
  428. }
  429. }
  430. // P table is applied to the output and this is the final output of one
  431. // S-box round:
  432. int finalOutput[] = new int[32];
  433. for (int i = 0; i < 32; i++) {
  434. finalOutput[i] = output[P[i] - 1];
  435. }
  436. return finalOutput;
  437. }
  438.  
  439. private static int[] leftShift(int[] bits, int n) {
  440. // Left shifting takes place here, i.e. each bit is rotated to the left
  441. // and the leftmost bit is stored at the rightmost bit. This is a left
  442. // shift operation.
  443. int answer[] = new int[bits.length];
  444. System.arraycopy(bits, 0, answer, 0, bits.length);
  445. for (int i = 0; i < n; i++) {
  446. int temp = answer[0];
  447. for (int j = 0; j < bits.length - 1; j++) {
  448. answer[j] = answer[j + 1];
  449. }
  450. answer[bits.length - 1] = temp;
  451. }
  452. return answer;
  453. }
  454.  
  455. private static void displayBits(int[] bits) {
  456. // Method to display int array bits as a hexadecimal string.
  457. for (int i = 0; i < bits.length; i += 4) {
  458. String output = new String();
  459. for (int j = 0; j < 4; j++) {
  460. output += bits[i + j];
  461. }
  462. System.out.print(Integer.toHexString(Integer.parseInt(output, 2)));
  463. }
  464. System.out.println();
  465. }
  466. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement