/* package whatever; // don't place package name! */
import java.util.*;
class Main {
private static class DES {
// CONSTANTS
// Initial Permutation Table
int[] IP = { 58, 50, 42, 34, 26, 18,
10, 2, 60, 52, 44, 36, 28, 20,
12, 4, 62, 54, 46, 38,
30, 22, 14, 6, 64, 56,
48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17,
9, 1, 59, 51, 43, 35, 27,
19, 11, 3, 61, 53, 45,
37, 29, 21, 13, 5, 63, 55,
47, 39, 31, 23, 15, 7 };
// Inverse Initial Permutation Table
int[] IP1 = { 40, 8, 48, 16, 56, 24, 64,
32, 39, 7, 47, 15, 55,
23, 63, 31, 38, 6, 46,
14, 54, 22, 62, 30, 37,
5, 45, 13, 53, 21, 61,
29, 36, 4, 44, 12, 52,
20, 60, 28, 35, 3, 43,
11, 51, 19, 59, 27, 34,
2, 42, 10, 50, 18, 58,
26, 33, 1, 41, 9, 49,
17, 57, 25 };
// first key-hePermutation Table
int[] PC1 = { 57, 49, 41, 33, 25,
17, 9, 1, 58, 50, 42, 34, 26,
18, 10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36, 63,
55, 47, 39, 31, 23, 15, 7, 62,
54, 46, 38, 30, 22, 14, 6, 61,
53, 45, 37, 29, 21, 13, 5, 28,
20, 12, 4 };
// second key-Permutation Table
int[] PC2 = { 14, 17, 11, 24, 1, 5, 3,
28, 15, 6, 21, 10, 23, 19, 12,
4, 26, 8, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 30, 40,
51, 45, 33, 48, 44, 49, 39, 56,
34, 53, 46, 42, 50, 36, 29, 32 };
// Expansion D-box Table
int[] EP = { 32, 1, 2, 3, 4, 5, 4,
5, 6, 7, 8, 9, 8, 9, 10,
11, 12, 13, 12, 13, 14, 15,
16, 17, 16, 17, 18, 19, 20,
21, 20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29, 28,
29, 30, 31, 32, 1 };
// Straight Permutation Table
int[] P = { 16, 7, 20, 21, 29, 12, 28,
17, 1, 15, 23, 26, 5, 18,
31, 10, 2, 8, 24, 14, 32,
27, 3, 9, 19, 13, 30, 6,
22, 11, 4, 25 };
// S-box Table
int[][][] sbox = {
{ { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 },
{ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 },
{ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 },
{ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } },
{ { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 },
{ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 },
{ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 },
{ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } },
{ { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 },
{ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 },
{ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 },
{ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } },
{ { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 },
{ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 },
{ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 },
{ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } },
{ { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 },
{ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 },
{ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 },
{ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } },
{ { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 },
{ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 },
{ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 },
{ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } },
{ { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 },
{ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 },
{ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 },
{ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } },
{ { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 },
{ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 },
{ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 },
{ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } }
};
int[] shiftBits = { 1, 1, 2, 2, 2, 2, 2, 2,
1, 2, 2, 2, 2, 2, 2, 1 };
// hexadecimal to binary conversion
{
int n = input.length() * 4;
input
= Long.
toBinaryString( Long.
parseUnsignedLong(input,
16)); while (input.length() < n)
input = "0" + input;
return input;
}
// binary to hexadecimal conversion
{
int n = (int)input.length() / 4;
input
= Long.
toHexString( Long.
parseUnsignedLong(input,
2)); while (input.length() < n)
input = "0" + input;
return input;
}
// per-mutate input hexadecimal
// according to specified sequence
{
input = hextoBin(input);
for (int i = 0; i < sequence.length; i++)
output += input.charAt(sequence[i] - 1);
output = binToHex(output);
return output;
}
// xor 2 hexadecimal strings
{
// hexadecimal to decimal(base 10)
long t_a
= Long.
parseUnsignedLong(a,
16); // hexadecimal to decimal(base 10)
long t_b
= Long.
parseUnsignedLong(b,
16); // xor
t_a = t_a ^ t_b;
// decimal to hexadecimal
a
= Long.
toHexString(t_a
); // prepend 0's to maintain length
while (a.length() < b.length())
a = "0" + a;
return a;
}
// left Circular Shifting bits
{
int n = input.length() * 4;
int perm[] = new int[n];
for (int i = 0; i < n - 1; i++)
perm[i] = (i + 2);
perm[n - 1] = 1;
while (numBits-- > 0)
input = permutation(perm, input);
return input;
}
// preparing 16 keys for 16 rounds
{
// first key permutation
key = permutation(PC1, key);
for (int i = 0; i < 16; i++) {
key = leftCircularShift(
key.substring(0, 7), shiftBits[i])
+ leftCircularShift(key.substring(7, 14),
shiftBits[i]);
// second key permutation
keys[i] = permutation(PC2, key);
}
return keys;
}
// s-box lookup
{
input = hextoBin(input);
for (int i = 0; i < 48; i += 6) {
String temp
= input.
substring(i, i
+ 6); int num = i / 6;
temp.charAt(0) + "" + temp.charAt(5), 2);
temp.substring(1, 5), 2);
sbox[num][row][col]);
}
return output;
}
{
// fk
String left
= input.
substring(0,
8); String temp
= input.
substring(8,
16); // Expansion permutation
temp = permutation(EP, temp);
// xor temp and round key
temp = xor(temp, key);
// lookup in s-box table
temp = sBox(temp);
// Straight D-box
temp = permutation(P, temp);
// xor
left = xor(left, temp);
+ (num + 1) + " "
+ right.toUpperCase()
+ " " + left.toUpperCase() + " "
+ key.toUpperCase());
// swapper
return right + left;
}
{
int i;
// get round keys
// initial permutation
plainText = permutation(IP, plainText);
"After initial permutation: "
+ plainText.toUpperCase());
"After splitting: L0="
+ plainText.substring(0, 8).toUpperCase()
+ " R0="
+ plainText.substring(8, 16).toUpperCase() + "\n");
// 16 rounds
for (i = 0; i < 16; i++) {
plainText = round(plainText, keys[i], i);
}
// 32-bit swap
plainText = plainText.substring(8, 16)
+ plainText.substring(0, 8);
// final permutation
plainText = permutation(IP1, plainText);
return plainText;
}
{
int i;
// get round keys
// initial permutation
plainText = permutation(IP, plainText);
"After initial permutation: "
+ plainText.toUpperCase());
"After splitting: L0="
+ plainText.substring(0, 8).toUpperCase()
+ " R0=" + plainText.substring(8, 16).toUpperCase()
+ "\n");
// 16-rounds
for (i = 15; i > -1; i--) {
plainText = round(plainText, keys[i], 15 - i);
}
// 32-bit swap
plainText = plainText.substring(8, 16)
+ plainText.substring(0, 8);
plainText = permutation(IP1, plainText);
return plainText;
}
}
public static void main
(String args
[]) {
String text
= "123456ABCD132536"; String key
= "656173795F457841";
DES cipher = new DES();
System.
out.
println("Encryption:\n"); text = cipher.encrypt(text, key);
"\nCipher Text: " + text.toUpperCase() + "\n");
System.
out.
println("Decryption\n"); text = cipher.decrypt(text, key);
"\nPlain Text: "
+ text.toUpperCase());
}
}
// code contributed by Abhay Bhat
LyogcGFja2FnZSB3aGF0ZXZlcjsgLy8gZG9uJ3QgcGxhY2UgcGFja2FnZSBuYW1lISAqLwoKaW1wb3J0IGphdmEudXRpbC4qOwoKY2xhc3MgTWFpbiB7Cglwcml2YXRlIHN0YXRpYyBjbGFzcyBERVMgewoJCS8vIENPTlNUQU5UUwoJCS8vIEluaXRpYWwgUGVybXV0YXRpb24gVGFibGUKCQlpbnRbXSBJUCA9IHsgNTgsIDUwLCA0MiwgMzQsIDI2LCAxOCwKCQkJCQkxMCwgMiwgNjAsIDUyLCA0NCwgMzYsIDI4LCAyMCwKCQkJCQkxMiwgNCwgNjIsIDU0LCA0NiwgMzgsCgkJCQkJMzAsIDIyLCAxNCwgNiwgNjQsIDU2LAoJCQkJCTQ4LCA0MCwgMzIsIDI0LCAxNiwgOCwKCQkJCQk1NywgNDksIDQxLCAzMywgMjUsIDE3LAoJCQkJCTksIDEsIDU5LCA1MSwgNDMsIDM1LCAyNywKCQkJCQkxOSwgMTEsIDMsIDYxLCA1MywgNDUsCgkJCQkJMzcsIDI5LCAyMSwgMTMsIDUsIDYzLCA1NSwKCQkJCQk0NywgMzksIDMxLCAyMywgMTUsIDcgfTsKCgkJLy8gSW52ZXJzZSBJbml0aWFsIFBlcm11dGF0aW9uIFRhYmxlCgkJaW50W10gSVAxID0geyA0MCwgOCwgNDgsIDE2LCA1NiwgMjQsIDY0LAoJCQkJCTMyLCAzOSwgNywgNDcsIDE1LCA1NSwKCQkJCQkyMywgNjMsIDMxLCAzOCwgNiwgNDYsCgkJCQkJMTQsIDU0LCAyMiwgNjIsIDMwLCAzNywKCQkJCQk1LCA0NSwgMTMsIDUzLCAyMSwgNjEsCgkJCQkJMjksIDM2LCA0LCA0NCwgMTIsIDUyLAoJCQkJCTIwLCA2MCwgMjgsIDM1LCAzLCA0MywKCQkJCQkxMSwgNTEsIDE5LCA1OSwgMjcsIDM0LAoJCQkJCTIsIDQyLCAxMCwgNTAsIDE4LCA1OCwKCQkJCQkyNiwgMzMsIDEsIDQxLCA5LCA0OSwKCQkJCQkxNywgNTcsIDI1IH07CgoJCS8vIGZpcnN0IGtleS1oZVBlcm11dGF0aW9uIFRhYmxlCgkJaW50W10gUEMxID0geyA1NywgNDksIDQxLCAzMywgMjUsCgkJCQkJMTcsIDksIDEsIDU4LCA1MCwgNDIsIDM0LCAyNiwKCQkJCQkxOCwgMTAsIDIsIDU5LCA1MSwgNDMsIDM1LCAyNywKCQkJCQkxOSwgMTEsIDMsIDYwLCA1MiwgNDQsIDM2LCA2MywKCQkJCQk1NSwgNDcsIDM5LCAzMSwgMjMsIDE1LCA3LCA2MiwKCQkJCQk1NCwgNDYsIDM4LCAzMCwgMjIsIDE0LCA2LCA2MSwKCQkJCQk1MywgNDUsIDM3LCAyOSwgMjEsIDEzLCA1LCAyOCwKCQkJCQkyMCwgMTIsIDQgfTsKCgkJLy8gc2Vjb25kIGtleS1QZXJtdXRhdGlvbiBUYWJsZQoJCWludFtdIFBDMiA9IHsgMTQsIDE3LCAxMSwgMjQsIDEsIDUsIDMsCgkJCQkJMjgsIDE1LCA2LCAyMSwgMTAsIDIzLCAxOSwgMTIsCgkJCQkJNCwgMjYsIDgsIDE2LCA3LCAyNywgMjAsIDEzLCAyLAoJCQkJCTQxLCA1MiwgMzEsIDM3LCA0NywgNTUsIDMwLCA0MCwKCQkJCQk1MSwgNDUsIDMzLCA0OCwgNDQsIDQ5LCAzOSwgNTYsCgkJCQkJMzQsIDUzLCA0NiwgNDIsIDUwLCAzNiwgMjksIDMyIH07CgoJCS8vIEV4cGFuc2lvbiBELWJveCBUYWJsZQoJCWludFtdIEVQID0geyAzMiwgMSwgMiwgMywgNCwgNSwgNCwKCQkJCQk1LCA2LCA3LCA4LCA5LCA4LCA5LCAxMCwKCQkJCQkxMSwgMTIsIDEzLCAxMiwgMTMsIDE0LCAxNSwKCQkJCQkxNiwgMTcsIDE2LCAxNywgMTgsIDE5LCAyMCwKCQkJCQkyMSwgMjAsIDIxLCAyMiwgMjMsIDI0LCAyNSwKCQkJCQkyNCwgMjUsIDI2LCAyNywgMjgsIDI5LCAyOCwKCQkJCQkyOSwgMzAsIDMxLCAzMiwgMSB9OwoKCQkvLyBTdHJhaWdodCBQZXJtdXRhdGlvbiBUYWJsZQoJCWludFtdIFAgPSB7IDE2LCA3LCAyMCwgMjEsIDI5LCAxMiwgMjgsCgkJCQkJMTcsIDEsIDE1LCAyMywgMjYsIDUsIDE4LAoJCQkJCTMxLCAxMCwgMiwgOCwgMjQsIDE0LCAzMiwKCQkJCQkyNywgMywgOSwgMTksIDEzLCAzMCwgNiwKCQkJCQkyMiwgMTEsIDQsIDI1IH07CgoJCS8vIFMtYm94IFRhYmxlCgkJaW50W11bXVtdIHNib3ggPSB7CgkJCXsgeyAxNCwgNCwgMTMsIDEsIDIsIDE1LCAxMSwgOCwgMywgMTAsIDYsIDEyLCA1LCA5LCAwLCA3IH0sCgkJCXsgMCwgMTUsIDcsIDQsIDE0LCAyLCAxMywgMSwgMTAsIDYsIDEyLCAxMSwgOSwgNSwgMywgOCB9LAoJCQl7IDQsIDEsIDE0LCA4LCAxMywgNiwgMiwgMTEsIDE1LCAxMiwgOSwgNywgMywgMTAsIDUsIDAgfSwKCQkJeyAxNSwgMTIsIDgsIDIsIDQsIDksIDEsIDcsIDUsIDExLCAzLCAxNCwgMTAsIDAsIDYsIDEzIH0gfSwKCgkJCXsgeyAxNSwgMSwgOCwgMTQsIDYsIDExLCAzLCA0LCA5LCA3LCAyLCAxMywgMTIsIDAsIDUsIDEwIH0sCgkJCXsgMywgMTMsIDQsIDcsIDE1LCAyLCA4LCAxNCwgMTIsIDAsIDEsIDEwLCA2LCA5LCAxMSwgNSB9LAoJCQl7IDAsIDE0LCA3LCAxMSwgMTAsIDQsIDEzLCAxLCA1LCA4LCAxMiwgNiwgOSwgMywgMiwgMTUgfSwKCQkJeyAxMywgOCwgMTAsIDEsIDMsIDE1LCA0LCAyLCAxMSwgNiwgNywgMTIsIDAsIDUsIDE0LCA5IH0gfSwKCQkJeyB7IDEwLCAwLCA5LCAxNCwgNiwgMywgMTUsIDUsIDEsIDEzLCAxMiwgNywgMTEsIDQsIDIsIDggfSwKCQkJeyAxMywgNywgMCwgOSwgMywgNCwgNiwgMTAsIDIsIDgsIDUsIDE0LCAxMiwgMTEsIDE1LCAxIH0sCgkJCXsgMTMsIDYsIDQsIDksIDgsIDE1LCAzLCAwLCAxMSwgMSwgMiwgMTIsIDUsIDEwLCAxNCwgNyB9LAoJCQl7IDEsIDEwLCAxMywgMCwgNiwgOSwgOCwgNywgNCwgMTUsIDE0LCAzLCAxMSwgNSwgMiwgMTIgfSB9LAoJCQl7IHsgNywgMTMsIDE0LCAzLCAwLCA2LCA5LCAxMCwgMSwgMiwgOCwgNSwgMTEsIDEyLCA0LCAxNSB9LAoJCQl7IDEzLCA4LCAxMSwgNSwgNiwgMTUsIDAsIDMsIDQsIDcsIDIsIDEyLCAxLCAxMCwgMTQsIDkgfSwKCQkJeyAxMCwgNiwgOSwgMCwgMTIsIDExLCA3LCAxMywgMTUsIDEsIDMsIDE0LCA1LCAyLCA4LCA0IH0sCgkJCXsgMywgMTUsIDAsIDYsIDEwLCAxLCAxMywgOCwgOSwgNCwgNSwgMTEsIDEyLCA3LCAyLCAxNCB9IH0sCgkJCXsgeyAyLCAxMiwgNCwgMSwgNywgMTAsIDExLCA2LCA4LCA1LCAzLCAxNSwgMTMsIDAsIDE0LCA5IH0sCgkJCXsgMTQsIDExLCAyLCAxMiwgNCwgNywgMTMsIDEsIDUsIDAsIDE1LCAxMCwgMywgOSwgOCwgNiB9LAoJCQl7IDQsIDIsIDEsIDExLCAxMCwgMTMsIDcsIDgsIDE1LCA5LCAxMiwgNSwgNiwgMywgMCwgMTQgfSwKCQkJeyAxMSwgOCwgMTIsIDcsIDEsIDE0LCAyLCAxMywgNiwgMTUsIDAsIDksIDEwLCA0LCA1LCAzIH0gfSwKCQkJeyB7IDEyLCAxLCAxMCwgMTUsIDksIDIsIDYsIDgsIDAsIDEzLCAzLCA0LCAxNCwgNywgNSwgMTEgfSwKCQkJeyAxMCwgMTUsIDQsIDIsIDcsIDEyLCA5LCA1LCA2LCAxLCAxMywgMTQsIDAsIDExLCAzLCA4IH0sCgkJCXsgOSwgMTQsIDE1LCA1LCAyLCA4LCAxMiwgMywgNywgMCwgNCwgMTAsIDEsIDEzLCAxMSwgNiB9LAoJCQl7IDQsIDMsIDIsIDEyLCA5LCA1LCAxNSwgMTAsIDExLCAxNCwgMSwgNywgNiwgMCwgOCwgMTMgfSB9LAoJCQl7IHsgNCwgMTEsIDIsIDE0LCAxNSwgMCwgOCwgMTMsIDMsIDEyLCA5LCA3LCA1LCAxMCwgNiwgMSB9LAoJCQl7IDEzLCAwLCAxMSwgNywgNCwgOSwgMSwgMTAsIDE0LCAzLCA1LCAxMiwgMiwgMTUsIDgsIDYgfSwKCQkJeyAxLCA0LCAxMSwgMTMsIDEyLCAzLCA3LCAxNCwgMTAsIDE1LCA2LCA4LCAwLCA1LCA5LCAyIH0sCgkJCXsgNiwgMTEsIDEzLCA4LCAxLCA0LCAxMCwgNywgOSwgNSwgMCwgMTUsIDE0LCAyLCAzLCAxMiB9IH0sCgkJCXsgeyAxMywgMiwgOCwgNCwgNiwgMTUsIDExLCAxLCAxMCwgOSwgMywgMTQsIDUsIDAsIDEyLCA3IH0sCgkJCXsgMSwgMTUsIDEzLCA4LCAxMCwgMywgNywgNCwgMTIsIDUsIDYsIDExLCAwLCAxNCwgOSwgMiB9LAoJCQl7IDcsIDExLCA0LCAxLCA5LCAxMiwgMTQsIDIsIDAsIDYsIDEwLCAxMywgMTUsIDMsIDUsIDggfSwKCQkJeyAyLCAxLCAxNCwgNywgNCwgMTAsIDgsIDEzLCAxNSwgMTIsIDksIDAsIDMsIDUsIDYsIDExIH0gfQoJCX07CgkJaW50W10gc2hpZnRCaXRzID0geyAxLCAxLCAyLCAyLCAyLCAyLCAyLCAyLAoJCQkJCQkJMSwgMiwgMiwgMiwgMiwgMiwgMiwgMSB9OwoKCQkvLyBoZXhhZGVjaW1hbCB0byBiaW5hcnkgY29udmVyc2lvbgoJCVN0cmluZyBoZXh0b0JpbihTdHJpbmcgaW5wdXQpCgkJewoJCQlpbnQgbiA9IGlucHV0Lmxlbmd0aCgpICogNDsKCQkJaW5wdXQgPSBMb25nLnRvQmluYXJ5U3RyaW5nKAoJCQkJTG9uZy5wYXJzZVVuc2lnbmVkTG9uZyhpbnB1dCwgMTYpKTsKCQkJd2hpbGUgKGlucHV0Lmxlbmd0aCgpIDwgbikKCQkJCWlucHV0ID0gIjAiICsgaW5wdXQ7CgkJCXJldHVybiBpbnB1dDsKCQl9CgoJCS8vIGJpbmFyeSB0byBoZXhhZGVjaW1hbCBjb252ZXJzaW9uCgkJU3RyaW5nIGJpblRvSGV4KFN0cmluZyBpbnB1dCkKCQl7CgkJCWludCBuID0gKGludClpbnB1dC5sZW5ndGgoKSAvIDQ7CgkJCWlucHV0ID0gTG9uZy50b0hleFN0cmluZygKCQkJCUxvbmcucGFyc2VVbnNpZ25lZExvbmcoaW5wdXQsIDIpKTsKCQkJd2hpbGUgKGlucHV0Lmxlbmd0aCgpIDwgbikKCQkJCWlucHV0ID0gIjAiICsgaW5wdXQ7CgkJCXJldHVybiBpbnB1dDsKCQl9CgoJCS8vIHBlci1tdXRhdGUgaW5wdXQgaGV4YWRlY2ltYWwKCQkvLyBhY2NvcmRpbmcgdG8gc3BlY2lmaWVkIHNlcXVlbmNlCgkJU3RyaW5nIHBlcm11dGF0aW9uKGludFtdIHNlcXVlbmNlLCBTdHJpbmcgaW5wdXQpCgkJewoJCQlTdHJpbmcgb3V0cHV0ID0gIiI7CgkJCWlucHV0ID0gaGV4dG9CaW4oaW5wdXQpOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNlcXVlbmNlLmxlbmd0aDsgaSsrKQoJCQkJb3V0cHV0ICs9IGlucHV0LmNoYXJBdChzZXF1ZW5jZVtpXSAtIDEpOwoJCQlvdXRwdXQgPSBiaW5Ub0hleChvdXRwdXQpOwoJCQlyZXR1cm4gb3V0cHV0OwoJCX0KCgkJLy8geG9yIDIgaGV4YWRlY2ltYWwgc3RyaW5ncwoJCVN0cmluZyB4b3IoU3RyaW5nIGEsIFN0cmluZyBiKQoJCXsKCQkJLy8gaGV4YWRlY2ltYWwgdG8gZGVjaW1hbChiYXNlIDEwKQoJCQlsb25nIHRfYSA9IExvbmcucGFyc2VVbnNpZ25lZExvbmcoYSwgMTYpOwoJCQkvLyBoZXhhZGVjaW1hbCB0byBkZWNpbWFsKGJhc2UgMTApCgkJCWxvbmcgdF9iID0gTG9uZy5wYXJzZVVuc2lnbmVkTG9uZyhiLCAxNik7CgkJCS8vIHhvcgoJCQl0X2EgPSB0X2EgXiB0X2I7CgkJCS8vIGRlY2ltYWwgdG8gaGV4YWRlY2ltYWwKCQkJYSA9IExvbmcudG9IZXhTdHJpbmcodF9hKTsKCQkJLy8gcHJlcGVuZCAwJ3MgdG8gbWFpbnRhaW4gbGVuZ3RoCgkJCXdoaWxlIChhLmxlbmd0aCgpIDwgYi5sZW5ndGgoKSkKCQkJCWEgPSAiMCIgKyBhOwoJCQlyZXR1cm4gYTsKCQl9CgoJCS8vIGxlZnQgQ2lyY3VsYXIgU2hpZnRpbmcgYml0cwoJCVN0cmluZyBsZWZ0Q2lyY3VsYXJTaGlmdChTdHJpbmcgaW5wdXQsIGludCBudW1CaXRzKQoJCXsKCQkJaW50IG4gPSBpbnB1dC5sZW5ndGgoKSAqIDQ7CgkJCWludCBwZXJtW10gPSBuZXcgaW50W25dOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IG4gLSAxOyBpKyspCgkJCQlwZXJtW2ldID0gKGkgKyAyKTsKCQkJcGVybVtuIC0gMV0gPSAxOwoJCQl3aGlsZSAobnVtQml0cy0tID4gMCkKCQkJCWlucHV0ID0gcGVybXV0YXRpb24ocGVybSwgaW5wdXQpOwoJCQlyZXR1cm4gaW5wdXQ7CgkJfQoKCQkvLyBwcmVwYXJpbmcgMTYga2V5cyBmb3IgMTYgcm91bmRzCgkJU3RyaW5nW10gZ2V0S2V5cyhTdHJpbmcga2V5KQoJCXsKCQkJU3RyaW5nIGtleXNbXSA9IG5ldyBTdHJpbmdbMTZdOwoJCQkvLyBmaXJzdCBrZXkgcGVybXV0YXRpb24KCQkJa2V5ID0gcGVybXV0YXRpb24oUEMxLCBrZXkpOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IDE2OyBpKyspIHsKCQkJCWtleSA9IGxlZnRDaXJjdWxhclNoaWZ0KAoJCQkJCQlrZXkuc3Vic3RyaW5nKDAsIDcpLCBzaGlmdEJpdHNbaV0pCgkJCQkJKyBsZWZ0Q2lyY3VsYXJTaGlmdChrZXkuc3Vic3RyaW5nKDcsIDE0KSwKCQkJCQkJCQkJCXNoaWZ0Qml0c1tpXSk7CgkJCQkvLyBzZWNvbmQga2V5IHBlcm11dGF0aW9uCgkJCQlrZXlzW2ldID0gcGVybXV0YXRpb24oUEMyLCBrZXkpOwoJCQl9CgkJCXJldHVybiBrZXlzOwoJCX0KCgkJLy8gcy1ib3ggbG9va3VwCgkJU3RyaW5nIHNCb3goU3RyaW5nIGlucHV0KQoJCXsKCQkJU3RyaW5nIG91dHB1dCA9ICIiOwoJCQlpbnB1dCA9IGhleHRvQmluKGlucHV0KTsKCQkJZm9yIChpbnQgaSA9IDA7IGkgPCA0ODsgaSArPSA2KSB7CgkJCQlTdHJpbmcgdGVtcCA9IGlucHV0LnN1YnN0cmluZyhpLCBpICsgNik7CgkJCQlpbnQgbnVtID0gaSAvIDY7CgkJCQlpbnQgcm93ID0gSW50ZWdlci5wYXJzZUludCgKCQkJCQl0ZW1wLmNoYXJBdCgwKSArICIiICsgdGVtcC5jaGFyQXQoNSksIDIpOwoJCQkJaW50IGNvbCA9IEludGVnZXIucGFyc2VJbnQoCgkJCQkJdGVtcC5zdWJzdHJpbmcoMSwgNSksIDIpOwoJCQkJb3V0cHV0ICs9IEludGVnZXIudG9IZXhTdHJpbmcoCgkJCQkJc2JveFtudW1dW3Jvd11bY29sXSk7CgkJCX0KCQkJcmV0dXJuIG91dHB1dDsKCQl9CgoJCVN0cmluZyByb3VuZChTdHJpbmcgaW5wdXQsIFN0cmluZyBrZXksIGludCBudW0pCgkJewoJCQkvLyBmawoJCQlTdHJpbmcgbGVmdCA9IGlucHV0LnN1YnN0cmluZygwLCA4KTsKCQkJU3RyaW5nIHRlbXAgPSBpbnB1dC5zdWJzdHJpbmcoOCwgMTYpOwoJCQlTdHJpbmcgcmlnaHQgPSB0ZW1wOwoJCQkvLyBFeHBhbnNpb24gcGVybXV0YXRpb24KCQkJdGVtcCA9IHBlcm11dGF0aW9uKEVQLCB0ZW1wKTsKCQkJLy8geG9yIHRlbXAgYW5kIHJvdW5kIGtleQoJCQl0ZW1wID0geG9yKHRlbXAsIGtleSk7CgkJCS8vIGxvb2t1cCBpbiBzLWJveCB0YWJsZQoJCQl0ZW1wID0gc0JveCh0ZW1wKTsKCQkJLy8gU3RyYWlnaHQgRC1ib3gKCQkJdGVtcCA9IHBlcm11dGF0aW9uKFAsIHRlbXApOwoJCQkvLyB4b3IKCQkJbGVmdCA9IHhvcihsZWZ0LCB0ZW1wKTsKCQkJU3lzdGVtLm91dC5wcmludGxuKCJSb3VuZCAiCgkJCQkJCQkrIChudW0gKyAxKSArICIgIgoJCQkJCQkJKyByaWdodC50b1VwcGVyQ2FzZSgpCgkJCQkJCQkrICIgIiArIGxlZnQudG9VcHBlckNhc2UoKSArICIgIgoJCQkJCQkJKyBrZXkudG9VcHBlckNhc2UoKSk7CgoJCQkvLyBzd2FwcGVyCgkJCXJldHVybiByaWdodCArIGxlZnQ7CgkJfQoKCQlTdHJpbmcgZW5jcnlwdChTdHJpbmcgcGxhaW5UZXh0LCBTdHJpbmcga2V5KQoJCXsKCQkJaW50IGk7CgkJCS8vIGdldCByb3VuZCBrZXlzCgkJCVN0cmluZyBrZXlzW10gPSBnZXRLZXlzKGtleSk7CgoJCQkvLyBpbml0aWFsIHBlcm11dGF0aW9uCgkJCXBsYWluVGV4dCA9IHBlcm11dGF0aW9uKElQLCBwbGFpblRleHQpOwoJCQlTeXN0ZW0ub3V0LnByaW50bG4oCgkJCQkiQWZ0ZXIgaW5pdGlhbCBwZXJtdXRhdGlvbjogIgoJCQkJKyBwbGFpblRleHQudG9VcHBlckNhc2UoKSk7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigKCQkJCSJBZnRlciBzcGxpdHRpbmc6IEwwPSIKCQkJCSsgcGxhaW5UZXh0LnN1YnN0cmluZygwLCA4KS50b1VwcGVyQ2FzZSgpCgkJCQkrICIgUjA9IgoJCQkJKyBwbGFpblRleHQuc3Vic3RyaW5nKDgsIDE2KS50b1VwcGVyQ2FzZSgpICsgIlxuIik7CgoJCQkvLyAxNiByb3VuZHMKCQkJZm9yIChpID0gMDsgaSA8IDE2OyBpKyspIHsKCQkJCXBsYWluVGV4dCA9IHJvdW5kKHBsYWluVGV4dCwga2V5c1tpXSwgaSk7CgkJCX0KCgkJCS8vIDMyLWJpdCBzd2FwCgkJCXBsYWluVGV4dCA9IHBsYWluVGV4dC5zdWJzdHJpbmcoOCwgMTYpCgkJCQkJCSsgcGxhaW5UZXh0LnN1YnN0cmluZygwLCA4KTsKCgkJCS8vIGZpbmFsIHBlcm11dGF0aW9uCgkJCXBsYWluVGV4dCA9IHBlcm11dGF0aW9uKElQMSwgcGxhaW5UZXh0KTsKCQkJcmV0dXJuIHBsYWluVGV4dDsKCQl9CgoJCVN0cmluZyBkZWNyeXB0KFN0cmluZyBwbGFpblRleHQsIFN0cmluZyBrZXkpCgkJewoJCQlpbnQgaTsKCQkJLy8gZ2V0IHJvdW5kIGtleXMKCQkJU3RyaW5nIGtleXNbXSA9IGdldEtleXMoa2V5KTsKCgkJCS8vIGluaXRpYWwgcGVybXV0YXRpb24KCQkJcGxhaW5UZXh0ID0gcGVybXV0YXRpb24oSVAsIHBsYWluVGV4dCk7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigKCQkJCSJBZnRlciBpbml0aWFsIHBlcm11dGF0aW9uOiAiCgkJCQkrIHBsYWluVGV4dC50b1VwcGVyQ2FzZSgpKTsKCQkJU3lzdGVtLm91dC5wcmludGxuKAoJCQkJIkFmdGVyIHNwbGl0dGluZzogTDA9IgoJCQkJKyBwbGFpblRleHQuc3Vic3RyaW5nKDAsIDgpLnRvVXBwZXJDYXNlKCkKCQkJCSsgIiBSMD0iICsgcGxhaW5UZXh0LnN1YnN0cmluZyg4LCAxNikudG9VcHBlckNhc2UoKQoJCQkJKyAiXG4iKTsKCgkJCS8vIDE2LXJvdW5kcwoJCQlmb3IgKGkgPSAxNTsgaSA+IC0xOyBpLS0pIHsKCQkJCXBsYWluVGV4dCA9IHJvdW5kKHBsYWluVGV4dCwga2V5c1tpXSwgMTUgLSBpKTsKCQkJfQoKCQkJLy8gMzItYml0IHN3YXAKCQkJcGxhaW5UZXh0ID0gcGxhaW5UZXh0LnN1YnN0cmluZyg4LCAxNikKCQkJCQkJKyBwbGFpblRleHQuc3Vic3RyaW5nKDAsIDgpOwoJCQlwbGFpblRleHQgPSBwZXJtdXRhdGlvbihJUDEsIHBsYWluVGV4dCk7CgkJCXJldHVybiBwbGFpblRleHQ7CgkJfQoJfQoJcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nIGFyZ3NbXSkKCXsKCQlTdHJpbmcgdGV4dCA9ICIxMjM0NTZBQkNEMTMyNTM2IjsKCQlTdHJpbmcga2V5ID0gIjY1NjE3Mzc5NUY0NTc4NDEiOwoKCQlERVMgY2lwaGVyID0gbmV3IERFUygpOwoJCVN5c3RlbS5vdXQucHJpbnRsbigiRW5jcnlwdGlvbjpcbiIpOwoJCXRleHQgPSBjaXBoZXIuZW5jcnlwdCh0ZXh0LCBrZXkpOwoJCVN5c3RlbS5vdXQucHJpbnRsbigKCQkJIlxuQ2lwaGVyIFRleHQ6ICIgKyB0ZXh0LnRvVXBwZXJDYXNlKCkgKyAiXG4iKTsKCQlTeXN0ZW0ub3V0LnByaW50bG4oIkRlY3J5cHRpb25cbiIpOwoJCXRleHQgPSBjaXBoZXIuZGVjcnlwdCh0ZXh0LCBrZXkpOwoJCVN5c3RlbS5vdXQucHJpbnRsbigKCQkJIlxuUGxhaW4gVGV4dDogIgoJCQkrIHRleHQudG9VcHBlckNhc2UoKSk7Cgl9Cn0KLy8gY29kZSBjb250cmlidXRlZCBieSBBYmhheSBCaGF0Cg==