#include <bits/stdc++.h>
using namespace std;
string permute(string key, int arr[], int len) {
string permutation_key = "";
for (int i = 0; i < len; i++) {
permutation_key = permutation_key + key[arr[i] - 1]; // arr[i] tidak zero indexed (1..n)
}
return permutation_key;
}
string hex_to_bin(string s) {
char str[16 + 5] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
string hex[16 + 5] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
string ret = "";
for (int i = 0; i < s.length(); i++) {
for (int j = 0; j < 16; j++) {
if (s[i] == str[j]) {
ret = ret + hex[j];
break;
}
}
}
return ret;
}
string bin_to_hex(string s) {
char str[16 + 5] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
string hex[16 + 5] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
string ret = "";
for (int i = 0; i < s.length(); i += 4) {
string four_bits = "";
for (int j = i; j < i + 4; j++) {
four_bits = four_bits + s[j];
}
for (int j = 0; j < 16; j++) {
if (four_bits == hex[j]) {
ret = ret + str[j];
break;
}
}
}
return ret;
}
int bin_to_dec(string s) {
int decimal = 0;
int power = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if (s[i] == '1') {
decimal += pow(2, power);
}
power++;
}
return decimal;
}
string dec_to_bin(int n) {
string ret = "";
while (n != 0) {
if (n % 2 == 0) {
ret = ret + "0";
} else {
ret = ret + "1";
}
n /= 2;
}
while (ret.length() < 4) {
ret = ret + "0";
}
reverse(ret.begin(), ret.end());
return ret;
}
string xor_f(string a, string b) {
string ret = "";
for (int i = 0; i < a.length(); i++) {
if (a[i] == b[i]) {
ret = ret + "0";
} else {
ret = ret + "1";
}
}
return ret;
}
string generate_key() {
srand(time({}));
int range_ascii[] = {48, 57, 65, 70};
string key = "";
for (int i = 0; i < 16; i++) {
char c = rand() % (range_ascii[3] + 1 - range_ascii[0]) + range_ascii[0];
if (c > range_ascii[1] && c < range_ascii[2]) {
i--;
continue;
}
key = key + c;
}
return key;
}
string parity_bit_drop_key(string key) {
int parity_table[] = {
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
};
return (permute(key, parity_table, 56));
}
string compression_56_to_48(string key) {
int compression_table[] = {
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
};
return (permute(key, compression_table, 48));
}
void split_string(string str, string &left, string &right) {
for (int i = 0; i < str.length() / 2; i++) {
left = left + str[i];
right = right + str[str.length() / 2 + i];
}
}
string shift_left(string key, int n_shifts) {
int shift_table[] = {
1, 1, 2, 2,
2, 2, 2, 2,
1, 2, 2, 2,
2, 2, 2, 1
};
string shifted_key = "";
for (int i = 0; i < shift_table[n_shifts]; i++) {
for (int j = 1; j < key.length(); j++) {
shifted_key = shifted_key + key[j];
}
shifted_key = shifted_key + key[0];
key = shifted_key;
shifted_key = "";
}
return key;
}
struct round_keys {
string random_hex;
string round_keys_bin[16 + 5];
string round_keys_hex[16 + 5];
};
round_keys generate_round_keys(string option, string key = "") {
round_keys ret;
if (option == "encryption_scheme") {
ret.random_hex = "AABB09182736CCDD";
} else {
ret.random_hex = key;
}
string key_bin = hex_to_bin(ret.random_hex);
string key_bin_56 = parity_bit_drop_key(key_bin);
string key_left;
string key_right;
split_string(key_bin_56, key_left, key_right);
for (int i = 0; i < 16; i++) {
key_left = shift_left(key_left, i);
key_right = shift_left(key_right, i);
string combined_key = key_left + key_right;
string round_key = compression_56_to_48(combined_key);
ret.round_keys_bin[i] = round_key;
ret.round_keys_hex[i] = bin_to_hex(round_key);
}
return ret;
}
string initial_permutation(string text) {
int IP_table[] = {
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
};
return (permute(text, IP_table, 64));
}
string expansion(string text) {
int expansion_table[] = {
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
};
return (permute(text, expansion_table, 48));
}
string sbox_operation(string text) {
int sbox[8 + 5][4 + 5][16 + 5] = {
{
{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}
}
};
string ret = "";
for (int i = 0; i < 8; i++) {
string outer = "";
string inner = "";
outer = outer + text[i * 6] + text[i * 6 + 5];
inner = inner + text[i * 6 + 1] + text[i * 6 + 2] + text[i * 6 + 3] + text[i * 6 + 4];
int val = sbox[i][bin_to_dec(outer)][bin_to_dec(inner)];
ret = ret + dec_to_bin(val);
}
return ret;
}
string per(string text) {
int per[] = {
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
};
return permute(text, per, 32);
}
string final_permutation(string text) {
int final_perm[] = {
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
};
return permute(text, final_perm, 64);
}
string DES_encrypt(string plain_text, round_keys key) {
plain_text = hex_to_bin(plain_text);
plain_text = initial_permutation(plain_text);
string chiper_left;
string chiper_right;
// THE FUNCTION
split_string(plain_text, chiper_left, chiper_right);
for (int i = 0; i < 16; i++) {
string chiper_right_expanded = expansion(chiper_right);
string first_xor = xor_f(chiper_right_expanded, key.round_keys_bin[i]);
string sbox_str = sbox_operation(first_xor);
sbox_str = per(sbox_str);
string result = xor_f(chiper_left, sbox_str);
chiper_left = result;
if (i != 15) {
swap(chiper_left, chiper_right);
}
}
string chiper_text = chiper_left + chiper_right;
chiper_text = final_permutation(chiper_text);
cout << "Initial permutation : " << bin_to_hex(plain_text) << "\n";
cout << "Final chipper text : " << bin_to_hex(chiper_text) << "\n";
return bin_to_hex(chiper_text);
}
string DES_decrypt(string chiper_text, string key_hex) {
round_keys key = generate_round_keys("decryption_scheme", key_hex);
round_keys reversed_key;
for (int i = 15; i >= 0; i--) {
reversed_key.round_keys_bin[15 - i] = key.round_keys_bin[i];
reversed_key.round_keys_hex[15 - i] = key.round_keys_hex[i];
}
return DES_encrypt(chiper_text, reversed_key);
}
vector<string> input_encrypt() {
// This function is used for converting literal string into hexadecimal
string input_text;
cout << "Input plain text:" << "\n";
cout << ">> ";
cin.ignore();
getline(cin, input_text);
vector<string> plain_text(1);
int k = 0;
for (int i = 0; i < input_text.length(); i++) {
string character = "";
for(int j = 7; j >= 0; j--) {
bool is_set = input_text[i] & (1 << j);
if (is_set == 1) {
character = character + "1";
} else {
character = character + "0";
}
}
string character_left, character_right;
split_string(character, character_left, character_right);
if (plain_text[k].length() == 16) {
k++;
plain_text.push_back("" );
}
plain_text[k] = plain_text[k] + bin_to_hex(character_left);
plain_text[k] = plain_text[k] + bin_to_hex(character_right);
}
if (plain_text[k].length() != 16) {
for (int i = plain_text[k].length(); i < 16; i++) {
plain_text[k] = plain_text[k] + '0';
}
}
return plain_text;
}
string output_decrypt(vector<string> plain_text_hex) {
string ret = "";
for (int i = 0; i < plain_text_hex.size(); i++) {
for (int j = 0; j < 16; j += 2) {
string two_hex = plain_text_hex[i].substr(j, 2);
int value = stoi(two_hex, 0, 16);
if (value != 0) {
ret += (char)value;
}
}
}
return ret;
}
int main() {
while (1) {
int menu;
cout << "||======================" << "||" << '\n';
cout << "|| Wellcome to DES" << "\t" << "||" << '\n';
cout << "|| Choose Menu:" << "\t\t" << "||" << '\n';
cout << "|| 1: Encrypt Text" << "\t" << "||" << '\n';
cout << "|| 2: Decrypt Text" << "\t" << "||" << '\n';
cout << "|| 0: Exit" << "\t\t" << "||" << '\n';
cout << "|| >> ";
cin >> menu;
cout << "||======================" << "||" << '\n' << '\n';
if (menu == 1) {
cout << "========================================================================================================================" << '\n';
vector<string> plain_text = input_encrypt();
const int message_size = plain_text.size();
round_keys key = generate_round_keys("encryption_scheme");
vector<string> chiper_text;
cout << "\n" << "Encrypting plain text..." << "\n";
for (int i = 0; i < message_size; i++) {
chiper_text.push_back(DES_encrypt(plain_text[i], key));
cout << "Plain text encrypted [" << i + 1 << "/" << message_size << "]" << '\n' << '\n';
}
cout << "Key = " << key.random_hex << '\n';
cout << "Chiper text = {" << '\n';
for (int i = 0; i < message_size; i++) {
cout << chiper_text[i];
}
cout << '\n' << "}" << '\n';
cout << "========================================================================================================================" << '\n' << '\n';
} else if (menu == 2) {
cout << "========================================================================================================================" << '\n';
string key, chiper_text;
vector<string> plain_text_hex;
cout << "Input key:" << '\n' << ">> ";
cin >> key;
cout << "Input chiper text:" << '\n' << ">> ";
cin >> chiper_text;
const int message_size = chiper_text.length() / 16;
cout << "\n" << "Decrypting chiper text..." << "\n";
for (int i = 0; i < chiper_text.length(); i += 16) {
string chiper_text_partition = chiper_text.substr(i, 16);
plain_text_hex.push_back(DES_decrypt(chiper_text_partition, key));
cout << "Chiper text decrypted [" << i / 16 + 1 << "/" << message_size << "]" << '\n' << '\n';
}
string plain_text = output_decrypt(plain_text_hex);
cout << plain_text << '\n';
cout << "========================================================================================================================" << '\n' << '\n';
} else if (menu == 0) {
break;
} else {
cout << "Invalid command" << '\n' << '\n';
}
}
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgpzdHJpbmcgcGVybXV0ZShzdHJpbmcga2V5LCBpbnQgYXJyW10sIGludCBsZW4pIHsKICBzdHJpbmcgcGVybXV0YXRpb25fa2V5ID0gIiI7CiAgZm9yIChpbnQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgcGVybXV0YXRpb25fa2V5ID0gcGVybXV0YXRpb25fa2V5ICsga2V5W2FycltpXSAtIDFdOyAvLyBhcnJbaV0gdGlkYWsgemVybyBpbmRleGVkICgxLi5uKQogIH0KICByZXR1cm4gcGVybXV0YXRpb25fa2V5Owp9CgpzdHJpbmcgaGV4X3RvX2JpbihzdHJpbmcgcykgewogIGNoYXIgc3RyWzE2ICsgNV0gPSB7JzAnLCAnMScsICcyJywgJzMnLCAnNCcsICc1JywgJzYnLCAnNycsICc4JywgJzknLCAnQScsICdCJywgJ0MnLCAnRCcsICdFJywgJ0YnfTsKICBzdHJpbmcgaGV4WzE2ICsgNV0gPSB7IjAwMDAiLCAiMDAwMSIsICIwMDEwIiwgIjAwMTEiLCAiMDEwMCIsICIwMTAxIiwgIjAxMTAiLCAiMDExMSIsICIxMDAwIiwgIjEwMDEiLCAiMTAxMCIsICIxMDExIiwgIjExMDAiLCAiMTEwMSIsICIxMTEwIiwgIjExMTEifTsKICBzdHJpbmcgcmV0ID0gIiI7CiAgZm9yIChpbnQgaSA9IDA7IGkgPCBzLmxlbmd0aCgpOyBpKyspIHsKICAgIGZvciAoaW50IGogPSAwOyBqIDwgMTY7IGorKykgewogICAgICBpZiAoc1tpXSA9PSBzdHJbal0pIHsKICAgICAgICByZXQgPSByZXQgKyBoZXhbal07CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIHJldDsKfQoKc3RyaW5nIGJpbl90b19oZXgoc3RyaW5nIHMpIHsKICBjaGFyIHN0clsxNiArIDVdID0geycwJywgJzEnLCAnMicsICczJywgJzQnLCAnNScsICc2JywgJzcnLCAnOCcsICc5JywgJ0EnLCAnQicsICdDJywgJ0QnLCAnRScsICdGJ307CiAgc3RyaW5nIGhleFsxNiArIDVdID0geyIwMDAwIiwgIjAwMDEiLCAiMDAxMCIsICIwMDExIiwgIjAxMDAiLCAiMDEwMSIsICIwMTEwIiwgIjAxMTEiLCAiMTAwMCIsICIxMDAxIiwgIjEwMTAiLCAiMTAxMSIsICIxMTAwIiwgIjExMDEiLCAiMTExMCIsICIxMTExIn07CiAgc3RyaW5nIHJldCA9ICIiOwogIGZvciAoaW50IGkgPSAwOyBpIDwgcy5sZW5ndGgoKTsgaSArPSA0KSB7CiAgICBzdHJpbmcgZm91cl9iaXRzID0gIiI7CiAgICBmb3IgKGludCBqID0gaTsgaiA8IGkgKyA0OyBqKyspIHsKICAgICAgZm91cl9iaXRzID0gZm91cl9iaXRzICsgc1tqXTsKICAgIH0KICAgIGZvciAoaW50IGogPSAwOyBqIDwgMTY7IGorKykgewogICAgICBpZiAoZm91cl9iaXRzID09IGhleFtqXSkgewogICAgICAgIHJldCA9IHJldCArIHN0cltqXTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogIH0KICByZXR1cm4gcmV0Owp9CgppbnQgYmluX3RvX2RlYyhzdHJpbmcgcykgewogIGludCBkZWNpbWFsID0gMDsKICBpbnQgcG93ZXIgPSAwOwogIGZvciAoaW50IGkgPSBzLmxlbmd0aCgpIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgIGlmIChzW2ldID09ICcxJykgewogICAgICBkZWNpbWFsICs9IHBvdygyLCBwb3dlcik7CiAgICB9CiAgICBwb3dlcisrOwogIH0KICByZXR1cm4gZGVjaW1hbDsKfQoKc3RyaW5nIGRlY190b19iaW4oaW50IG4pIHsKICBzdHJpbmcgcmV0ID0gIiI7CiAgd2hpbGUgKG4gIT0gMCkgewogICAgaWYgKG4gJSAyID09IDApIHsKICAgICAgcmV0ID0gcmV0ICsgIjAiOwogICAgfSBlbHNlIHsKICAgICAgcmV0ID0gcmV0ICsgIjEiOwogICAgfQogICAgbiAvPSAyOwogIH0KICB3aGlsZSAocmV0Lmxlbmd0aCgpIDwgNCkgewogICAgcmV0ID0gcmV0ICsgIjAiOwogIH0KICByZXZlcnNlKHJldC5iZWdpbigpLCByZXQuZW5kKCkpOwogIHJldHVybiByZXQ7Cn0KCnN0cmluZyB4b3JfZihzdHJpbmcgYSwgc3RyaW5nIGIpIHsKICBzdHJpbmcgcmV0ID0gIiI7CiAgZm9yIChpbnQgaSA9IDA7IGkgPCBhLmxlbmd0aCgpOyBpKyspIHsKICAgIGlmIChhW2ldID09IGJbaV0pIHsKICAgICAgcmV0ID0gcmV0ICsgIjAiOwogICAgfSBlbHNlIHsKICAgICAgcmV0ID0gcmV0ICsgIjEiOwogICAgfQogIH0KICByZXR1cm4gcmV0Owp9CgpzdHJpbmcgZ2VuZXJhdGVfa2V5KCkgewogIHNyYW5kKHRpbWUoe30pKTsKICBpbnQgcmFuZ2VfYXNjaWlbXSA9IHs0OCwgNTcsIDY1LCA3MH07CiAgc3RyaW5nIGtleSA9ICIiOwogIGZvciAoaW50IGkgPSAwOyBpIDwgMTY7IGkrKykgewogICAgY2hhciBjID0gcmFuZCgpICUgKHJhbmdlX2FzY2lpWzNdICsgMSAtIHJhbmdlX2FzY2lpWzBdKSArIHJhbmdlX2FzY2lpWzBdOwogICAgaWYgKGMgPiByYW5nZV9hc2NpaVsxXSAmJiBjIDwgcmFuZ2VfYXNjaWlbMl0pIHsKICAgICAgaS0tOwogICAgICBjb250aW51ZTsKICAgIH0KICAgIGtleSA9IGtleSArIGM7CiAgfQogIHJldHVybiBrZXk7Cn0KCnN0cmluZyBwYXJpdHlfYml0X2Ryb3Bfa2V5KHN0cmluZyBrZXkpIHsKICBpbnQgcGFyaXR5X3RhYmxlW10gPSB7CiAgICA1NywgNDksIDQxLCAzMywgMjUsIDE3LCA5LAogICAgMSwgNTgsIDUwLCA0MiwgMzQsIDI2LCAxOCwKICAgIDEwLCAyLCA1OSwgNTEsIDQzLCAzNSwgMjcsCiAgICAxOSwgMTEsIDMsIDYwLCA1MiwgNDQsIDM2LAogICAgNjMsIDU1LCA0NywgMzksIDMxLCAyMywgMTUsCiAgICA3LCA2MiwgNTQsIDQ2LCAzOCwgMzAsIDIyLAogICAgMTQsIDYsIDYxLCA1MywgNDUsIDM3LCAyOSwKICAgIDIxLCAxMywgNSwgMjgsIDIwLCAxMiwgNAogIH07CiAgcmV0dXJuIChwZXJtdXRlKGtleSwgcGFyaXR5X3RhYmxlLCA1NikpOwp9CgpzdHJpbmcgY29tcHJlc3Npb25fNTZfdG9fNDgoc3RyaW5nIGtleSkgewogIGludCBjb21wcmVzc2lvbl90YWJsZVtdID0gewogICAgICAxNCwgMTcsIDExLCAyNCwgMSwgNSwKCQkJMywgMjgsIDE1LCA2LCAyMSwgMTAsCgkJCTIzLCAxOSwgMTIsIDQsIDI2LCA4LAoJCQkxNiwgNywgMjcsIDIwLCAxMywgMiwKCQkJNDEsIDUyLCAzMSwgMzcsIDQ3LCA1NSwKCQkJMzAsIDQwLCA1MSwgNDUsIDMzLCA0OCwKCQkJNDQsIDQ5LCAzOSwgNTYsIDM0LCA1MywKCQkJNDYsIDQyLCA1MCwgMzYsIDI5LCAzMgogIH07CiAgcmV0dXJuIChwZXJtdXRlKGtleSwgY29tcHJlc3Npb25fdGFibGUsIDQ4KSk7Cn0KCnZvaWQgc3BsaXRfc3RyaW5nKHN0cmluZyBzdHIsIHN0cmluZyAmbGVmdCwgc3RyaW5nICZyaWdodCkgewogIGZvciAoaW50IGkgPSAwOyBpIDwgc3RyLmxlbmd0aCgpIC8gMjsgaSsrKSB7CiAgICBsZWZ0ID0gbGVmdCArIHN0cltpXTsKICAgIHJpZ2h0ID0gcmlnaHQgKyBzdHJbc3RyLmxlbmd0aCgpIC8gMiArIGldOwogIH0KfQoKc3RyaW5nIHNoaWZ0X2xlZnQoc3RyaW5nIGtleSwgaW50IG5fc2hpZnRzKSB7CiAgaW50IHNoaWZ0X3RhYmxlW10gPSB7CiAgICAxLCAxLCAyLCAyLAogICAgMiwgMiwgMiwgMiwKICAgIDEsIDIsIDIsIDIsCiAgICAyLCAyLCAyLCAxCiAgfTsKCiAgc3RyaW5nIHNoaWZ0ZWRfa2V5ID0gIiI7CiAgZm9yIChpbnQgaSA9IDA7IGkgPCBzaGlmdF90YWJsZVtuX3NoaWZ0c107IGkrKykgewogICAgZm9yIChpbnQgaiA9IDE7IGogPCBrZXkubGVuZ3RoKCk7IGorKykgewogICAgICBzaGlmdGVkX2tleSA9IHNoaWZ0ZWRfa2V5ICsga2V5W2pdOwogICAgfQogICAgc2hpZnRlZF9rZXkgPSBzaGlmdGVkX2tleSArIGtleVswXTsKICAgIGtleSA9IHNoaWZ0ZWRfa2V5OwogICAgc2hpZnRlZF9rZXkgPSAiIjsKICB9CiAgcmV0dXJuIGtleTsKfQoKc3RydWN0IHJvdW5kX2tleXMgewogIHN0cmluZyByYW5kb21faGV4OwogIHN0cmluZyByb3VuZF9rZXlzX2JpblsxNiArIDVdOwogIHN0cmluZyByb3VuZF9rZXlzX2hleFsxNiArIDVdOwp9OwoKcm91bmRfa2V5cyBnZW5lcmF0ZV9yb3VuZF9rZXlzKHN0cmluZyBvcHRpb24sIHN0cmluZyBrZXkgPSAiIikgewogIHJvdW5kX2tleXMgcmV0OwogIGlmIChvcHRpb24gPT0gImVuY3J5cHRpb25fc2NoZW1lIikgewogICAgcmV0LnJhbmRvbV9oZXggPSAiQUFCQjA5MTgyNzM2Q0NERCI7CiAgfSBlbHNlIHsKICAgIHJldC5yYW5kb21faGV4ID0ga2V5OwogIH0KICBzdHJpbmcga2V5X2JpbiA9IGhleF90b19iaW4ocmV0LnJhbmRvbV9oZXgpOyAKICBzdHJpbmcga2V5X2Jpbl81NiA9IHBhcml0eV9iaXRfZHJvcF9rZXkoa2V5X2Jpbik7CiAgCiAgc3RyaW5nIGtleV9sZWZ0OwogIHN0cmluZyBrZXlfcmlnaHQ7CiAgc3BsaXRfc3RyaW5nKGtleV9iaW5fNTYsIGtleV9sZWZ0LCBrZXlfcmlnaHQpOwoKICBmb3IgKGludCBpID0gMDsgaSA8IDE2OyBpKyspIHsKICAgIGtleV9sZWZ0ID0gc2hpZnRfbGVmdChrZXlfbGVmdCwgaSk7CiAgICBrZXlfcmlnaHQgPSBzaGlmdF9sZWZ0KGtleV9yaWdodCwgaSk7CiAgICBzdHJpbmcgY29tYmluZWRfa2V5ID0ga2V5X2xlZnQgKyBrZXlfcmlnaHQ7CiAgICBzdHJpbmcgcm91bmRfa2V5ID0gY29tcHJlc3Npb25fNTZfdG9fNDgoY29tYmluZWRfa2V5KTsKICAgIHJldC5yb3VuZF9rZXlzX2JpbltpXSA9IHJvdW5kX2tleTsKICAgIHJldC5yb3VuZF9rZXlzX2hleFtpXSA9IGJpbl90b19oZXgocm91bmRfa2V5KTsKICB9CiAgcmV0dXJuIHJldDsKfQoKc3RyaW5nIGluaXRpYWxfcGVybXV0YXRpb24oc3RyaW5nIHRleHQpIHsKICBpbnQgSVBfdGFibGVbXSA9IHsKICAgIDU4LCA1MCwgNDIsIDM0LCAyNiwgMTgsIDEwLCAyLAogICAgNjAsIDUyLCA0NCwgMzYsIDI4LCAyMCwgMTIsIDQsCiAgICA2MiwgNTQsIDQ2LCAzOCwgMzAsIDIyLCAxNCwgNiwKICAgIDY0LCA1NiwgNDgsIDQwLCAzMiwgMjQsIDE2LCA4LAogICAgNTcsIDQ5LCA0MSwgMzMsIDI1LCAxNywgOSwgMSwKICAgIDU5LCA1MSwgNDMsIDM1LCAyNywgMTksIDExLCAzLAogICAgNjEsIDUzLCA0NSwgMzcsIDI5LCAyMSwgMTMsIDUsCiAgICA2MywgNTUsIDQ3LCAzOSwgMzEsIDIzLCAxNSwgNwogIH07CiAgcmV0dXJuIChwZXJtdXRlKHRleHQsIElQX3RhYmxlLCA2NCkpOwp9CgpzdHJpbmcgZXhwYW5zaW9uKHN0cmluZyB0ZXh0KSB7CiAgaW50IGV4cGFuc2lvbl90YWJsZVtdID0gewogICAgMzIsIDEsIDIsIDMsIDQsIDUsIDQsIDUsCiAgICA2LCA3LCA4LCA5LCA4LCA5LCAxMCwgMTEsCiAgICAxMiwgMTMsIDEyLCAxMywgMTQsIDE1LCAxNiwgMTcsCiAgICAxNiwgMTcsIDE4LCAxOSwgMjAsIDIxLCAyMCwgMjEsCiAgICAyMiwgMjMsIDI0LCAyNSwgMjQsIDI1LCAyNiwgMjcsCiAgICAyOCwgMjksIDI4LCAyOSwgMzAsIDMxLCAzMiwgMQogIH07CiAgcmV0dXJuIChwZXJtdXRlKHRleHQsIGV4cGFuc2lvbl90YWJsZSwgNDgpKTsKfQoKc3RyaW5nIHNib3hfb3BlcmF0aW9uKHN0cmluZyB0ZXh0KSB7CiAgaW50IHNib3hbOCArIDVdWzQgKyA1XVsxNiArIDVdID0gewogICAgewogICAgICB7MTQsIDQsIDEzLCAxLCAyLCAxNSwgMTEsIDgsIDMsIDEwLCA2LCAxMiwgNSwgOSwgMCwgN30sCiAgICAgIHswLCAxNSwgNywgNCwgMTQsIDIsIDEzLCAxLCAxMCwgNiwgMTIsIDExLCA5LCA1LCAzLCA4fSwKICAgICAgezQsIDEsIDE0LCA4LCAxMywgNiwgMiwgMTEsIDE1LCAxMiwgOSwgNywgMywgMTAsIDUsIDB9LAogICAgICB7MTUsIDEyLCA4LCAyLCA0LCA5LCAxLCA3LCA1LCAxMSwgMywgMTQsIDEwLCAwLCA2LCAxM30KICAgIH0sCgogICAgewogICAgICB7MTUsIDEsIDgsIDE0LCA2LCAxMSwgMywgNCwgOSwgNywgMiwgMTMsIDEyLCAwLCA1LCAxMH0sCiAgICAgIHszLCAxMywgNCwgNywgMTUsIDIsIDgsIDE0LCAxMiwgMCwgMSwgMTAsIDYsIDksIDExLCA1fSwKICAgICAgezAsIDE0LCA3LCAxMSwgMTAsIDQsIDEzLCAxLCA1LCA4LCAxMiwgNiwgOSwgMywgMiwgMTV9LAogICAgICB7MTMsIDgsIDEwLCAxLCAzLCAxNSwgNCwgMiwgMTEsIDYsIDcsIDEyLCAwLCA1LCAxNCwgOX0KICAgIH0sCgogICAgewogICAgICB7MTAsIDAsIDksIDE0LCA2LCAzLCAxNSwgNSwgMSwgMTMsIDEyLCA3LCAxMSwgNCwgMiwgOH0sCiAgICAgIHsxMywgNywgMCwgOSwgMywgNCwgNiwgMTAsIDIsIDgsIDUsIDE0LCAxMiwgMTEsIDE1LCAxfSwKICAgICAgezEzLCA2LCA0LCA5LCA4LCAxNSwgMywgMCwgMTEsIDEsIDIsIDEyLCA1LCAxMCwgMTQsIDd9LAogICAgICB7MSwgMTAsIDEzLCAwLCA2LCA5LCA4LCA3LCA0LCAxNSwgMTQsIDMsIDExLCA1LCAyLCAxMn0KICAgIH0sCgogICAgewogICAgICB7NywgMTMsIDE0LCAzLCAwLCA2LCA5LCAxMCwgMSwgMiwgOCwgNSwgMTEsIDEyLCA0LCAxNX0sCiAgICAgIHsxMywgOCwgMTEsIDUsIDYsIDE1LCAwLCAzLCA0LCA3LCAyLCAxMiwgMSwgMTAsIDE0LCA5fSwKICAgICAgezEwLCA2LCA5LCAwLCAxMiwgMTEsIDcsIDEzLCAxNSwgMSwgMywgMTQsIDUsIDIsIDgsIDR9LAogICAgICB7MywgMTUsIDAsIDYsIDEwLCAxLCAxMywgOCwgOSwgNCwgNSwgMTEsIDEyLCA3LCAyLCAxNH0KICAgIH0sCgogICAgewogICAgICB7MiwgMTIsIDQsIDEsIDcsIDEwLCAxMSwgNiwgOCwgNSwgMywgMTUsIDEzLCAwLCAxNCwgOX0sCiAgICAgIHsxNCwgMTEsIDIsIDEyLCA0LCA3LCAxMywgMSwgNSwgMCwgMTUsIDEwLCAzLCA5LCA4LCA2fSwKICAgICAgezQsIDIsIDEsIDExLCAxMCwgMTMsIDcsIDgsIDE1LCA5LCAxMiwgNSwgNiwgMywgMCwgMTR9LAogICAgICB7MTEsIDgsIDEyLCA3LCAxLCAxNCwgMiwgMTMsIDYsIDE1LCAwLCA5LCAxMCwgNCwgNSwgM30KICAgIH0sCgogICAgewogICAgICB7MTIsIDEsIDEwLCAxNSwgOSwgMiwgNiwgOCwgMCwgMTMsIDMsIDQsIDE0LCA3LCA1LCAxMX0sCiAgICAgIHsxMCwgMTUsIDQsIDIsIDcsIDEyLCA5LCA1LCA2LCAxLCAxMywgMTQsIDAsIDExLCAzLCA4fSwKICAgICAgezksIDE0LCAxNSwgNSwgMiwgOCwgMTIsIDMsIDcsIDAsIDQsIDEwLCAxLCAxMywgMTEsIDZ9LAogICAgICB7NCwgMywgMiwgMTIsIDksIDUsIDE1LCAxMCwgMTEsIDE0LCAxLCA3LCA2LCAwLCA4LCAxM30KICAgIH0sCgogICAgewogICAgICB7NCwgMTEsIDIsIDE0LCAxNSwgMCwgOCwgMTMsIDMsIDEyLCA5LCA3LCA1LCAxMCwgNiwgMX0sCiAgICAgIHsxMywgMCwgMTEsIDcsIDQsIDksIDEsIDEwLCAxNCwgMywgNSwgMTIsIDIsIDE1LCA4LCA2fSwKICAgICAgezEsIDQsIDExLCAxMywgMTIsIDMsIDcsIDE0LCAxMCwgMTUsIDYsIDgsIDAsIDUsIDksIDJ9LAogICAgICB7NiwgMTEsIDEzLCA4LCAxLCA0LCAxMCwgNywgOSwgNSwgMCwgMTUsIDE0LCAyLCAzLCAxMn0KICAgIH0sCgogICAgewogICAgICB7MTMsIDIsIDgsIDQsIDYsIDE1LCAxMSwgMSwgMTAsIDksIDMsIDE0LCA1LCAwLCAxMiwgN30sCiAgICAgIHsxLCAxNSwgMTMsIDgsIDEwLCAzLCA3LCA0LCAxMiwgNSwgNiwgMTEsIDAsIDE0LCA5LCAyfSwKICAgICAgezcsIDExLCA0LCAxLCA5LCAxMiwgMTQsIDIsIDAsIDYsIDEwLCAxMywgMTUsIDMsIDUsIDh9LAogICAgICB7MiwgMSwgMTQsIDcsIDQsIDEwLCA4LCAxMywgMTUsIDEyLCA5LCAwLCAzLCA1LCA2LCAxMX0KICAgIH0KICB9OwogIAogIHN0cmluZyByZXQgPSAiIjsKICBmb3IgKGludCBpID0gMDsgaSA8IDg7IGkrKykgewogICAgc3RyaW5nIG91dGVyID0gIiI7CiAgICBzdHJpbmcgaW5uZXIgPSAiIjsKICAgIG91dGVyID0gb3V0ZXIgKyB0ZXh0W2kgKiA2XSArIHRleHRbaSAqIDYgKyA1XTsKICAgIGlubmVyID0gaW5uZXIgKyB0ZXh0W2kgKiA2ICsgMV0gKyB0ZXh0W2kgKiA2ICsgMl0gKyB0ZXh0W2kgKiA2ICsgM10gKyB0ZXh0W2kgKiA2ICsgNF07CiAgICBpbnQgdmFsID0gc2JveFtpXVtiaW5fdG9fZGVjKG91dGVyKV1bYmluX3RvX2RlYyhpbm5lcildOwogICAgcmV0ID0gcmV0ICsgZGVjX3RvX2Jpbih2YWwpOwogIH0KICByZXR1cm4gcmV0Owp9CgpzdHJpbmcgcGVyKHN0cmluZyB0ZXh0KSB7CiAgaW50IHBlcltdID0gewogICAgMTYsIDcsIDIwLCAyMSwKICAgIDI5LCAxMiwgMjgsIDE3LAogICAgMSwgMTUsIDIzLCAyNiwKICAgIDUsIDE4LCAzMSwgMTAsCiAgICAyLCA4LCAyNCwgMTQsCiAgICAzMiwgMjcsIDMsIDksCiAgICAxOSwgMTMsIDMwLCA2LAogICAgMjIsIDExLCA0LCAyNQogIH07CiAgcmV0dXJuIHBlcm11dGUodGV4dCwgcGVyLCAzMik7Cn0KCnN0cmluZyBmaW5hbF9wZXJtdXRhdGlvbihzdHJpbmcgdGV4dCkgewogIGludCBmaW5hbF9wZXJtW10gPSB7CiAgICA0MCwgOCwgNDgsIDE2LCA1NiwgMjQsIDY0LCAzMiwKICAgIDM5LCA3LCA0NywgMTUsIDU1LCAyMywgNjMsIDMxLAogICAgMzgsIDYsIDQ2LCAxNCwgNTQsIDIyLCA2MiwgMzAsCiAgICAzNywgNSwgNDUsIDEzLCA1MywgMjEsIDYxLCAyOSwKICAgIDM2LCA0LCA0NCwgMTIsIDUyLCAyMCwgNjAsIDI4LAogICAgMzUsIDMsIDQzLCAxMSwgNTEsIDE5LCA1OSwgMjcsCiAgICAzNCwgMiwgNDIsIDEwLCA1MCwgMTgsIDU4LCAyNiwKICAgIDMzLCAxLCA0MSwgOSwgNDksIDE3LCA1NywgMjUKICB9OwogIHJldHVybiBwZXJtdXRlKHRleHQsIGZpbmFsX3Blcm0sIDY0KTsKfQoKc3RyaW5nIERFU19lbmNyeXB0KHN0cmluZyBwbGFpbl90ZXh0LCByb3VuZF9rZXlzIGtleSkgewogIHBsYWluX3RleHQgPSBoZXhfdG9fYmluKHBsYWluX3RleHQpOwogIHBsYWluX3RleHQgPSBpbml0aWFsX3Blcm11dGF0aW9uKHBsYWluX3RleHQpOwoKICBzdHJpbmcgY2hpcGVyX2xlZnQ7CiAgc3RyaW5nIGNoaXBlcl9yaWdodDsKCiAgLy8gVEhFIEZVTkNUSU9OCiAgc3BsaXRfc3RyaW5nKHBsYWluX3RleHQsIGNoaXBlcl9sZWZ0LCBjaGlwZXJfcmlnaHQpOwogIAogIGZvciAoaW50IGkgPSAwOyBpIDwgMTY7IGkrKykgewogICAgc3RyaW5nIGNoaXBlcl9yaWdodF9leHBhbmRlZCA9IGV4cGFuc2lvbihjaGlwZXJfcmlnaHQpOwoKICAgIHN0cmluZyBmaXJzdF94b3IgPSB4b3JfZihjaGlwZXJfcmlnaHRfZXhwYW5kZWQsIGtleS5yb3VuZF9rZXlzX2JpbltpXSk7CgogICAgc3RyaW5nIHNib3hfc3RyID0gc2JveF9vcGVyYXRpb24oZmlyc3RfeG9yKTsKICAgIHNib3hfc3RyID0gcGVyKHNib3hfc3RyKTsKICAgIHN0cmluZyByZXN1bHQgPSB4b3JfZihjaGlwZXJfbGVmdCwgc2JveF9zdHIpOwogICAgCiAgICBjaGlwZXJfbGVmdCA9IHJlc3VsdDsKCiAgICBpZiAoaSAhPSAxNSkgewogICAgICBzd2FwKGNoaXBlcl9sZWZ0LCBjaGlwZXJfcmlnaHQpOwogICAgfQogIH0KICBzdHJpbmcgY2hpcGVyX3RleHQgPSBjaGlwZXJfbGVmdCArIGNoaXBlcl9yaWdodDsKICBjaGlwZXJfdGV4dCA9IGZpbmFsX3Blcm11dGF0aW9uKGNoaXBlcl90ZXh0KTsKCiAgY291dCA8PCAiSW5pdGlhbCBwZXJtdXRhdGlvbiAgOiAiIDw8IGJpbl90b19oZXgocGxhaW5fdGV4dCkgPDwgIlxuIjsKICBjb3V0IDw8ICJGaW5hbCBjaGlwcGVyIHRleHQgICA6ICIgPDwgYmluX3RvX2hleChjaGlwZXJfdGV4dCkgPDwgIlxuIjsKCiAgcmV0dXJuIGJpbl90b19oZXgoY2hpcGVyX3RleHQpOwp9CgpzdHJpbmcgREVTX2RlY3J5cHQoc3RyaW5nIGNoaXBlcl90ZXh0LCBzdHJpbmcga2V5X2hleCkgewogIHJvdW5kX2tleXMga2V5ID0gZ2VuZXJhdGVfcm91bmRfa2V5cygiZGVjcnlwdGlvbl9zY2hlbWUiLCBrZXlfaGV4KTsKICByb3VuZF9rZXlzIHJldmVyc2VkX2tleTsKICBmb3IgKGludCBpID0gMTU7IGkgPj0gMDsgaS0tKSB7CiAgICByZXZlcnNlZF9rZXkucm91bmRfa2V5c19iaW5bMTUgLSBpXSA9IGtleS5yb3VuZF9rZXlzX2JpbltpXTsKICAgIHJldmVyc2VkX2tleS5yb3VuZF9rZXlzX2hleFsxNSAtIGldID0ga2V5LnJvdW5kX2tleXNfaGV4W2ldOwogIH0KICByZXR1cm4gREVTX2VuY3J5cHQoY2hpcGVyX3RleHQsIHJldmVyc2VkX2tleSk7Cn0KCnZlY3RvcjxzdHJpbmc+IGlucHV0X2VuY3J5cHQoKSB7IAogIC8vIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCBmb3IgY29udmVydGluZyBsaXRlcmFsIHN0cmluZyBpbnRvIGhleGFkZWNpbWFsCiAgc3RyaW5nIGlucHV0X3RleHQ7CiAgY291dCA8PCAiSW5wdXQgcGxhaW4gdGV4dDoiIDw8ICJcbiI7CiAgY291dCA8PCAiPj4gIjsKICBjaW4uaWdub3JlKCk7CiAgZ2V0bGluZShjaW4sIGlucHV0X3RleHQpOwogIHZlY3RvcjxzdHJpbmc+IHBsYWluX3RleHQoMSk7CgogIGludCBrID0gMDsKICBmb3IgKGludCBpID0gMDsgaSA8IGlucHV0X3RleHQubGVuZ3RoKCk7IGkrKykgewogICAgc3RyaW5nIGNoYXJhY3RlciA9ICIiOwogICAgZm9yKGludCBqID0gNzsgaiA+PSAwOyBqLS0pIHsKICAgICAgYm9vbCBpc19zZXQgPSBpbnB1dF90ZXh0W2ldICYgKDEgPDwgaik7CiAgICAgIGlmIChpc19zZXQgPT0gMSkgewogICAgICAgIGNoYXJhY3RlciA9IGNoYXJhY3RlciArICIxIjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjaGFyYWN0ZXIgPSBjaGFyYWN0ZXIgKyAiMCI7CiAgICAgIH0KICAgIH0KICAgIHN0cmluZyBjaGFyYWN0ZXJfbGVmdCwgY2hhcmFjdGVyX3JpZ2h0OwogICAgc3BsaXRfc3RyaW5nKGNoYXJhY3RlciwgY2hhcmFjdGVyX2xlZnQsIGNoYXJhY3Rlcl9yaWdodCk7CiAgICBpZiAocGxhaW5fdGV4dFtrXS5sZW5ndGgoKSA9PSAxNikgewogICAgICBrKys7CiAgICAgIHBsYWluX3RleHQucHVzaF9iYWNrKCIiICk7CiAgICB9CiAgICBwbGFpbl90ZXh0W2tdID0gcGxhaW5fdGV4dFtrXSArIGJpbl90b19oZXgoY2hhcmFjdGVyX2xlZnQpOwogICAgcGxhaW5fdGV4dFtrXSA9IHBsYWluX3RleHRba10gKyBiaW5fdG9faGV4KGNoYXJhY3Rlcl9yaWdodCk7CiAgfQoKICBpZiAocGxhaW5fdGV4dFtrXS5sZW5ndGgoKSAhPSAxNikgewogICAgZm9yIChpbnQgaSA9IHBsYWluX3RleHRba10ubGVuZ3RoKCk7IGkgPCAxNjsgaSsrKSB7CiAgICAgIHBsYWluX3RleHRba10gPSBwbGFpbl90ZXh0W2tdICsgJzAnOwogICAgfQogIH0KICByZXR1cm4gcGxhaW5fdGV4dDsKfQoKc3RyaW5nIG91dHB1dF9kZWNyeXB0KHZlY3RvcjxzdHJpbmc+IHBsYWluX3RleHRfaGV4KSB7CiAgc3RyaW5nIHJldCA9ICIiOwogIGZvciAoaW50IGkgPSAwOyBpIDwgcGxhaW5fdGV4dF9oZXguc2l6ZSgpOyBpKyspIHsKICAgIGZvciAoaW50IGogPSAwOyBqIDwgMTY7IGogKz0gMikgewogICAgICBzdHJpbmcgdHdvX2hleCA9IHBsYWluX3RleHRfaGV4W2ldLnN1YnN0cihqLCAyKTsKICAgICAgaW50IHZhbHVlID0gc3RvaSh0d29faGV4LCAwLCAxNik7CiAgICAgIGlmICh2YWx1ZSAhPSAwKSB7CiAgICAgICAgcmV0ICs9IChjaGFyKXZhbHVlOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiByZXQ7Cn0KCmludCBtYWluKCkgewogIHdoaWxlICgxKSB7CiAgICBpbnQgbWVudTsKICAgIGNvdXQgPDwgInx8PT09PT09PT09PT09PT09PT09PT09PSIgPDwgInx8IiA8PCAnXG4nOwogICAgY291dCA8PCAifHwgV2VsbGNvbWUgdG8gREVTIiA8PCAiXHQiIDw8ICJ8fCIgPDwgJ1xuJzsKICAgIGNvdXQgPDwgInx8IENob29zZSBNZW51OiIgPDwgIlx0XHQiIDw8ICJ8fCIgPDwgJ1xuJzsgCiAgICBjb3V0IDw8ICJ8fCAxOiBFbmNyeXB0IFRleHQiIDw8ICJcdCIgPDwgInx8IiA8PCAnXG4nOwogICAgY291dCA8PCAifHwgMjogRGVjcnlwdCBUZXh0IiA8PCAiXHQiIDw8ICJ8fCIgPDwgJ1xuJzsKICAgIGNvdXQgPDwgInx8IDA6IEV4aXQiIDw8ICJcdFx0IiA8PCAifHwiIDw8ICdcbic7CiAgICBjb3V0IDw8ICJ8fCA+PiAiOwogICAgY2luID4+IG1lbnU7CiAgICBjb3V0IDw8ICJ8fD09PT09PT09PT09PT09PT09PT09PT0iIDw8ICJ8fCIgPDwgJ1xuJyA8PCAnXG4nOwoKICAgIGlmIChtZW51ID09IDEpIHsKICAgICAgY291dCA8PCAiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IiA8PCAnXG4nOwogICAgICB2ZWN0b3I8c3RyaW5nPiBwbGFpbl90ZXh0ID0gaW5wdXRfZW5jcnlwdCgpOwogICAgICBjb25zdCBpbnQgbWVzc2FnZV9zaXplID0gcGxhaW5fdGV4dC5zaXplKCk7CiAgICAgIHJvdW5kX2tleXMga2V5ID0gZ2VuZXJhdGVfcm91bmRfa2V5cygiZW5jcnlwdGlvbl9zY2hlbWUiKTsKICAgICAgdmVjdG9yPHN0cmluZz4gY2hpcGVyX3RleHQ7CgogICAgICBjb3V0IDw8ICJcbiIgPDwgIkVuY3J5cHRpbmcgcGxhaW4gdGV4dC4uLiIgPDwgIlxuIjsgIAogICAgICBmb3IgKGludCBpID0gMDsgaSA8IG1lc3NhZ2Vfc2l6ZTsgaSsrKSB7CiAgICAgICAgY2hpcGVyX3RleHQucHVzaF9iYWNrKERFU19lbmNyeXB0KHBsYWluX3RleHRbaV0sIGtleSkpOwogICAgICAgIGNvdXQgPDwgIlBsYWluIHRleHQgZW5jcnlwdGVkIFsiIDw8IGkgKyAxIDw8ICIvIiA8PCBtZXNzYWdlX3NpemUgPDwgIl0iIDw8ICdcbicgPDwgJ1xuJzsKICAgICAgfQogICAgICBjb3V0IDw8ICJLZXkgPSAiIDw8IGtleS5yYW5kb21faGV4IDw8ICdcbic7CiAgICAgIGNvdXQgPDwgIkNoaXBlciB0ZXh0ID0geyIgPDwgJ1xuJzsKICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBtZXNzYWdlX3NpemU7IGkrKykgewogICAgICAgIGNvdXQgPDwgY2hpcGVyX3RleHRbaV07CiAgICAgIH0KICAgICAgY291dCA8PCAnXG4nIDw8ICJ9IiA8PCAnXG4nOwogICAgICBjb3V0IDw8ICI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0iIDw8ICdcbicgPDwgJ1xuJzsKICAgIH0gZWxzZSBpZiAobWVudSA9PSAyKSB7ICAKICAgICAgY291dCA8PCAiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IiA8PCAnXG4nOwogICAgICBzdHJpbmcga2V5LCBjaGlwZXJfdGV4dDsKICAgICAgdmVjdG9yPHN0cmluZz4gcGxhaW5fdGV4dF9oZXg7CiAgICAgIGNvdXQgPDwgIklucHV0IGtleToiIDw8ICdcbicgPDwgIj4+ICI7CiAgICAgIGNpbiA+PiBrZXk7CiAgICAgIGNvdXQgPDwgIklucHV0IGNoaXBlciB0ZXh0OiIgPDwgJ1xuJyA8PCAiPj4gIjsKICAgICAgY2luID4+IGNoaXBlcl90ZXh0OwogICAgICBjb25zdCBpbnQgbWVzc2FnZV9zaXplID0gY2hpcGVyX3RleHQubGVuZ3RoKCkgLyAxNjsKICAgICAgY291dCA8PCAiXG4iIDw8ICJEZWNyeXB0aW5nIGNoaXBlciB0ZXh0Li4uIiA8PCAiXG4iOwogICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNoaXBlcl90ZXh0Lmxlbmd0aCgpOyBpICs9IDE2KSB7CiAgICAgICAgc3RyaW5nIGNoaXBlcl90ZXh0X3BhcnRpdGlvbiA9IGNoaXBlcl90ZXh0LnN1YnN0cihpLCAxNik7CiAgICAgICAgcGxhaW5fdGV4dF9oZXgucHVzaF9iYWNrKERFU19kZWNyeXB0KGNoaXBlcl90ZXh0X3BhcnRpdGlvbiwga2V5KSk7CiAgICAgICAgY291dCA8PCAiQ2hpcGVyIHRleHQgZGVjcnlwdGVkIFsiIDw8IGkgLyAxNiArIDEgPDwgIi8iIDw8IG1lc3NhZ2Vfc2l6ZSA8PCAiXSIgPDwgJ1xuJyA8PCAnXG4nOwogICAgICB9CiAgICAgIHN0cmluZyBwbGFpbl90ZXh0ID0gb3V0cHV0X2RlY3J5cHQocGxhaW5fdGV4dF9oZXgpOwogICAgICBjb3V0IDw8IHBsYWluX3RleHQgPDwgJ1xuJzsKICAgICAgY291dCA8PCAiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IiA8PCAnXG4nIDw8ICdcbic7CiAgICB9IGVsc2UgaWYgKG1lbnUgPT0gMCkgewogICAgICBicmVhazsKICAgIH0gZWxzZSB7CiAgICAgIGNvdXQgPDwgIkludmFsaWQgY29tbWFuZCIgPDwgJ1xuJyA8PCAnXG4nOwogICAgfQogIH0KCiAgcmV0dXJuIDA7Cn0=