Cryptography Stack Exchange is a question and answer site for software developers, mathematicians and others interested in cryptography. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am trying to implement MISTY1. It's RFC, RFC2994, contains psuedocode that I basically copy and pasted into Code::Blocks. However, I managed to mess that up somehow. After 2 days, I still have not figured out what i did wrong (Im probably being blinded by familiarity).

The RFC provides 2 test vectors, but only the key, plaintext and ciphertext. it does not provide internal values of any sort, and i cannot find other examples of calculations.

I can decrypt incorrectly encrypted data, so i suspect the error is in the key scheduling part, but I have no values to test with.

Can someone see where I made a mistake with the algorithm?

class MISTY1{
        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]);
               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]);
               d0 = d0 ^ (d1 | EK[((k-1)/2+4)%8]);
               d1 = d1 ^ (d0 & EK[((k-1)/2+2)%8+8]);
            return (d0 << 16) | d1;

        MISTY1() : keyset(false) {}

        MISTY1(std::string key){
            keyset = false;

        void setkey(std::string key){
            if (keyset)
            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)
            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)
            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));

What did I manage to do wrong?

The full code is at . the test vector (in the main function) provided contained 2 blocks of data. i just encrypted the first block. the second block is commented out. the functions not in class MISTY1 have been used for quite some time and are of no concern. They are there to tell you what they do

Edit: I have looked at other implementations, and I seem to be doing the same things they do, and yet I'm not getting correct outputs.

EDIT: After fixing the && bug, it is still not correct:

share|improve this question
up vote 2 down vote accepted

Your implementation of FI() looks suspect to me. I'm pretty sure d7 is supposed to be a 7-bit value, but you store it in a 16-bit value. This means that, after any operation that could set higher bits of d7, you need to clear all but the low 7 bits of d7. Your code doesn't do that. I suspect that's gonna screw things up.

You even have a statement d7 = d7 & 0x7f; at the critical point, but for some reason you put it in parentheses and commented it out. Fix that. Uncomment and unparenthesize it.

See RFC 2994 for more.

share|improve this answer

Your implementation of FI() has the expression (d7 && 0xffffU) << 9 at the end. I suspect you mean (d7 & 0xffffU) << 9.

share|improve this answer
that is a bug, but unfortunately, it didnt fix the implementation :( – calccrypto Aug 2 '12 at 8:35

Given that you have other implementations that seem to be correct, here are some steps you can take:

  • Test each of the components of the cipher, by feeding some inputs and comparing the outputs your code gives to the output the other implementations give. Test FI(), FO(), and the tables; those are small enough you should be able to exhaustively test them (on all possible inputs). Test FL() and FLINV() on a large collection of random inputs. Then, test the full cipher on a large collection of random inputs.

  • Generate some test vectors from the other implementations that you believe you be correct. Extract the output after each round. Compare these testvectors to what your implementation produces.

I would expect that these methods should enable you to narrow down where the problem is.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.