সি: ধ্রুবক সময় কোড দ্বারা AES FIPS-197 সাববাইট টেবিল প্রতিস্থাপন করুন


17

ইন হয় FIPS-197 ( অ্যাডভান্সড এনক্রিপশন স্ট্যান্ডার্ড , হবে AES নামেও পরিচিত) তা ভারী ব্যবহারের তৈরি করা হয় SubBytes, যা হিসাবে প্রয়োগ করা যেতে পারে

unsigned char SubBytes(unsigned char x) {
static const unsigned char t[256] = {
  0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
  0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
  0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
  0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
  0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
  0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
  0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
  0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
  0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
  0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
  0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
  0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
  0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
  0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
  0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
  0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16};
return t[x];}

এই ফাংশন স্বেচ্ছাসেবী নয়; এটি একটি বিপরীতমুখী ম্যাপিং যা একটি গ্যালোইস ফিল্ডের একটি উল্টোপাল্টা এবং তারপরে অ্যাফাইন রূপান্তর দ্বারা গঠিত। সমস্ত বিশদটি ফেডারেশন -197 বিভাগ 5.1.1 বা এখানে বিভাগ 4.2.1 (কিছুটা আলাদা নামের অধীনে) are

একটি সারণী হিসাবে বাস্তবায়নের সাথে একটি সমস্যা হ'ল এটি তথাকথিত ক্যাশে-সময় আক্রমণগুলিতে খোলে ।

সুতরাং আপনার মিশনটি হ'ল উপরের SubBytes()ফাংশনটির জন্য একটি সঠিক প্রতিস্থাপন করা , যা ধ্রুবক-সময় আচরণ প্রদর্শন করে; আমরা যে ক্ষেত্রে যখন কিছুই ইনপুট উপর নির্ভর করে অনুমান করব xএর SubBytesপারেন ব্যবহার করা হয়:

  • একটি অ্যারে সূচক হিসাবে,
  • নিয়ন্ত্রণের প্রতীক হিসাবে if, while, for, case, অথবা অপারেটর ?:;
  • অপারেটরদের কোনো প্রতীক হিসাবে &&, ||, !, ==, !=, <, >, <=, >=, *, /, %;
  • অপারেটরদের অধিকার প্রতীক হিসাবে >>, <<, *=, /=, %=, <<=, >>=

বিজয়ী এন্ট্রি সর্বনিম্ন খরচ সঙ্গে এক, ইনপুট-নির্ভরশীল ডেটার পথে মৃত্যুদন্ড কার্যকর অপারেটরদের সংখ্যা থেকে প্রাপ্ত হবে, ইউনারী অপারেটরদের জন্য 5 ওজনের -এবং ~ভাল জন্য যত <<1, >>1, +1, -1; অন্যান্য সমস্ত অপারেটরের জন্য 7 এর ওজন, অন্যান্য গণনাগুলির সাথে শিফট, বা অন্যান্য ধ্রুবকের যোগ / সংযোজন (টাইপ কাস্ট এবং প্রচারগুলি বিনামূল্যে) নীতিমালা অনুসারে, আনলোলিং লুপগুলি (যদি থাকে তবে) এর ব্যয় অপরিবর্তিত থাকে এবং ইনপুট থেকে স্বতন্ত্র থাকে x। টাই-ব্রেকার হিসাবে, সাদা স্থান এবং মন্তব্যগুলি জয় করার পরে সংক্ষিপ্ত কোডের সাথে উত্তর।

আমি ২০১৩, ইউটিসি-তে যত তাড়াতাড়ি সম্ভব উত্তর হিসাবে একটি এন্ট্রি মনোনীত করার পরিকল্পনা করছি। আমি সেই ভাষাগুলিতে এমন উত্তরগুলি বিবেচনা করব যা সম্পর্কে আমি কিছু জ্ঞান রেখেছি, সেগুলিকে আকারের জন্য অনুকূলিত করা হয়নি এমন একটি সরাসরি অনুবাদ হিসাবে র‌্যাঙ্ক করে।

প্রাথমিক +1-1বাদ্যযন্ত্র অপারেটরগুলিতে, বিনামূল্যে ক্যাসেট এবং পদোন্নতি এবং আকারের র‌্যাঙ্কিংয়ের প্রাথমিক বাদ দেওয়ার জন্য ক্ষমাপ্রার্থী। *অবিচ্ছিন্ন এবং গুণক হিসাবে উভয়ই নিষিদ্ধ নোট ।


1
লক্ষ্য করা যায় না যে লুকআপগুলি নিখরচায় কারণ আপনি এগুলি ধ্রুবক হিসাবে ইনলাইন করতে পারেন।
পিটার টেলর

"বছরের প্রথম দিকে, ইউটিসি" - তারিখটি কি সময় অঞ্চলের চেয়ে আকর্ষণীয় হবে না?
পাওলো ইবারম্যান

@ পাওলোএবারম্যান: আমার উদ্দেশ্য এখন পরিষ্কার হওয়া উচিত।
fgrieu

উত্তর:


13

স্কোর: 940 933 926 910, ফিল্ড টাওয়ার অ্যাপ্রোচ

public class SBox2
{
    public static void main(String[] args)
    {
        for (int i = 0; i < 256; i++) {
            int s = SubBytes(i);
            System.out.format("%02x  ", s);
            if (i % 16 == 15) System.out.println();
        }
    }

    private static int SubBytes(int x) {
        int fwd;
        fwd  = 0x010001 & -(x & 1); x >>= 1; //   7+5+7+5+ | 24+
        fwd ^= 0x1d010f & -(x & 1); x >>= 1; // 7+7+5+7+5+ | 31+
        fwd ^= 0x4f020b & -(x & 1); x >>= 1; // 7+7+5+7+5+ | 31+
        fwd ^= 0x450201 & -(x & 1); x >>= 1; // 7+7+5+7+5+ | 31+
        fwd ^= 0xce080d & -(x & 1); x >>= 1; // 7+7+5+7+5+ | 31+
        fwd ^= 0xa20f0f & -(x & 1); x >>= 1; // 7+7+5+7+5+ | 31+
        fwd ^= 0xc60805 & -(x & 1); x >>= 1; // 7+7+5+7+5+ | 31+
        fwd ^= 0x60070e & -x;                // 7+7+5+     | 19+

        // Running total so far: 229

        int p1;
        {
            int ma = fwd;
            int mb = fwd >> 16;         // 7+         | 7+
            p1  = ma & -(mb&1); ma<<=1; //   7+5+7+5+ | 24+
            p1 ^= ma & -(mb&2); ma<<=1; // 7+7+5+7+5+ | 31+
            p1 ^= ma & -(mb&4); ma<<=1; // 7+7+5+7+5+ | 31+
            p1 ^= ma & -(mb&8);         // 7+7+5+7+   | 26+
            int t = p1 >> 3;            // 7+         | 7+
            p1 ^= (t >> 1) ^ (t & 0xe); // 7+5+7+7+   | 26+
        }

        // Running total so far: 229 + 152 = 381

        int y3, y2, y1, y0;
        {
            int Kinv = (fwd >> 20) ^ p1;     // 7+7+
            int w0 = Kinv & 1; Kinv >>= 1;   // 7+5+
            int w1 = Kinv & 1; Kinv >>= 1;   // 7+5+
            int w2 = Kinv & 1; Kinv >>= 1;   // 7+5+
            int w3 = Kinv & 1;               // 7+

            int t0 = w1 ^ w0 ^ (w2 & w3);      // 7+7+7+
            int t1 = w2 ^ (w0 | w3);           // 7+7+
            int t2 = t0 ^ t1;                  // 7+

            y3 = t2 ^ (t1 & (w1 & w3));        // 7+7+7+
            y2 = t0 ^ (w0 | t2);               // 7+7+
            y1 = w0 ^ w3 ^ (t1 & t0);          // 7+7+7+
            y0 = w3 ^ (t0 | (w1 ^ (w0 | w2))); // 7+7+7+7


        }

        // Running total so far: 381 + 24*7 + 3*5 = 564

        int p2;
        {
            int ma = fwd;
            p2  = ma & -y0; ma<<=1;       //   7+5+5+ | 17+
            p2 ^= ma & -y1; ma<<=1;       // 7+7+5+5+ | 24+
            p2 ^= ma & -y2; ma<<=1;       // 7+7+5+5+ | 24+
            p2 ^= ma & -y3;               // 7+7+5+   | 19+
            int t = p2 >> 3;              // 7+       | 7+
            p2 ^= (t >> 1) ^ (t & 0xe0e); // 7+5+7+7+ | 26
        }

        // Running total so far: 564 + 117 = 681

        int inv8;
        inv8  =  31 & -(p2 & 1);           //   7+5+7+   | 19+
        inv8 ^= 178 & -(p2 & 2); p2 >>= 2; // 7+7+5+7+7+ | 33+
        inv8 ^= 171 & -(p2 & 1);           // 7+7+5+7+   | 26+
        inv8 ^=  54 & -(p2 & 2); p2 >>= 6; // 7+7+5+7+7+ | 33+
        inv8 ^= 188 & -(p2 & 1);           // 7+7+5+7+   | 26+
        inv8 ^=  76 & -(p2 & 2); p2 >>= 2; // 7+7+5+7+7+ | 33+
        inv8 ^= 127 & -(p2 & 1);           // 7+7+5+7+   | 26+
        inv8 ^= 222 & -(p2 & 2);           // 7+7+5+7    | 26+

        return inv8 ^ 0x63;                // 7+         | 7+

        // Grand total: 681 + 229 = 910
    }
}

কাঠামোটি মূলত বায়ার এবং পেরালটার বাস্তবায়নের মতোই - জিএফ (2 ^ 8) এর বিপর্যয় হ্রাস করে জিএফ (2 to 4) এ একে একে রৈখিক উপস্থায় পরিণত করে, একটি অ-রৈখিক দেহ এবং একটি লিনিয়ার উপসর্গ, এবং তারপরে সেগুলি পৃথকভাবে ছোট করুন। আমি বিট নিষ্কাশনের জন্য কিছু জরিমানা প্রদান করি, তবে আমি সমান্তরালভাবে অপারেশন করতে সক্ষম হয়ে ক্ষতিপূরণ করি (এর বিটগুলির কিছু বিচার্য প্যাডিং সহ fwd)। আরো বিস্তারিত...

পটভূমি

সমস্যার বিবরণে উল্লিখিত হিসাবে, এস-বাক্সটি গ্যালোইস ফিল্ড জিএফ (2 ^ 8) এর একটি নির্দিষ্ট রূপায়ণের পরে একটি অ্যাফাইন ট্রান্সফরমেশন দ্বারা একটি বিপরীতকে অন্তর্ভুক্ত করে। আপনি যদি উভয়টির অর্থ জানেন তবে এই বিভাগটি এড়িয়ে যান।

একটি affine (বা লিনিয়ার) রূপান্তর একটি ফাংশন f(x)যা শ্রদ্ধা করে f(x + y) = f(x) + f(y)এবং f(a*x) = a*f(x)

ক্ষেত্র হ'ল Fদুটি বিশেষ উপাদান সহ উপাদানগুলির একটি সেট যা আমরা কল করব 0এবং 1এবং দুটি অপারেটর, যা আমরা কল করব +এবং *যা বিভিন্ন বৈশিষ্ট্যকে সম্মান করে। এই বিভাগে, যে অনুমান x, yএবং zউপাদান F

  • উপাদান Fঅধীনে ফর্ম একটি abelian গ্রুপ +সঙ্গে 0পরিচয় হিসাবে: অর্থাত x + yএকজন উপাদান F; x + 0 = 0 + x = x; প্রতিটি xএকটি সংশ্লিষ্ট হয়েছে -xযেমন যে x + (-x) = (-x) + x = 0; x + (y + z) = (x + y) + z; এবং x + y= y + x
  • উপাদান Fছাড়া অন্য 0অধীনে ফর্ম একটি abelian গ্রুপ *সঙ্গে 1পরিচয় হয়।
  • গুণ উপরন্তু উপর বিতরণ: x * (y + z) = (x * y) + (x * z)

দেখা যাচ্ছে যে সীমাবদ্ধ ক্ষেত্রগুলিতে বেশ কয়েকটি গুরুতর সীমাবদ্ধতা রয়েছে:

  • তাদের অবশ্যই অনেকগুলি উপাদান থাকতে হবে যা একটি মৌলিক শক্তি।
  • এগুলি একই আকারের অন্যান্য সমস্ত সীমাবদ্ধ ক্ষেত্রগুলি সহ আইসমোর্ফিক (যেমন প্রকৃতপক্ষে একটি নির্দিষ্ট আকারের কেবলমাত্র একটি সীমাবদ্ধ ক্ষেত্র রয়েছে, এবং অন্য যে কোনও ব্যক্তি কেবল পুনঃব্যবস্থা হয়; সেই ক্ষেত্রটি জিএফ (পি-কে) কল করুন যেখানে pপ্রধান এবং kশক্তি) ।
  • এর F\{0}অধীনে গুণক গোষ্ঠীটি *চক্রীয়; অর্থাৎ কমপক্ষে একটি উপাদান gযেমন প্রতিটি উপাদান একটি শক্তি হয় g
  • 1 এর বেশি ক্ষমতার জন্য kপ্রধান আদেশের ক্ষেত্রের আদেশের অবিচ্ছিন্ন বহুবর্ষ হিসাবে একটি প্রতিনিধিত্ব রয়েছে । উদাহরণস্বরূপ জিএফ (2 xover 8) এর ওভার জিএফ (2) এর বহুবর্ষের ক্ষেত্রে একটি প্রতিনিধিত্ব রয়েছে । আসলে সাধারণত একাধিক প্রতিনিধিত্ব রয়েছে। x^7 * xজিএফ বিবেচনা করুন (2 Consider 8); এটি কিছু অর্ডার -7 বহুপদী হতে হবে, তবে কোনটি? অনেকগুলি পছন্দ রয়েছে যা সঠিক কাঠামো দেয়; এইএস তৈরি করতে বেছে নিয়েছে x^8 = x^4 + x^3 + x + 1(অভিধানে ক্ষুদ্রতম বহুবচন যা কাজ করে)।

তাহলে আমরা কীভাবে জিএফ-এর (2 ^ 8) নির্দিষ্ট উপস্থাপনে একটি বিপর্যয় গণনা করব? সরাসরি মোকাবেলা করা খুব সমস্যাযুক্ত, তাই আমাদের এটিকে ভেঙে ফেলা দরকার।

মাঠের টাওয়ারগুলি: জিএফ (2 ^ 4) এর ক্ষেত্রে জিএফ (2 ^ 8) উপস্থাপন করছে

জিএফ (2) এর 8 টি শর্তের বহুবচন সহ জিএফ (2 ^ 8) উপস্থাপনের পরিবর্তে আমরা এটিকে জিএফের (2 ^ 4) 2 পদের বহুবচন দিয়ে উপস্থাপন করতে পারি। এবার আমাদের জন্য একটি রৈখিক বহুপদী নির্বাচন করতে হবে x^2। আমরা নির্বাচন ধরুন x^2 = px + q। তারপরে (ax + b) * (cx + d) = (ad + bc + acp)x + (bd + acq)

এই উপস্থাপনে একটি বিপরীত খুঁজে পাওয়া সহজ? যদি (cx + d) = (ax + b)^-1আমরা একযোগে সমীকরণ পেতে পারি

  • ad + (b + ap)c = 0
  • bd + (aq)c = 1

চলুন D = [b(b+ap) + a^2 q]এবং সেট করুন c = a * D^-1; d = (b + ap) * D^-1। সুতরাং আমরা জিএফ (2 ^ 4) এর রূপান্তর ব্যয়ের জন্য জিএফ (2 ^ 8), একটি বিপরীতমুখী এবং কয়েকটি সংযোজন এবং জিএফ (2 multip 4) এর গুন, এবং একটি রূপান্তর ফিরে করতে পারি। এমনকি যদি আমরা কোনও টেবিলের মাধ্যমে বিপরীতটি করি তবে আমরা টেবিলটির আকার 256 থেকে 16 এ কমিয়েছি।

বাস্তবায়ন বিশদ

জিএফ (4) এর উপস্থাপনা তৈরি করতে আমরা হ্রাস করতে তিনটি বহুপদীগুলির মধ্যে চয়ন করতে পারি x^4:

  • x^4 = x + 1
  • x^4 = x^3 + 1
  • x^4 = x^3 + x^2 + x + 1

সর্বাধিক গুরুত্বপূর্ণ পার্থক্যটি হ'ল গুণণের বাস্তবায়ন। তিনটির যে কোনওটির জন্য (যা poly3, 9, চ এর সাথে মিলিয়ে) নিম্নলিখিত কাজ করবে:

// 14x &, 7x unary -, 3x <<1, 3x >>1, 3x >>3, 6x ^ gives score 226
int mul(int a, int b) {
    // Call current values a = a0, b = b0
    int p = a & -(b & 1);
    a = ((a << 1) ^ (poly & -(a >> 3))) & 15;
    b >>= 1;
    // Now p = a0 * (b0 mod x); a = a0 x; b = b0 div x

    p ^= a & -(b & 1);
    a = ((a << 1) ^ (poly & -(a >> 3))) & 15;
    b >>= 1;
    // Now p = a0 * (b0 mod x^2); a = a0 x^2; b = b0 div x^2

    p ^= a & -(b & 1);
    a = ((a << 1) ^ (poly & -(a >> 3))) & 15;
    b >>= 1;
    // Now p = a0 * (b0 mod x^3); a = a0 x^3; b = b0 div x^3

    p ^= a & -(b & 1);
    // p = a0 * b0

    return p;
}

তবে, আমরা যদি চয়ন poly = 3করি তবে আমরা ওভারফ্লোটি আরও দক্ষতার সাথে পরিচালনা করতে পারি কারণ এটির একটি সুন্দর কাঠামো রয়েছে: ডাবল-ওভারফ্লো নেই, কারণ দুটি ইনপুট দুটি ঘনকিক এবং ঘনকও x^6 = x^2 (x + 1)। এছাড়াও আমরা শিফটগুলি সংরক্ষণ করতে পারি b: যেহেতু আমরা ওভারফ্লোটি শেষের দিকে ছেড়ে চলেছি, তাই 1 বা 1 এর a0 x^2সাথে কোনও সেট বিট নেই xএবং তাই আমরা এটি -1 এর পরিবর্তে -4 দিয়ে মাস্ক করতে পারি। ফলাফল হলো

// 10x &, 4x unary -, 3x <<1, 1x >>1, 1x >>3, 5x ^ gives score 152
int mul(int a, int b) {
    int p;
    p  = a & -(b & 1); a <<= 1;
    p ^= a & -(b & 2); a <<= 1;
    p ^= a & -(b & 4); a <<= 1;
    p ^= a & -(b & 8);
    // Here p = a0 * b0 but with overflow, which we need to bring back down.

    int t = p >> 3;
    p ^= (t >> 1) ^ (t & 0xe);
    return p & 15;
}

আমাদের এখনও জিএফের (2 ^ 8) জিএফ (2 2 4) এর উপস্থাপনের জন্য pএবং এর মানগুলি বেছে নিতে হবে q, তবে সেগুলিতে আমাদের কোনও বাধা নেই। একটি বিষয় যা গুরুত্বপূর্ণ তা হ'ল আমরা আমাদের মূল উপস্থাপনের বিট থেকে কর্ম প্রতিনিধিত্বের বিটগুলিতে রৈখিক ফাংশন পেতে পারি। এটি দুটি কারণে গুরুত্বপূর্ণ: প্রথমত, লিনিয়ার ট্রান্সফর্মেশনগুলি করা সহজ, অন্যদিকে একটি অ-লিনিয়ার রূপান্তরকরণের জন্য পুরো এস-বক্সটি অপ্টিমাইজ করতে অসুবিধাতে অনুকূলকরণের সমতুল্য প্রয়োজন হবে; দ্বিতীয়ত, কারণ আমরা কিছু পার্শ্ব সুবিধা পেতে পারি। কাঠামোটি পুনরুদ্ধার করতে:

GF256 SubBytes(GF256 x) {
    GF16 a, b, t, D, Dinv, c, d;

    (a, b) = f(x); // f is linear

    t = b + a * p;
    D = b * t + a * a * q;
    Dinv = inverse_GF16(D);
    c = a * Dinv;
    d = t * Dinv;

    return finv(c, d); // finv is also linear
}

বিটগুলি যদি xহয় x7 x6 ... x0তবে যেহেতু রূপান্তরটি লিনিয়ার হয় আমরা পাই a = f({x7}0000000 + 0{x6}000000 + ... + 0000000{x0}) = f({x7}0000000) + f(0{x6}000000) + ... + f(0000000{x0})। এটি স্কোয়ার করুন এবং আমরা a^2 = f({x7}0000000)^2 + f(0{x6}000000)^2 + ... + f(0000000{x0})^2যেখানে ক্রস-শর্তগুলি বাতিল করে (কারণ জিএফ (2), 1 + 1 = 0) তে। সুতরাং এর a^2একটি রৈখিক ফাংশন হিসাবে গণনা করা যেতে পারে x। আমরা পেতে ফরওয়ার্ড লিনিয়ার রূপান্তরকে বাড়িয়ে তুলতে পারি:

GF256 SubBytes(GF256 x) {
    GF16 a, b, t, a2q, D, Dinv, c, d;

    (a, b, t, a2q) = faug(x);

    D = b * t + a2q;
    Dinv = inverse_GF16(D);
    c = a * Dinv;
    d = t * Dinv;

    return finv(c, d);
}

এবং আমরা তিনটি গুণ এবং একটি সংযোজন নেমে এসেছি। Dinvসমান্তরালভাবে দুটি গুণকে করতে আমরা গুণক কোড প্রসারিত করতে পারি । সুতরাং আমাদের মোট ব্যয় হ'ল ফরোয়ার্ড লিনিয়ার রূপান্তরকরণ, সংযোজন, দুটি গুণ, জিএফ (2 ^ 4) এর বিপরীতমুখী এবং পিছনে রৈখিক রূপান্তর is আমরা এস-বাক্স-পরবর্তী বিপরীতমুখী রৈখিক রূপান্তর রোল করতে পারি এবং এটি মূলত বিনামূল্যে পেতে পারি।

রৈখিক রূপান্তরগুলির জন্য সহগের গুণাগুণ খুব আকর্ষণীয় নয় এবং এখানে একটি মুখোশ এবং সেখানে স্থানান্তরিত করার জন্য মাইক্রো-অপ্টিমাইজেশনও নয়। বাকি আকর্ষণীয় অংশটি অপ্টিমাইজেশনinverse_GF16। 4 বিট থেকে 4 বিট থেকে 2 ^ 64 টি বিভিন্ন ফাংশন রয়েছে, সুতরাং সরাসরি অপ্টিমাইজেশনের জন্য প্রচুর স্মৃতি এবং সময় প্রয়োজন। আমি যা করেছি তা হ'ল 4 বিট থেকে শুরু করে 1 বিট পর্যন্ত 4 টি ফাংশন বিবেচনা করা, যে কোনও একটি ক্রিয়াকলাপের জন্য অনুমোদিত মোট ব্যয়ের উপর একটি ক্যাপ রাখুন (ফাংশন প্রতি সর্বাধিক ব্যয় সহ আমি এক মিনিটের মধ্যে সমস্ত উপযুক্ত অভিব্যক্তি গণনা করতে পারি), এবং ফাংশন প্রতিটি tuple জন্য সাধারণ subexpression নির্মূল। ক্র্যাঞ্চিংয়ের 25 মিনিটের পরে, আমি দেখতে পেলাম যে ক্যাপটির সাথে সর্বোত্তম বিপরীতমুখীতার মোট ব্যয় 133 (আউটপুট বিট প্রতি গড়ে 33.25, যা কোনও ব্যক্তি বিটের জন্য সস্তারতম এক্সপ্রেশন 35 বলে বিবেচনা করে খারাপ নয়) ।

আমি এখনও জিএফ (2 ^ 4) এর বিপর্যয় হ্রাস করার জন্য অন্যান্য পদ্ধতির সাথে পরীক্ষা নিরীক্ষা করছি এবং টপ-ডাউনের চেয়ে ডাউন-আপ তৈরির একটি পদ্ধতির 133 থেকে 126 এর উন্নতি হয়েছে।


ফ্যান্টাস্টিক! আমি নিশ্চিত এটি কাজ করে! বিশদ: 8 মটি & 1ছাঁটাই করা যেতে পারে (উদাহরণস্বরূপ যদি xহয় unsigned char; CHAR_BITকোডগল্ফে 8 হয়)।
fgrieu

@ ফগ্রিউ, ভাল কথা।
পিটার টেলর

8

স্কোর: 980 = 7 * 5 + 115 * 7 + 7 * 5 + 15 * 7, বায়ার এবং পেরাল্টার মিনিমাইজেশন

আমি জোয়ান বোয়ার এবং রেনা পেরাল্টার ক্রিপ্টোলজির অ্যাপ্লিকেশনগুলির সাথে একটি নতুন যুক্ত যৌক্তিক যুক্তি হ্রাস করার কৌশলটি পেয়েছি , যা (সি ফর্মালিজমের জন্য সংরক্ষণ করা) যা প্রয়োজন তা করে। তাদের সমীকরণগুলি অর্জন করতে ব্যবহৃত কৌশলটি আমেরিকা যুক্তরাষ্ট্রের চেয়ে কম নয় aten আমি কেবল তাদের সমীকরণের একটি সরাসরি সি অনুবাদ করেছি , দয়া করে এখানে লিঙ্কযুক্ত ।

unsigned char SubBytes_Boyar_Peralta(unsigned char x7){
  unsigned char 
  x6=x7>>1,x5=x6>>1,x4=x5>>1,x3=x4>>1,x2=x3>>1,x1=x2>>1,x0=x1>>1,
  y14=x3^x5,y13=x0^x6,y9=x0^x3,y8=x0^x5,t0=x1^x2,y1=t0^x7,y4=y1^x3,y12=y13^y14,y2=y1^x0,
  y5=y1^x6,y3=y5^y8,t1=x4^y12,y15=t1^x5,y20=t1^x1,y6=y15^x7,y10=y15^t0,y11=y20^y9,y7=x7^y11,
  y17=y10^y11,y19=y10^y8,y16=t0^y11,y21=y13^y16,y18=x0^y16,t2=y12&y15,t3=y3&y6,t4=t3^t2,
  t5=y4&x7,t6=t5^t2,t7=y13&y16,t8=y5&y1,t9=t8^t7,t10=y2&y7,t11=t10^t7,t12=y9&y11,
  t13=y14&y17,t14=t13^t12,t15=y8&y10,t16=t15^t12,t17=t4^t14,t18=t6^t16,t19=t9^t14,
  t20=t11^t16,t21=t17^y20,t22=t18^y19,t23=t19^y21,t24=t20^y18,t25=t21^t22,t26=t21&t23,
  t27=t24^t26,t28=t25&t27,t29=t28^t22,t30=t23^t24,t31=t22^t26,t32=t31&t30,t33=t32^t24,
  t34=t23^t33,t35=t27^t33,t36=t24&t35,t37=t36^t34,t38=t27^t36,t39=t29&t38,t40=t25^t39,
  t41=t40^t37,t42=t29^t33,t43=t29^t40,t44=t33^t37,t45=t42^t41,z0=t44&y15,z1=t37&y6,
  z2=t33&x7,z3=t43&y16,z4=t40&y1,z5=t29&y7,z6=t42&y11,z7=t45&y17,z8=t41&y10,z9=t44&y12,
  z10=t37&y3,z11=t33&y4,z12=t43&y13,z13=t40&y5,z14=t29&y2,z15=t42&y9,z16=t45&y14,z17=t41&y8,
  t46=z15^z16,t47=z10^z11,t48=z5^z13,t49=z9^z10,t50=z2^z12,t51=z2^z5,t52=z7^z8,t53=z0^z3,
  t54=z6^z7,t55=z16^z17,t56=z12^t48,t57=t50^t53,t58=z4^t46,t59=z3^t54,t60=t46^t57,
  t61=z14^t57,t62=t52^t58,t63=t49^t58,t64=z4^t59,t65=t61^t62,t66=z1^t63,s0=t59^t63,
  s6=t56^t62,s7=t48^t60,t67=t64^t65,s3=t53^t66,s4=t51^t66,s5=t47^t65,s1=t64^s3,s2=t55^t67;
  return (((((((s0<<1|s1&1)<<1|s2&1)<<1|s3&1)<<1|s4&1)<<1|s5&1)<<1|s6&1)<<1|s7&1)^0x63;}

বাহ, সত্যিই কাজ করে এবং সত্যই সস্তা। বিচ্ছিন্ন করার সময়, এটি প্রজ্ঞা, এপিলোগি এবং সরানোর নির্দেশাবলী ব্যতীত 144 টি নির্দেশাবলী।
ugoren

5

স্কোর: 10965

এটি অ্যারে লুকিয়ালটিকে আনرول করার একই নীতিটি ব্যবহার করে। অতিরিক্ত ক্যাসেটের প্রয়োজন হতে পারে।

কীভাবে উন্নতি করতে হবে তা নির্দেশ করার জন্য উগোরেনকে ধন্যবাদ is_zero

// Cost: 255 * (5+7+24+7) = 10965
unsigned char SubBytes(unsigned char x) {
    unsigned char r = 0x63;
    char c = (char)x;
    c--; r ^= is_zero(c) & (0x63^0x7c); // 5+7+24+7 inlining the final xor
    c--; r ^= is_zero(c) & (0x63^0x77); // 5+7+24+7
    // ...
    c--; r ^= is_zero(c) & (0x63^0x16); // 5+7+24+7
    return r;
}

// Cost: 24
// Returns (unsigned char)-1 when input is 0 and 0 otherwise
unsigned char is_zero(char c) {
    // Shifting a signed number right is unspecified, so use unsigned
    unsigned char u;
    c |= -c;               // 7+5+
    u = (unsigned char)c;
    u >>= (CHAR_BITS - 1); // 7+
    c = (char)u;
    // c is 0 if we want -1 and 1 otherwise.
    c--;                   // 5
    return (unsigned char)c;
}

2
একটি পূর্ণসংখ্যা সি এর (c|-c)>>31জন্য 0 এবং অন্যথায় -1 হয়।
ugoren

@ ইউগেরেন, বোধগম্য ভাষায়, হ্যাঁ। সি-তে, স্বাক্ষরবিহীন প্রকারের ডান স্থানান্তর অনির্দিষ্ট।
পিটার টেলর

1
আমার ধারণা আপনি স্বাক্ষরিত মানে। তবে এই সাইটটি কঠোর মানক সম্মতির জন্য সত্যই বিখ্যাত নয়। এছাড়াও, আপনার c >> 4কাছে আমার কাছে স্বাক্ষর করা ডান শিফটের মতো মনে হচ্ছে। এবং যদি আপনি সত্যিই জেদ - ((unsigned int)(c|-c))>>31হয় c?1:0
ugoren

@ ইউগোরেন, আপনি ঠিক বলেছেন, আমি স্বাক্ষর করেছি। c >>4সহ বা চিহ্ন এক্সটেনশন ছাড়া কাজ করে। তবে স্বাক্ষরবিহীন শিফটটি ব্যবহার করার বিষয়ে ভাল ধারণা: আমি বাড়ি এলে সম্পাদনা করব এবং ফোনটির পরিবর্তে একটি উপযুক্ত কম্পিউটার ব্যবহার করতে পারি। ধন্যবাদ।
পিটার টেলর

3

স্কোর: 9109, বীজগণিত পদ্ধতি

কেউ যদি এটিকে তীব্রভাবে উন্নতি করতে পারে তবে আমি অনুসন্ধানের পদ্ধতিটি ছেড়ে দেব, তবে এটি প্রমাণিত হয়েছে যে একটি ভাল বীজগণিত পদ্ধতি সম্ভব is এই প্রয়োগটি ইউক্লিডের অ্যালগরিদম ব্যবহার করে গুণক বিপরীতটি আবিষ্কার করে । আমি এটি জাভাতে লিখেছি কিন্তু নীতিগতভাবে এটি সিতে পোর্ট করা যেতে পারে - আমি কেবলমাত্র 8-বিট প্রকারের সাহায্যে পুনরায় কাজ করতে চাইলে যে অংশগুলি পরিবর্তন হবে তা আমি মন্তব্য করেছি।

is_nonzeroআমার অন্যান্য উত্তরের মন্তব্যে চেকটি কীভাবে সংক্ষিপ্ত করবেন তা নির্দেশ করার জন্য উগ্রেনকে ধন্যবাদ Thanks

public class SBox
{
    public static void main(String[] args)
    {
        for (int i = 0; i < 256; i++) {
            int s = SubBytes(i);
            System.out.format("%02x  ", s);
            if (i % 16 == 15) System.out.println();
        }
    }

    // Total cost: 9109
    public static int SubBytes(int x)
    {
        x = inv_euclid(x); // 9041
        x = affine(x);     // 68
        return x;
    }

    // Total cost: 68
    private static int affine(int s0) {
        int s = s0;
        s ^= (s0 << 1) ^ (s0 >> 7); // 5 + 7
        s ^= (s0 << 2) ^ (s0 >> 6); // 7 + 7
        s ^= (s0 << 3) ^ (s0 >> 5); // 7 + 7
        s ^= (s0 << 4) ^ (s0 >> 4); // 7 + 7
        return (s ^ 0x63) & 0xff;   // 7 + 7
    }

    // Does the inverse in the Galois field for a total cost of 24 + 9010 + 7 = 9041
    private static int inv_euclid(int s) {
        // The first part of handling the special case: cost of 24
        int zeromask = is_nonzero(s);

        // NB the special value of r would complicate the unrolling slightly with unsigned bytes
        int r = 0x11b, a = 0, b = 1;

        // Total cost of loop: 7*(29+233+566+503+28) - 503 = 9010
        for (int depth = 0; depth < 7; depth++) { // 7*(
            // Calculate mask to fake out when we're looping further than necessary: cost 29
            int mask = is_nonzero(s >> 1);

            // Cost: 233
            int ord = polynomial_order(s);

            // This next block does div/rem at a total cost of 6*(24+49) + 69 + 59 = 566
            int quot = 0, rem = r;
            for (int i = 7; i > 1; i--) {                   // 6*(
                int divmask = is_nonzero(ord & (rem >> i)); // 24+7+7
                quot ^= (1 << i) & divmask;                 // 7+0+7+ since 1<<i is inlined on unrolling
                rem ^= (s << i) & divmask;                  // 7+7+7) +
            }
            int divmask1 = is_nonzero(ord & (rem >> 1));    // 24+7+5
            quot ^= 2 & divmask1;                           // 7+7+
            rem ^= (s << 1) & divmask1;                     // 7+5+7+
            int divmask0 = is_nonzero(ord & rem);           // 24+7
            quot ^= 1 & divmask0;                           // 7+7+
            rem ^= s & divmask0;                            // 7+7

            // This next block does the rest for the cost of a mul (503) plus 28
            // When depth = 0, b = 1 so we can skip the mul on unrolling
            r = s;
            s = rem;
            quot = mul(quot, b) ^ a;
            a = b;
            b ^= (quot ^ b) & mask;
        }

        // The rest of handling the special case: cost 7
        return b & zeromask;
    }

    // Gets the highest set bit in the input. Assumes that it's always at least 1<<1
    // Cost: 233
    private static int polynomial_order(int s) {
        int ord = 2;
        ord ^= 6 & -((s >> 2) & 1);           // 7+7+5+7+7 = 33 +
        ord ^= (ord ^ 8) & -((s >> 3) & 1);   // 7+7+7+5+7+7 = 40 +
        ord ^= (ord ^ 16) & -((s >> 4) & 1);  // 40 +
        ord ^= (ord ^ 32) & -((s >> 5) & 1);  // 40 +
        ord ^= (ord ^ 64) & -((s >> 6) & 1);  // 40 +
        ord ^= (ord ^ 128) & -((s >> 7) & 1); // 40
        return ord;
    }

    // Returns 0 if c is 0 and -1 otherwise
    // Cost: 24
    private static int is_nonzero(int c) {
        c |= -c;   // 7+5+
        c >>>= 31; // 7+ (simulating a cast to unsigned and right shift by CHAR_BIT)
        c = -c;    // 5+ (could be saved assuming a particular implementation of signed right shift)
        return c;
    }

    // Performs a multiplication in the Rijndael finite field
    // Cost: 503 (496 if working with unsigned bytes)
    private static int mul(int a, int b) {
        int p = 0;
        for (int counter = 0; counter < 8; counter++) { // 8*(_+_
            p ^= a & -(b & 1);                          // +7+7+5+7
            a = (a << 1) ^ (0x1b & -(a >> 7));          // +5+7+7+5+7
            b >>= 1;                                    // +5)
        }
        p &= 0xff;                                      // +7 avoidable with unsigned bytes
        return p;
    }
}

2

স্কোর: 256 * (7+ (8 * (7 + 7 + 7) - (2 + 2)) + 5 + 7 + 7) = 48640 (লুপগুলি নিবন্ধভুক্ত ধরে নিয়েছে)

unsigned char SubBytes(unsigned char x) {
static const unsigned char t[256] = {
  0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
  0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
  0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
  0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
  0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
  0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
  0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
  0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
  0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
  0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
  0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
  0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
  0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
  0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
  0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
  0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16};

unsigned char ret_val = 0;
int i,j;
for(i=0;i<256;i++) {
  unsigned char is_index = (x ^ ((unsigned char) i));
  for(j=0;j<8;j++) {
   is_index |= (is_index << (1 << j)) | (is_index >> (1 << j));
  }
  is_index = ~is_index;
  ret_val |= is_index & t[i];
}

return ret_val;}

ব্যাখ্যা:

মূলত বিটওয়াইস অপারেটরগুলি ব্যবহার করে এবং সর্বদা পুরো অ্যারে প্রক্রিয়াকরণ করে একটি অ্যারে লুকআপ পুনরায় প্রয়োগ করা হয়। আমরা অ্যারের মধ্য দিয়ে লুপ করি এবং xপ্রতিটি সূচকের সাথে জোর করি , তারপরে ফলাফলটিকে যুক্তিযুক্তভাবে উপেক্ষা করার জন্য বিটওয়াইস অপারেটরগুলি ব্যবহার করি, সুতরাং আমরা কখন 255 x=iএবং অন্যথায় 0 পাই । আমরা বিটওয়াইস-এবং এটি অ্যারে-মান সহ, যাতে নির্বাচিত মানটি অপরিবর্তিত হয় এবং অন্যগুলি 0 হয়ে যায় we তারপরে আমরা বিটওয়াইস-বা এই অ্যারেটি গ্রহণ করি, যার ফলে কেবলমাত্র নির্বাচিত মানটি টেনে আনা হয়।

দুটি 1 << jক্রিয়াকলাপটি লুপটি আনলোল করার অংশ হিসাবে চলে যাবে, তাদের পরিবর্তে 1 থেকে 128 এর মধ্যে 2 এর ক্ষমতা দিয়ে।


এখন দেখার জন্য বিটওয়াইড অপারেটরগুলি ব্যবহার করে গণিতটি করা সম্ভব কিনা actually
হিস্টোক্র্যাট

এখানে অ্যালগরিদমটি দেখে , আমার সন্দেহ রয়েছে যে বহুবর্ষীয় সময়ের কিছু পদক্ষেপের বিকল্প হিসাবে কমপক্ষে একবারে সমস্ত বাইটের উপরে লুপিং ছাড়াই বহুপক্ষীয় বিপর্যয় বাস্তবায়ন করা সম্ভব হবে। সুতরাং এটি কোনও "স্মার্ট" সমাধানগুলিকে ভালভাবে পরাজিত করতে পারে। আমি সন্দেহ করি যে এই ধ্রুবক-সময়ের অ্যারে লুকআপটি আরও আশাব্যঞ্জক অ্যাভিনিউ is
হিস্টোক্র্যাট

খুশী হলাম। Aes.c ফাংশন rj_sbox এখানে অনুপ্রেরণা দিতে পারে (যদিও, হয়, এটা প্রশ্নের সাথে মিলছে না)।
fgrieu

কোথায় -(2+2)আপনার স্কোরিং হিসাব থেকে এসেছে? সম্পাদনা: আহ, ইনলাইনিং একটি <<1এবং একটি তৈরি করে >>1
পিটার টেলর

0

স্কোর 1968 1692, অনুসন্ধান সারণী ব্যবহার করে

দ্রষ্টব্য: এই সমাধানটির কারণে মানদণ্ডগুলি পাস হয় না w >> b

লুক টেবিল ব্যবহার করে, তবে একসাথে 8 বাইট পড়া।
3 * 7 + 32 * (6 * 7 + 2 * 5) + 7 = 692

unsigned char SubBytes(unsigned char x){

static const unsigned char t[256] = {
  0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
  0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
  0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
  0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
  0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
  0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
  0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
  0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
  0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
  0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
  0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
  0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
  0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
  0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
  0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
  0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16};

  unsigned long long *t2 = (unsigned long long *)t;
  int a = x>>3, b=(x&7)<<3;                       // 7+7+7
  int i;
  int ret = 0;
  for (i=0;i<256/8;i++) {                         // 32 *
      unsigned long long w = t2[i];
      int badi = ((unsigned int)(a|-a))>>31;      // 7+7+5
      w &= (badi-1);                              // +7+7
      a--;                                        // +5
      ret |= w >> b;                              // +7+7
  }
  return ret & 0xff;                              // +7
}

আমি মনে করি না যে এটি প্রশ্নের ধ্রুবক সময়ের সংজ্ঞা পূরণ করে, কারণ w>>bআরএইচএস থেকে গণনা করা হয়েছেx
পিটার টেলর

বেশ কয়েকটি লঙ্ঘন আছে: w >> bযেখানেb ইনপুট নির্ভর করে; এছাড়াও x/8, x%8এবং *= (1-badi)। প্রথমটি বিশেষত নিম্ন-প্রান্তের সিপিইউতে সময় নির্ভরতাতে অধঃপতিত হতে পারে। তবে বিস্তৃত ভেরিয়েবল ব্যবহারের ধারণার অবশ্যই সম্ভাবনা রয়েছে।
fgrieu

আমি নির্দেশাবলী যথেষ্ট পরিমাণে পড়িনি। আমি বেশিরভাগ সমস্যার ঠিক করতে পারবো, কিন্তু w >> bবেশ অপরিহার্য (আমি দেখতে প্রয়োজন হলে সবকিছু rewriting ছাড়া সংশোধন করা যেতে পারে।
ugoren

0

সারণী সন্ধান এবং মাস্ক, স্কোর = 256 * (5 * 7 + 1 * 5) = 10240

কেবলমাত্র আমরা চাই ফলাফলটি বের করতে একটি মুখোশ সহ টেবিল লুকআপ ব্যবহার করে। সত্য যে ব্যবহার j|-jহয় নেতিবাচক (যখন আমি! = X) এর বা শূন্য (যখন আমি == এক্স)। শিফটিং একটি অল-ওয়ান বা অল-জিরো মাস্ক তৈরি করে যা কেবল আমাদের পছন্দসই প্রবেশটি নির্বাচন করতে ব্যবহৃত হয়।

static const unsigned char t[256] = {
  0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
  0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
  0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
  0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
  0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
  0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
  0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
  0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
  0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
  0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
  0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
  0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
  0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
  0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
  0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
  0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16};

unsigned char SubBytes(unsigned char x) {
  unsigned char r = 255;
  for (int i = 0; i < 256; i++) {
    int j = i - x;
    r &= t[i] | ((j | -j) >> 31);
  }
  return r;
}

এটি কি কম অপ্টিমাইজড বাদে আমার দ্বিতীয় উত্তরটির মতো নয়?
পিটার টেলর

বন্ধ, আমার ধারণা। আমি স্বাক্ষরিত শিফটটি ব্যবহার করছি যাতে আমাকে শেষে -1 করতে হবে না।
কিথ র্যান্ডাল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.