#include <algorithm>
#include <iostream>
#include <sstream>
static const std::string h = "0123456789abcdef";
uint64_t toint(const std::string & s, const int & base = 10){
// Changees strings to uint64_t
uint64_t INT = 0;
switch (base){
case 2:
for(unsigned int x = 0; x < s.size(); x++)
INT = (INT << 1) + (s[x] == '\x31');
break;
case 8:
std::stringstream(s) >> std::oct >> INT;
break;
case 10:
std::stringstream(s) >> std::dec >> INT;
break;
case 16:
std::stringstream(s) >> std::hex >> INT;
break;
case 256:
for(uint8_t x = 0; x < s.size(); x++)
INT = (INT << 8) + (uint8_t) s[x];
break;
default:
exit(1);
break;
};
return INT;
}
template<typename T>
std::string makehex(T value, unsigned int size = 2 * sizeof(T)){
// Changes a value to its hexadecimal string
if (!size){
std::stringstream out;
out << std::hex << value;
return out.str();
}
std::string out(size, '0');
while (value && size){
out[--size] = h[value & 15];
value >>= 4;
}
return out;
}
std::string hexlify(const std::string & in){
// Changes an ASCII string to an ASCII string containing the
// hexadecimal representation of the orignal chars
std::string out = "";
for(unsigned int x = 0; x < in.size(); x++)
out += makehex((unsigned char) in[x], 2);
return out;
}
std::string unhexlify(const std::string & in){
if (in.size() & 1)
exit(1);
std::string out = "";
for(unsigned int x = 0; x < in.size(); x += 2)
if (in.substr(x, 2) == "00")
out += std::string(1, 0);
else
out += (unsigned char) ((h.find(tolower(in[x])) << 4) + h.find(tolower(in[x + 1])));
return out;
}
class MISTY1{
private:
bool keyset;
uint16_t EK[32];
uint8_t S7TABLE[128];
uint16_t S9TABLE[512];
uint16_t FI(uint16_t FI_IN, uint16_t FI_KEY){
uint16_t d9 = FI_IN >> 7;
uint16_t d7 = FI_IN & 0x7f;
d9 = S9TABLE[d9] ^ d7;
d7 = S7TABLE[d7] ^ d9;
// ( d7 = d7 & 0x7f; )
d7 = d7 ^ (FI_KEY >> 9);
d9 = d9 ^ (FI_KEY & 0x1ff);
d9 = S9TABLE[d9] ^ d7;
return ((uint16_t) (d7 && 0xffffU) << 9) | d9;
}
uint32_t FO(uint32_t FO_IN, uint16_t k){
uint16_t t0 = FO_IN >> 16;
uint16_t t1 = FO_IN & 0xffff;
t0 = t0 ^ EK[k];
t0 = FI(t0, EK[(k+5)%8+8]);
t0 = t0 ^ t1;
t1 = t1 ^ EK[(k+2)%8];
t1 = FI(t1, EK[(k+1)%8+8]);
t1 = t1 ^ t0;
t0 = t0 ^ EK[(k+7)%8];
t0 = FI(t0, EK[(k+3)%8+8]);
t0 = t0 ^ t1;
t1 = t1 ^ EK[(k+4)%8];
return (t1 << 16) | t0;
}
uint32_t FL(uint32_t FL_IN, uint32_t k){
uint16_t d0 = FL_IN >> 16;
uint16_t d1 = FL_IN & 0xffff;
if (!(k & 1)){
d1 = d1 ^ (d0 & EK[k/2]);
d0 = d0 ^ (d1 | EK[(k/2+6)%8+8]);
}
else{
d1 = d1 ^ (d0 & EK[((k-1)/2+2)%8+8]);
d0 = d0 ^ (d1 | EK[((k-1)/2+4)%8]);
}
return (d0 << 16) | d1;
}
uint32_t FLINV(uint32_t FL_IN, uint32_t k){
uint16_t d0 = FL_IN >> 16;
uint16_t d1 = FL_IN & 0xffff;
if (!(k & 1)){
d0 = d0 ^ (d1 | EK[(k/2+6)%8+8]);
d1 = d1 ^ (d0 & EK[k/2]);
}
else{
d0 = d0 ^ (d1 | EK[((k-1)/2+4)%8]);
d1 = d1 ^ (d0 & EK[((k-1)/2+2)%8+8]);
}
return (d0 << 16) | d1;
}
public:
MISTY1() : keyset(false) {}
MISTY1(std::string key){
keyset = false;
setkey(key);
}
void setkey(std::string key){
if (keyset)
exit(2);
uint8_t S7[128] = { 0x1b, 0x32, 0x33, 0x5a, 0x3b, 0x10, 0x17, 0x54, 0x5b, 0x1a, 0x72, 0x73, 0x6b, 0x2c, 0x66, 0x49,
0x1f, 0x24, 0x13, 0x6c, 0x37, 0x2e, 0x3f, 0x4a, 0x5d, 0x0f, 0x40, 0x56, 0x25, 0x51, 0x1c, 0x04,
0x0b, 0x46, 0x20, 0x0d, 0x7b, 0x35, 0x44, 0x42, 0x2b, 0x1e, 0x41, 0x14, 0x4b, 0x79, 0x15, 0x6f,
0x0e, 0x55, 0x09, 0x36, 0x74, 0x0c, 0x67, 0x53, 0x28, 0x0a, 0x7e, 0x38, 0x02, 0x07, 0x60, 0x29,
0x19, 0x12, 0x65, 0x2f, 0x30, 0x39, 0x08, 0x68, 0x5f, 0x78, 0x2a, 0x4c, 0x64, 0x45, 0x75, 0x3d,
0x59, 0x48, 0x03, 0x57, 0x7c, 0x4f, 0x62, 0x3c, 0x1d, 0x21, 0x5e, 0x27, 0x6a, 0x70, 0x4d, 0x3a,
0x01, 0x6d, 0x6e, 0x63, 0x18, 0x77, 0x23, 0x05, 0x26, 0x76, 0x00, 0x31, 0x2d, 0x7a, 0x7f, 0x61,
0x50, 0x22, 0x11, 0x06, 0x47, 0x16, 0x52, 0x4e, 0x71, 0x3e, 0x69, 0x43, 0x34, 0x5c, 0x58, 0x7d};
uint16_t S9[512] = {0x1c3, 0x0cb, 0x153, 0x19f, 0x1e3, 0x0e9, 0x0fb, 0x035, 0x181, 0x0b9, 0x117, 0x1eb, 0x133, 0x009, 0x02d, 0x0d3,
0x0c7, 0x14a, 0x037, 0x07e, 0x0eb, 0x164, 0x193, 0x1d8, 0x0a3, 0x11e, 0x055, 0x02c, 0x01d, 0x1a2, 0x163, 0x118,
0x14b, 0x152, 0x1d2, 0x00f, 0x02b, 0x030, 0x13a, 0x0e5, 0x111, 0x138, 0x18e, 0x063, 0x0e3, 0x0c8, 0x1f4, 0x01b,
0x001, 0x09d, 0x0f8, 0x1a0, 0x16d, 0x1f3, 0x01c, 0x146, 0x07d, 0x0d1, 0x082, 0x1ea, 0x183, 0x12d, 0x0f4, 0x19e,
0x1d3, 0x0dd, 0x1e2, 0x128, 0x1e0, 0x0ec, 0x059, 0x091, 0x011, 0x12f, 0x026, 0x0dc, 0x0b0, 0x18c, 0x10f, 0x1f7,
0x0e7, 0x16c, 0x0b6, 0x0f9, 0x0d8, 0x151, 0x101, 0x14c, 0x103, 0x0b8, 0x154, 0x12b, 0x1ae, 0x017, 0x071, 0x00c,
0x047, 0x058, 0x07f, 0x1a4, 0x134, 0x129, 0x084, 0x15d, 0x19d, 0x1b2, 0x1a3, 0x048, 0x07c, 0x051, 0x1ca, 0x023,
0x13d, 0x1a7, 0x165, 0x03b, 0x042, 0x0da, 0x192, 0x0ce, 0x0c1, 0x06b, 0x09f, 0x1f1, 0x12c, 0x184, 0x0fa, 0x196,
0x1e1, 0x169, 0x17d, 0x031, 0x180, 0x10a, 0x094, 0x1da, 0x186, 0x13e, 0x11c, 0x060, 0x175, 0x1cf, 0x067, 0x119,
0x065, 0x068, 0x099, 0x150, 0x008, 0x007, 0x17c, 0x0b7, 0x024, 0x019, 0x0de, 0x127, 0x0db, 0x0e4, 0x1a9, 0x052,
0x109, 0x090, 0x19c, 0x1c1, 0x028, 0x1b3, 0x135, 0x16a, 0x176, 0x0df, 0x1e5, 0x188, 0x0c5, 0x16e, 0x1de, 0x1b1,
0x0c3, 0x1df, 0x036, 0x0ee, 0x1ee, 0x0f0, 0x093, 0x049, 0x09a, 0x1b6, 0x069, 0x081, 0x125, 0x00b, 0x05e, 0x0b4,
0x149, 0x1c7, 0x174, 0x03e, 0x13b, 0x1b7, 0x08e, 0x1c6, 0x0ae, 0x010, 0x095, 0x1ef, 0x04e, 0x0f2, 0x1fd, 0x085,
0x0fd, 0x0f6, 0x0a0, 0x16f, 0x083, 0x08a, 0x156, 0x09b, 0x13c, 0x107, 0x167, 0x098, 0x1d0, 0x1e9, 0x003, 0x1fe,
0x0bd, 0x122, 0x089, 0x0d2, 0x18f, 0x012, 0x033, 0x06a, 0x142, 0x0ed, 0x170, 0x11b, 0x0e2, 0x14f, 0x158, 0x131,
0x147, 0x05d, 0x113, 0x1cd, 0x079, 0x161, 0x1a5, 0x179, 0x09e, 0x1b4, 0x0cc, 0x022, 0x132, 0x01a, 0x0e8, 0x004,
0x187, 0x1ed, 0x197, 0x039, 0x1bf, 0x1d7, 0x027, 0x18b, 0x0c6, 0x09c, 0x0d0, 0x14e, 0x06c, 0x034, 0x1f2, 0x06e,
0x0ca, 0x025, 0x0ba, 0x191, 0x0fe, 0x013, 0x106, 0x02f, 0x1ad, 0x172, 0x1db, 0x0c0, 0x10b, 0x1d6, 0x0f5, 0x1ec,
0x10d, 0x076, 0x114, 0x1ab, 0x075, 0x10c, 0x1e4, 0x159, 0x054, 0x11f, 0x04b, 0x0c4, 0x1be, 0x0f7, 0x029, 0x0a4,
0x00e, 0x1f0, 0x077, 0x04d, 0x17a, 0x086, 0x08b, 0x0b3, 0x171, 0x0bf, 0x10e, 0x104, 0x097, 0x15b, 0x160, 0x168,
0x0d7, 0x0bb, 0x066, 0x1ce, 0x0fc, 0x092, 0x1c5, 0x06f, 0x016, 0x04a, 0x0a1, 0x139, 0x0af, 0x0f1, 0x190, 0x00a,
0x1aa, 0x143, 0x17b, 0x056, 0x18d, 0x166, 0x0d4, 0x1fb, 0x14d, 0x194, 0x19a, 0x087, 0x1f8, 0x123, 0x0a7, 0x1b8,
0x141, 0x03c, 0x1f9, 0x140, 0x02a, 0x155, 0x11a, 0x1a1, 0x198, 0x0d5, 0x126, 0x1af, 0x061, 0x12e, 0x157, 0x1dc,
0x072, 0x18a, 0x0aa, 0x096, 0x115, 0x0ef, 0x045, 0x07b, 0x08d, 0x145, 0x053, 0x05f, 0x178, 0x0b2, 0x02e, 0x020,
0x1d5, 0x03f, 0x1c9, 0x1e7, 0x1ac, 0x044, 0x038, 0x014, 0x0b1, 0x16b, 0x0ab, 0x0b5, 0x05a, 0x182, 0x1c8, 0x1d4,
0x018, 0x177, 0x064, 0x0cf, 0x06d, 0x100, 0x199, 0x130, 0x15a, 0x005, 0x120, 0x1bb, 0x1bd, 0x0e0, 0x04f, 0x0d6,
0x13f, 0x1c4, 0x12a, 0x015, 0x006, 0x0ff, 0x19b, 0x0a6, 0x043, 0x088, 0x050, 0x15f, 0x1e8, 0x121, 0x073, 0x17e,
0x0bc, 0x0c2, 0x0c9, 0x173, 0x189, 0x1f5, 0x074, 0x1cc, 0x1e6, 0x1a8, 0x195, 0x01f, 0x041, 0x00d, 0x1ba, 0x032,
0x03d, 0x1d1, 0x080, 0x0a8, 0x057, 0x1b9, 0x162, 0x148, 0x0d9, 0x105, 0x062, 0x07a, 0x021, 0x1ff, 0x112, 0x108,
0x1c0, 0x0a9, 0x11d, 0x1b0, 0x1a6, 0x0cd, 0x0f3, 0x05c, 0x102, 0x05b, 0x1d9, 0x144, 0x1f6, 0x0ad, 0x0a5, 0x03a,
0x1cb, 0x136, 0x17f, 0x046, 0x0e1, 0x01e, 0x1dd, 0x0e6, 0x137, 0x1fa, 0x185, 0x08c, 0x08f, 0x040, 0x1b5, 0x0be,
0x078, 0x000, 0x0ac, 0x110, 0x15e, 0x124, 0x002, 0x1bc, 0x0a2, 0x0ea, 0x070, 0x1fc, 0x116, 0x15c, 0x04c, 0x1c2};
for(uint8_t i = 0; i < 128; i++)
S7TABLE[i] = S7[i];
for(uint16_t i = 0; i < 512; i++)
S9TABLE[i] = S9[i];
for(uint8_t i = 0; i < 8; i++)
EK[i] = ((key[i*2]*256) & 0xffff) + (key[i*2+1] & 0xff);
for(uint8_t i = 0; i < 8; i++){
EK[i+ 8] = FI(EK[i], EK[(i+1)%8]);
EK[i+16] = EK[i+8] & 0x1ff;
EK[i+24] = EK[i+8] >> 9;
}
keyset = true;
}
std::string encrypt(std::string data){
if (!keyset)
exit(1);
uint32_t D0 = toint(data.substr(0, 4), 256);
uint32_t D1 = toint(data.substr(4, 4), 256);
// 0 round
D0 = FL(D0, 0);
D1 = FL(D1, 1);
D1 = D1 ^ FO(D0, 0);
// 1 round
D0 = D0 ^ FO(D1, 1);
// 2 round
D0 = FL(D0, 2);
D1 = FL(D1, 3);
D1 = D1 ^ FO(D0, 2);
// 3 round
D0 = D0 ^ FO(D1, 3);
// 4 round
D0 = FL(D0, 4);
D1 = FL(D1, 5);
D1 = D1 ^ FO(D0, 4);
// 5 round
D0 = D0 ^ FO(D1, 5);
// 6 round
D0 = FL(D0, 6);
D1 = FL(D1, 7);
D1 = D1 ^ FO(D0, 6);
// 7 round
D0 = D0 ^ FO(D1, 7);
// final
D0 = FL(D0, 8);
D1 = FL(D1, 9);
return unhexlify(makehex(D1, 8) + makehex(D0, 8));
}
std::string decrypt(std::string data){
if (!keyset)
exit(1);
uint32_t D0 = toint(data.substr(4, 4), 256);
uint32_t D1 = toint(data.substr(0, 4), 256);
D0 = FLINV(D0, 8);
D1 = FLINV(D1, 9);
D0 = D0 ^ FO(D1, 7);
D1 = D1 ^ FO(D0, 6);
D0 = FLINV(D0, 6);
D1 = FLINV(D1, 7);
D0 = D0 ^ FO(D1, 5);
D1 = D1 ^ FO(D0, 4);
D0 = FLINV(D0, 4);
D1 = FLINV(D1, 5);
D0 = D0 ^ FO(D1, 3);
D1 = D1 ^ FO(D0, 2);
D0 = FLINV(D0, 2);
D1 = FLINV(D1, 3);
D0 = D0 ^ FO(D1, 1);
D1 = D1 ^ FO(D0, 0);
D0 = FLINV(D0, 0);
D1 = FLINV(D1, 1);
return unhexlify(makehex(D0, 8) + makehex(D1));
}
};
int main(){
std::string k = unhexlify("00112233445566778899aabbccddeeff");
std::string p = unhexlify("0123456789abcdef"); // fedcba9876543210
std::string c = unhexlify("8b1da5f56ab3d07c"); // 04b68240b13be95d
MISTY1 m(k);
std::string test_p = m.encrypt(p);
std::cout << hexlify(test_p) << std::endl;
std::cout << hexlify(m.decrypt(test_p)) << std::endl;
return 0;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3N0cmVhbT4KCnN0YXRpYyBjb25zdCBzdGQ6OnN0cmluZyBoID0gIjAxMjM0NTY3ODlhYmNkZWYiOwoKdWludDY0X3QgdG9pbnQoY29uc3Qgc3RkOjpzdHJpbmcgJiBzLCBjb25zdCBpbnQgJiBiYXNlID0gMTApewogICAgLy8gQ2hhbmdlZXMgc3RyaW5ncyB0byB1aW50NjRfdAogICAgdWludDY0X3QgSU5UID0gMDsKICAgIHN3aXRjaCAoYmFzZSl7CiAgICAgICAgY2FzZSAyOgogICAgICAgICAgICBmb3IodW5zaWduZWQgaW50IHggPSAwOyB4IDwgcy5zaXplKCk7IHgrKykKICAgICAgICAgICAgICAgIElOVCA9IChJTlQgPDwgMSkgKyAoc1t4XSA9PSAnXHgzMScpOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIHN0ZDo6c3RyaW5nc3RyZWFtKHMpID4+IHN0ZDo6b2N0ID4+IElOVDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxMDoKICAgICAgICAgICAgc3RkOjpzdHJpbmdzdHJlYW0ocykgPj4gc3RkOjpkZWMgPj4gSU5UOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDE2OgogICAgICAgICAgICBzdGQ6OnN0cmluZ3N0cmVhbShzKSA+PiBzdGQ6OmhleCA+PiBJTlQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjU2OgogICAgICAgICAgICBmb3IodWludDhfdCB4ID0gMDsgeCA8IHMuc2l6ZSgpOyB4KyspCiAgICAgICAgICAgICAgICBJTlQgPSAoSU5UIDw8IDgpICsgKHVpbnQ4X3QpIHNbeF07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIGV4aXQoMSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgfTsKICAgIHJldHVybiBJTlQ7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0ZDo6c3RyaW5nIG1ha2VoZXgoVCB2YWx1ZSwgdW5zaWduZWQgaW50IHNpemUgPSAyICogc2l6ZW9mKFQpKXsKICAgIC8vIENoYW5nZXMgYSB2YWx1ZSB0byBpdHMgaGV4YWRlY2ltYWwgc3RyaW5nCiAgICBpZiAoIXNpemUpewogICAgICAgIHN0ZDo6c3RyaW5nc3RyZWFtIG91dDsKICAgICAgICBvdXQgPDwgc3RkOjpoZXggPDwgdmFsdWU7CiAgICAgICAgcmV0dXJuIG91dC5zdHIoKTsKICAgIH0KICAgIHN0ZDo6c3RyaW5nIG91dChzaXplLCAnMCcpOwogICAgd2hpbGUgKHZhbHVlICYmIHNpemUpewogICAgICAgIG91dFstLXNpemVdID0gaFt2YWx1ZSAmIDE1XTsKICAgICAgICB2YWx1ZSA+Pj0gNDsKICAgIH0KICAgIHJldHVybiBvdXQ7Cn0KCnN0ZDo6c3RyaW5nIGhleGxpZnkoY29uc3Qgc3RkOjpzdHJpbmcgJiBpbil7CiAgICAvLyBDaGFuZ2VzIGFuIEFTQ0lJIHN0cmluZyB0byBhbiBBU0NJSSBzdHJpbmcgY29udGFpbmluZyB0aGUKICAgIC8vIGhleGFkZWNpbWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBvcmlnbmFsIGNoYXJzCiAgICBzdGQ6OnN0cmluZyBvdXQgPSAiIjsKICAgIGZvcih1bnNpZ25lZCBpbnQgeCA9IDA7IHggPCBpbi5zaXplKCk7IHgrKykKICAgICAgICBvdXQgKz0gbWFrZWhleCgodW5zaWduZWQgY2hhcikgaW5beF0sIDIpOwogICAgcmV0dXJuIG91dDsKfQoKc3RkOjpzdHJpbmcgdW5oZXhsaWZ5KGNvbnN0IHN0ZDo6c3RyaW5nICYgaW4pewoJaWYgKGluLnNpemUoKSAmIDEpCiAgICAgICAgZXhpdCgxKTsKICAgIHN0ZDo6c3RyaW5nIG91dCA9ICIiOwoJZm9yKHVuc2lnbmVkIGludCB4ID0gMDsgeCA8IGluLnNpemUoKTsgeCArPSAyKQoJCWlmIChpbi5zdWJzdHIoeCwgMikgPT0gIjAwIikKCQkJb3V0ICs9IHN0ZDo6c3RyaW5nKDEsIDApOwoJCWVsc2UKCQkJb3V0ICs9ICh1bnNpZ25lZCBjaGFyKSAoKGguZmluZCh0b2xvd2VyKGluW3hdKSkgPDwgNCkgKyBoLmZpbmQodG9sb3dlcihpblt4ICsgMV0pKSk7CglyZXR1cm4gb3V0Owp9CgpjbGFzcyBNSVNUWTF7CiAgICBwcml2YXRlOgogICAgICAgIGJvb2wga2V5c2V0OwogICAgICAgIHVpbnQxNl90IEVLWzMyXTsKICAgICAgICB1aW50OF90IFM3VEFCTEVbMTI4XTsKICAgICAgICB1aW50MTZfdCBTOVRBQkxFWzUxMl07CgogICAgICAgIHVpbnQxNl90IEZJKHVpbnQxNl90IEZJX0lOLCB1aW50MTZfdCBGSV9LRVkpewogICAgICAgICAgICB1aW50MTZfdCBkOSA9IEZJX0lOID4+IDc7CiAgICAgICAgICAgIHVpbnQxNl90IGQ3ID0gRklfSU4gJiAweDdmOwogICAgICAgICAgICBkOSA9IFM5VEFCTEVbZDldIF4gZDc7CiAgICAgICAgICAgIGQ3ID0gUzdUQUJMRVtkN10gXiBkOTsKLy8gICAgICAgICAgICAoIGQ3ID0gZDcgJiAweDdmOyApCiAgICAgICAgICAgIGQ3ID0gZDcgXiAoRklfS0VZID4+IDkpOwogICAgICAgICAgICBkOSA9IGQ5IF4gKEZJX0tFWSAmIDB4MWZmKTsKICAgICAgICAgICAgZDkgPSBTOVRBQkxFW2Q5XSBeIGQ3OwogICAgICAgICAgICByZXR1cm4gKCh1aW50MTZfdCkgKGQ3ICYmIDB4ZmZmZlUpIDw8IDkpIHwgZDk7CiAgICAgICAgfQoKICAgICAgICB1aW50MzJfdCBGTyh1aW50MzJfdCBGT19JTiwgdWludDE2X3Qgayl7CiAgICAgICAgICAgIHVpbnQxNl90IHQwID0gRk9fSU4gPj4gMTY7CiAgICAgICAgICAgIHVpbnQxNl90IHQxID0gRk9fSU4gJiAweGZmZmY7CiAgICAgICAgICAgIHQwID0gdDAgXiBFS1trXTsKICAgICAgICAgICAgdDAgPSBGSSh0MCwgRUtbKGsrNSklOCs4XSk7CiAgICAgICAgICAgIHQwID0gdDAgXiB0MTsKICAgICAgICAgICAgdDEgPSB0MSBeIEVLWyhrKzIpJThdOwogICAgICAgICAgICB0MSA9IEZJKHQxLCBFS1soaysxKSU4KzhdKTsKICAgICAgICAgICAgdDEgPSB0MSBeIHQwOwogICAgICAgICAgICB0MCA9IHQwIF4gRUtbKGsrNyklOF07CiAgICAgICAgICAgIHQwID0gRkkodDAsIEVLWyhrKzMpJTgrOF0pOwogICAgICAgICAgICB0MCA9IHQwIF4gdDE7CiAgICAgICAgICAgIHQxID0gdDEgXiBFS1soays0KSU4XTsKICAgICAgICAgICAgcmV0dXJuICh0MSA8PCAxNikgfCB0MDsKICAgICAgICB9CgogICAgICAgIHVpbnQzMl90IEZMKHVpbnQzMl90IEZMX0lOLCB1aW50MzJfdCBrKXsKICAgICAgICAgICAgdWludDE2X3QgZDAgPSBGTF9JTiA+PiAxNjsKICAgICAgICAgICAgdWludDE2X3QgZDEgPSBGTF9JTiAmIDB4ZmZmZjsKICAgICAgICAgICAgaWYgKCEoayAmIDEpKXsKICAgICAgICAgICAgICAgZDEgPSBkMSBeIChkMCAmIEVLW2svMl0pOwogICAgICAgICAgICAgICBkMCA9IGQwIF4gKGQxIHwgRUtbKGsvMis2KSU4KzhdKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlewogICAgICAgICAgICAgICBkMSA9IGQxIF4gKGQwICYgRUtbKChrLTEpLzIrMiklOCs4XSk7CiAgICAgICAgICAgICAgIGQwID0gZDAgXiAoZDEgfCBFS1soKGstMSkvMis0KSU4XSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIChkMCA8PCAxNikgfCBkMTsKICAgICAgICB9CgogICAgICAgIHVpbnQzMl90IEZMSU5WKHVpbnQzMl90IEZMX0lOLCB1aW50MzJfdCBrKXsKICAgICAgICAgICAgdWludDE2X3QgZDAgPSBGTF9JTiA+PiAxNjsKICAgICAgICAgICAgdWludDE2X3QgZDEgPSBGTF9JTiAmIDB4ZmZmZjsKICAgICAgICAgICAgaWYgKCEoayAmIDEpKXsKICAgICAgICAgICAgICAgZDAgPSBkMCBeIChkMSB8IEVLWyhrLzIrNiklOCs4XSk7CiAgICAgICAgICAgICAgIGQxID0gZDEgXiAoZDAgJiBFS1trLzJdKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlewogICAgICAgICAgICAgICBkMCA9IGQwIF4gKGQxIHwgRUtbKChrLTEpLzIrNCklOF0pOwogICAgICAgICAgICAgICBkMSA9IGQxIF4gKGQwICYgRUtbKChrLTEpLzIrMiklOCs4XSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIChkMCA8PCAxNikgfCBkMTsKICAgICAgICB9CgogICAgcHVibGljOgogICAgICAgIE1JU1RZMSgpIDoga2V5c2V0KGZhbHNlKSB7fQoKICAgICAgICBNSVNUWTEoc3RkOjpzdHJpbmcga2V5KXsKICAgICAgICAgICAga2V5c2V0ID0gZmFsc2U7CiAgICAgICAgICAgIHNldGtleShrZXkpOwogICAgICAgIH0KCiAgICAgICAgdm9pZCBzZXRrZXkoc3RkOjpzdHJpbmcga2V5KXsKICAgICAgICAgICAgaWYgKGtleXNldCkKICAgICAgICAgICAgICAgIGV4aXQoMik7CiAgICAgICAgICAgIHVpbnQ4X3QgUzdbMTI4XSA9IHsgMHgxYiwgMHgzMiwgMHgzMywgMHg1YSwgMHgzYiwgMHgxMCwgMHgxNywgMHg1NCwgMHg1YiwgMHgxYSwgMHg3MiwgMHg3MywgMHg2YiwgMHgyYywgMHg2NiwgMHg0OSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDFmLCAweDI0LCAweDEzLCAweDZjLCAweDM3LCAweDJlLCAweDNmLCAweDRhLCAweDVkLCAweDBmLCAweDQwLCAweDU2LCAweDI1LCAweDUxLCAweDFjLCAweDA0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MGIsIDB4NDYsIDB4MjAsIDB4MGQsIDB4N2IsIDB4MzUsIDB4NDQsIDB4NDIsIDB4MmIsIDB4MWUsIDB4NDEsIDB4MTQsIDB4NGIsIDB4NzksIDB4MTUsIDB4NmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwZSwgMHg1NSwgMHgwOSwgMHgzNiwgMHg3NCwgMHgwYywgMHg2NywgMHg1MywgMHgyOCwgMHgwYSwgMHg3ZSwgMHgzOCwgMHgwMiwgMHgwNywgMHg2MCwgMHgyOSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDE5LCAweDEyLCAweDY1LCAweDJmLCAweDMwLCAweDM5LCAweDA4LCAweDY4LCAweDVmLCAweDc4LCAweDJhLCAweDRjLCAweDY0LCAweDQ1LCAweDc1LCAweDNkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NTksIDB4NDgsIDB4MDMsIDB4NTcsIDB4N2MsIDB4NGYsIDB4NjIsIDB4M2MsIDB4MWQsIDB4MjEsIDB4NWUsIDB4MjcsIDB4NmEsIDB4NzAsIDB4NGQsIDB4M2EsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwMSwgMHg2ZCwgMHg2ZSwgMHg2MywgMHgxOCwgMHg3NywgMHgyMywgMHgwNSwgMHgyNiwgMHg3NiwgMHgwMCwgMHgzMSwgMHgyZCwgMHg3YSwgMHg3ZiwgMHg2MSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDUwLCAweDIyLCAweDExLCAweDA2LCAweDQ3LCAweDE2LCAweDUyLCAweDRlLCAweDcxLCAweDNlLCAweDY5LCAweDQzLCAweDM0LCAweDVjLCAweDU4LCAweDdkfTsKCiAgICAgICAgICAgIHVpbnQxNl90IFM5WzUxMl0gPSB7MHgxYzMsIDB4MGNiLCAweDE1MywgMHgxOWYsIDB4MWUzLCAweDBlOSwgMHgwZmIsIDB4MDM1LCAweDE4MSwgMHgwYjksIDB4MTE3LCAweDFlYiwgMHgxMzMsIDB4MDA5LCAweDAyZCwgMHgwZDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwYzcsIDB4MTRhLCAweDAzNywgMHgwN2UsIDB4MGViLCAweDE2NCwgMHgxOTMsIDB4MWQ4LCAweDBhMywgMHgxMWUsIDB4MDU1LCAweDAyYywgMHgwMWQsIDB4MWEyLCAweDE2MywgMHgxMTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxNGIsIDB4MTUyLCAweDFkMiwgMHgwMGYsIDB4MDJiLCAweDAzMCwgMHgxM2EsIDB4MGU1LCAweDExMSwgMHgxMzgsIDB4MThlLCAweDA2MywgMHgwZTMsIDB4MGM4LCAweDFmNCwgMHgwMWIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwMDEsIDB4MDlkLCAweDBmOCwgMHgxYTAsIDB4MTZkLCAweDFmMywgMHgwMWMsIDB4MTQ2LCAweDA3ZCwgMHgwZDEsIDB4MDgyLCAweDFlYSwgMHgxODMsIDB4MTJkLCAweDBmNCwgMHgxOWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxZDMsIDB4MGRkLCAweDFlMiwgMHgxMjgsIDB4MWUwLCAweDBlYywgMHgwNTksIDB4MDkxLCAweDAxMSwgMHgxMmYsIDB4MDI2LCAweDBkYywgMHgwYjAsIDB4MThjLCAweDEwZiwgMHgxZjcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwZTcsIDB4MTZjLCAweDBiNiwgMHgwZjksIDB4MGQ4LCAweDE1MSwgMHgxMDEsIDB4MTRjLCAweDEwMywgMHgwYjgsIDB4MTU0LCAweDEyYiwgMHgxYWUsIDB4MDE3LCAweDA3MSwgMHgwMGMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwNDcsIDB4MDU4LCAweDA3ZiwgMHgxYTQsIDB4MTM0LCAweDEyOSwgMHgwODQsIDB4MTVkLCAweDE5ZCwgMHgxYjIsIDB4MWEzLCAweDA0OCwgMHgwN2MsIDB4MDUxLCAweDFjYSwgMHgwMjMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxM2QsIDB4MWE3LCAweDE2NSwgMHgwM2IsIDB4MDQyLCAweDBkYSwgMHgxOTIsIDB4MGNlLCAweDBjMSwgMHgwNmIsIDB4MDlmLCAweDFmMSwgMHgxMmMsIDB4MTg0LCAweDBmYSwgMHgxOTYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxZTEsIDB4MTY5LCAweDE3ZCwgMHgwMzEsIDB4MTgwLCAweDEwYSwgMHgwOTQsIDB4MWRhLCAweDE4NiwgMHgxM2UsIDB4MTFjLCAweDA2MCwgMHgxNzUsIDB4MWNmLCAweDA2NywgMHgxMTksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwNjUsIDB4MDY4LCAweDA5OSwgMHgxNTAsIDB4MDA4LCAweDAwNywgMHgxN2MsIDB4MGI3LCAweDAyNCwgMHgwMTksIDB4MGRlLCAweDEyNywgMHgwZGIsIDB4MGU0LCAweDFhOSwgMHgwNTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxMDksIDB4MDkwLCAweDE5YywgMHgxYzEsIDB4MDI4LCAweDFiMywgMHgxMzUsIDB4MTZhLCAweDE3NiwgMHgwZGYsIDB4MWU1LCAweDE4OCwgMHgwYzUsIDB4MTZlLCAweDFkZSwgMHgxYjEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwYzMsIDB4MWRmLCAweDAzNiwgMHgwZWUsIDB4MWVlLCAweDBmMCwgMHgwOTMsIDB4MDQ5LCAweDA5YSwgMHgxYjYsIDB4MDY5LCAweDA4MSwgMHgxMjUsIDB4MDBiLCAweDA1ZSwgMHgwYjQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxNDksIDB4MWM3LCAweDE3NCwgMHgwM2UsIDB4MTNiLCAweDFiNywgMHgwOGUsIDB4MWM2LCAweDBhZSwgMHgwMTAsIDB4MDk1LCAweDFlZiwgMHgwNGUsIDB4MGYyLCAweDFmZCwgMHgwODUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwZmQsIDB4MGY2LCAweDBhMCwgMHgxNmYsIDB4MDgzLCAweDA4YSwgMHgxNTYsIDB4MDliLCAweDEzYywgMHgxMDcsIDB4MTY3LCAweDA5OCwgMHgxZDAsIDB4MWU5LCAweDAwMywgMHgxZmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwYmQsIDB4MTIyLCAweDA4OSwgMHgwZDIsIDB4MThmLCAweDAxMiwgMHgwMzMsIDB4MDZhLCAweDE0MiwgMHgwZWQsIDB4MTcwLCAweDExYiwgMHgwZTIsIDB4MTRmLCAweDE1OCwgMHgxMzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxNDcsIDB4MDVkLCAweDExMywgMHgxY2QsIDB4MDc5LCAweDE2MSwgMHgxYTUsIDB4MTc5LCAweDA5ZSwgMHgxYjQsIDB4MGNjLCAweDAyMiwgMHgxMzIsIDB4MDFhLCAweDBlOCwgMHgwMDQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxODcsIDB4MWVkLCAweDE5NywgMHgwMzksIDB4MWJmLCAweDFkNywgMHgwMjcsIDB4MThiLCAweDBjNiwgMHgwOWMsIDB4MGQwLCAweDE0ZSwgMHgwNmMsIDB4MDM0LCAweDFmMiwgMHgwNmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwY2EsIDB4MDI1LCAweDBiYSwgMHgxOTEsIDB4MGZlLCAweDAxMywgMHgxMDYsIDB4MDJmLCAweDFhZCwgMHgxNzIsIDB4MWRiLCAweDBjMCwgMHgxMGIsIDB4MWQ2LCAweDBmNSwgMHgxZWMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxMGQsIDB4MDc2LCAweDExNCwgMHgxYWIsIDB4MDc1LCAweDEwYywgMHgxZTQsIDB4MTU5LCAweDA1NCwgMHgxMWYsIDB4MDRiLCAweDBjNCwgMHgxYmUsIDB4MGY3LCAweDAyOSwgMHgwYTQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwMGUsIDB4MWYwLCAweDA3NywgMHgwNGQsIDB4MTdhLCAweDA4NiwgMHgwOGIsIDB4MGIzLCAweDE3MSwgMHgwYmYsIDB4MTBlLCAweDEwNCwgMHgwOTcsIDB4MTViLCAweDE2MCwgMHgxNjgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwZDcsIDB4MGJiLCAweDA2NiwgMHgxY2UsIDB4MGZjLCAweDA5MiwgMHgxYzUsIDB4MDZmLCAweDAxNiwgMHgwNGEsIDB4MGExLCAweDEzOSwgMHgwYWYsIDB4MGYxLCAweDE5MCwgMHgwMGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxYWEsIDB4MTQzLCAweDE3YiwgMHgwNTYsIDB4MThkLCAweDE2NiwgMHgwZDQsIDB4MWZiLCAweDE0ZCwgMHgxOTQsIDB4MTlhLCAweDA4NywgMHgxZjgsIDB4MTIzLCAweDBhNywgMHgxYjgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxNDEsIDB4MDNjLCAweDFmOSwgMHgxNDAsIDB4MDJhLCAweDE1NSwgMHgxMWEsIDB4MWExLCAweDE5OCwgMHgwZDUsIDB4MTI2LCAweDFhZiwgMHgwNjEsIDB4MTJlLCAweDE1NywgMHgxZGMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwNzIsIDB4MThhLCAweDBhYSwgMHgwOTYsIDB4MTE1LCAweDBlZiwgMHgwNDUsIDB4MDdiLCAweDA4ZCwgMHgxNDUsIDB4MDUzLCAweDA1ZiwgMHgxNzgsIDB4MGIyLCAweDAyZSwgMHgwMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxZDUsIDB4MDNmLCAweDFjOSwgMHgxZTcsIDB4MWFjLCAweDA0NCwgMHgwMzgsIDB4MDE0LCAweDBiMSwgMHgxNmIsIDB4MGFiLCAweDBiNSwgMHgwNWEsIDB4MTgyLCAweDFjOCwgMHgxZDQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwMTgsIDB4MTc3LCAweDA2NCwgMHgwY2YsIDB4MDZkLCAweDEwMCwgMHgxOTksIDB4MTMwLCAweDE1YSwgMHgwMDUsIDB4MTIwLCAweDFiYiwgMHgxYmQsIDB4MGUwLCAweDA0ZiwgMHgwZDYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxM2YsIDB4MWM0LCAweDEyYSwgMHgwMTUsIDB4MDA2LCAweDBmZiwgMHgxOWIsIDB4MGE2LCAweDA0MywgMHgwODgsIDB4MDUwLCAweDE1ZiwgMHgxZTgsIDB4MTIxLCAweDA3MywgMHgxN2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwYmMsIDB4MGMyLCAweDBjOSwgMHgxNzMsIDB4MTg5LCAweDFmNSwgMHgwNzQsIDB4MWNjLCAweDFlNiwgMHgxYTgsIDB4MTk1LCAweDAxZiwgMHgwNDEsIDB4MDBkLCAweDFiYSwgMHgwMzIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwM2QsIDB4MWQxLCAweDA4MCwgMHgwYTgsIDB4MDU3LCAweDFiOSwgMHgxNjIsIDB4MTQ4LCAweDBkOSwgMHgxMDUsIDB4MDYyLCAweDA3YSwgMHgwMjEsIDB4MWZmLCAweDExMiwgMHgxMDgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxYzAsIDB4MGE5LCAweDExZCwgMHgxYjAsIDB4MWE2LCAweDBjZCwgMHgwZjMsIDB4MDVjLCAweDEwMiwgMHgwNWIsIDB4MWQ5LCAweDE0NCwgMHgxZjYsIDB4MGFkLCAweDBhNSwgMHgwM2EsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxY2IsIDB4MTM2LCAweDE3ZiwgMHgwNDYsIDB4MGUxLCAweDAxZSwgMHgxZGQsIDB4MGU2LCAweDEzNywgMHgxZmEsIDB4MTg1LCAweDA4YywgMHgwOGYsIDB4MDQwLCAweDFiNSwgMHgwYmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwNzgsIDB4MDAwLCAweDBhYywgMHgxMTAsIDB4MTVlLCAweDEyNCwgMHgwMDIsIDB4MWJjLCAweDBhMiwgMHgwZWEsIDB4MDcwLCAweDFmYywgMHgxMTYsIDB4MTVjLCAweDA0YywgMHgxYzJ9OwogICAgICAgICAgICBmb3IodWludDhfdCBpID0gMDsgaSA8IDEyODsgaSsrKQogICAgICAgICAgICAgICAgUzdUQUJMRVtpXSA9IFM3W2ldOwogICAgICAgICAgICBmb3IodWludDE2X3QgaSA9IDA7IGkgPCA1MTI7IGkrKykKICAgICAgICAgICAgICAgIFM5VEFCTEVbaV0gPSBTOVtpXTsKICAgICAgICAgICAgZm9yKHVpbnQ4X3QgaSA9IDA7IGkgPCA4OyBpKyspCiAgICAgICAgICAgICAgICBFS1tpXSA9ICgoa2V5W2kqMl0qMjU2KSAmIDB4ZmZmZikgKyAoa2V5W2kqMisxXSAmIDB4ZmYpOwogICAgICAgICAgICBmb3IodWludDhfdCBpID0gMDsgaSA8IDg7IGkrKyl7CiAgICAgICAgICAgICAgICBFS1tpKyA4XSA9IEZJKEVLW2ldLCBFS1soaSsxKSU4XSk7CiAgICAgICAgICAgICAgICBFS1tpKzE2XSA9IEVLW2krOF0gJiAweDFmZjsKICAgICAgICAgICAgICAgIEVLW2krMjRdID0gRUtbaSs4XSA+PiA5OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGtleXNldCA9IHRydWU7CiAgICAgICAgfQoKICAgICAgICBzdGQ6OnN0cmluZyBlbmNyeXB0KHN0ZDo6c3RyaW5nIGRhdGEpewogICAgICAgICAgICBpZiAoIWtleXNldCkKICAgICAgICAgICAgICAgIGV4aXQoMSk7CiAgICAgICAgICAgIHVpbnQzMl90IEQwID0gdG9pbnQoZGF0YS5zdWJzdHIoMCwgNCksIDI1Nik7CiAgICAgICAgICAgIHVpbnQzMl90IEQxID0gdG9pbnQoZGF0YS5zdWJzdHIoNCwgNCksIDI1Nik7CiAgICAgICAgICAgIC8vIDAgcm91bmQKICAgICAgICAgICAgRDAgPSBGTChEMCwgMCk7CiAgICAgICAgICAgIEQxID0gRkwoRDEsIDEpOwogICAgICAgICAgICBEMSA9IEQxIF4gRk8oRDAsIDApOwogICAgICAgICAgICAvLyAxIHJvdW5kCiAgICAgICAgICAgIEQwID0gRDAgXiBGTyhEMSwgMSk7CiAgICAgICAgICAgIC8vIDIgcm91bmQKICAgICAgICAgICAgRDAgPSBGTChEMCwgMik7CiAgICAgICAgICAgIEQxID0gRkwoRDEsIDMpOwogICAgICAgICAgICBEMSA9IEQxIF4gRk8oRDAsIDIpOwogICAgICAgICAgICAvLyAzIHJvdW5kCiAgICAgICAgICAgIEQwID0gRDAgXiBGTyhEMSwgMyk7CiAgICAgICAgICAgIC8vIDQgcm91bmQKICAgICAgICAgICAgRDAgPSBGTChEMCwgNCk7CiAgICAgICAgICAgIEQxID0gRkwoRDEsIDUpOwogICAgICAgICAgICBEMSA9IEQxIF4gRk8oRDAsIDQpOwogICAgICAgICAgICAvLyA1IHJvdW5kCiAgICAgICAgICAgIEQwID0gRDAgXiBGTyhEMSwgNSk7CiAgICAgICAgICAgIC8vIDYgcm91bmQKICAgICAgICAgICAgRDAgPSBGTChEMCwgNik7CiAgICAgICAgICAgIEQxID0gRkwoRDEsIDcpOwogICAgICAgICAgICBEMSA9IEQxIF4gRk8oRDAsIDYpOwogICAgICAgICAgICAvLyA3IHJvdW5kCiAgICAgICAgICAgIEQwID0gRDAgXiBGTyhEMSwgNyk7CiAgICAgICAgICAgIC8vIGZpbmFsCiAgICAgICAgICAgIEQwID0gRkwoRDAsIDgpOwogICAgICAgICAgICBEMSA9IEZMKEQxLCA5KTsKICAgICAgICAgICAgcmV0dXJuIHVuaGV4bGlmeShtYWtlaGV4KEQxLCA4KSArIG1ha2VoZXgoRDAsIDgpKTsKICAgICAgICB9CgogICAgICAgIHN0ZDo6c3RyaW5nIGRlY3J5cHQoc3RkOjpzdHJpbmcgZGF0YSl7CiAgICAgICAgICAgIGlmICgha2V5c2V0KQogICAgICAgICAgICAgICAgZXhpdCgxKTsKICAgICAgICAgICAgdWludDMyX3QgRDAgPSB0b2ludChkYXRhLnN1YnN0cig0LCA0KSwgMjU2KTsKICAgICAgICAgICAgdWludDMyX3QgRDEgPSB0b2ludChkYXRhLnN1YnN0cigwLCA0KSwgMjU2KTsKICAgICAgICAgICAgRDAgPSBGTElOVihEMCwgOCk7CiAgICAgICAgICAgIEQxID0gRkxJTlYoRDEsIDkpOwogICAgICAgICAgICBEMCA9IEQwIF4gRk8oRDEsIDcpOwogICAgICAgICAgICBEMSA9IEQxIF4gRk8oRDAsIDYpOwogICAgICAgICAgICBEMCA9IEZMSU5WKEQwLCA2KTsKICAgICAgICAgICAgRDEgPSBGTElOVihEMSwgNyk7CiAgICAgICAgICAgIEQwID0gRDAgXiBGTyhEMSwgNSk7CiAgICAgICAgICAgIEQxID0gRDEgXiBGTyhEMCwgNCk7CiAgICAgICAgICAgIEQwID0gRkxJTlYoRDAsIDQpOwogICAgICAgICAgICBEMSA9IEZMSU5WKEQxLCA1KTsKICAgICAgICAgICAgRDAgPSBEMCBeIEZPKEQxLCAzKTsKICAgICAgICAgICAgRDEgPSBEMSBeIEZPKEQwLCAyKTsKICAgICAgICAgICAgRDAgPSBGTElOVihEMCwgMik7CiAgICAgICAgICAgIEQxID0gRkxJTlYoRDEsIDMpOwogICAgICAgICAgICBEMCA9IEQwIF4gRk8oRDEsIDEpOwogICAgICAgICAgICBEMSA9IEQxIF4gRk8oRDAsIDApOwogICAgICAgICAgICBEMCA9IEZMSU5WKEQwLCAwKTsKICAgICAgICAgICAgRDEgPSBGTElOVihEMSwgMSk7CiAgICAgICAgICAgIHJldHVybiB1bmhleGxpZnkobWFrZWhleChEMCwgOCkgKyBtYWtlaGV4KEQxKSk7CiAgICAgICAgfQp9OwoKaW50IG1haW4oKXsKCiAgICBzdGQ6OnN0cmluZyBrID0gdW5oZXhsaWZ5KCIwMDExMjIzMzQ0NTU2Njc3ODg5OWFhYmJjY2RkZWVmZiIpOwogICAgc3RkOjpzdHJpbmcgcCA9IHVuaGV4bGlmeSgiMDEyMzQ1Njc4OWFiY2RlZiIpOyAvLyBmZWRjYmE5ODc2NTQzMjEwCiAgICBzdGQ6OnN0cmluZyBjID0gdW5oZXhsaWZ5KCI4YjFkYTVmNTZhYjNkMDdjIik7IC8vIDA0YjY4MjQwYjEzYmU5NWQKCiAgICBNSVNUWTEgbShrKTsKICAgIHN0ZDo6c3RyaW5nIHRlc3RfcCA9IG0uZW5jcnlwdChwKTsKICAgIHN0ZDo6Y291dCA8PCBoZXhsaWZ5KHRlc3RfcCkgPDwgc3RkOjplbmRsOwogICAgc3RkOjpjb3V0IDw8IGhleGxpZnkobS5kZWNyeXB0KHRlc3RfcCkpIDw8IHN0ZDo6ZW5kbDsKCiAgICByZXR1cm4gMDsKfQ==