রিজান্ডেলের এস-বাক্সটি কার্যকর করুন


15

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

আপনার প্রিয় ভাষায় একটি ফাংশন লিখুন যা রিজান্ডেলের এস-বাক্স কার্যকর করে। সংক্ষিপ্ততম কোড জিতেছে।


1
বোনাস পয়েন্টগুলি (আমার কাছ থেকে আপটোটস) যদি ফলাফলের ক্রিয়াটি ধ্রুবক সময় হয় (যেমন কোনও ডেটা নির্ভর-ভিত্তিক কোড পাথ বা অ্যারে অ্যাক্সেস বা আপনার ভাষা যা সমর্থন করে)।
পাওলো ইবারম্যান

@ পাওলোবারম্যান অ্যারে অ্যাক্সেসগুলি বহু ভাষায় অবিচ্ছিন্ন সময় হয় (এটি একটি পয়েন্টারের কাছে একটি (স্কেলড) মান যুক্ত করে এটির নিরঙ্কুশ করে, এ কারণেই একটি সন্ধানের টেবিলটি খুব দ্রুত)
র্যাচেট ফ্রেইক

@ratchetfreak অ্যারে অ্যাক্সেসগুলি হ'ল ও (1), তবে আসল অ্যাক্সেসের সময় ক্যাশে হিট বা মিসের উপর নির্ভর করে, উদাহরণস্বরূপ, যা এইএস-তে চ্যানেল-চক্রের আক্রমণকে বাড়ে।
পাওলো ইবারম্যান

@ PaŭloEbermann, তবে আপনি একটি অনুসন্ধানের টেবিলটি পূরণ করতে সংক্ষিপ্ত কোডটি ব্যবহার করতে পারেন যা মেমরির একটি পৃষ্ঠার নীচে পরে উপযুক্ত in
পিটার টেলর

@ পাওলোবার্মান এবং যদি 256 দৈর্ঘ্যের টেবিলটি কোডের সাথে সংরক্ষণ করা হয় (সংকলনের সময় উত্পন্ন এনাম হিসাবে) আপনি প্রায় ক্যাশে হিটের নিশ্চয়তা দিয়েছেন
র‌্যাচেট ফ্রিক

উত্তর:


6

রুবি, 161 টি অক্ষর

R=0..255
S=R.map{|t|t=b=R.select{|y|x=t;z=0;8.times{z^=y*(x&1);x/=2;y*=2};r=283<<8;8.times{r/=2;z^r<z/2&&z^=r};z==1}[0]||0;4.times{|r|t^=b<<1+r^b>>4+r};t&255^99}

আউটপুটটি পরীক্ষা করতে আপনি নীচের কোডটি এটিকে টেবুলার আকারে মুদ্রণের জন্য ব্যবহার করতে পারেন:

S.map{|x|"%02x"%x}.each_slice(16){|l|puts l*' '}

7

গল্ফস্ক্রিপ্ট, 60 টি অক্ষর

{[[0 1{.283{1$2*.255>@*^}:r~^}255*].@?~)={257r}4*99]{^}*}:S;

এই কোডটি একটি ফাংশনটিকে সংজ্ঞায়িত করে Sযা একটি বাইট নেয় এবং এতে রিজান্ডেল এস-বাক্স প্রয়োগ করে। (এটি rকয়েকটি অক্ষর সংরক্ষণের জন্য নামের একটি অভ্যন্তরীণ সহায়তা ফাংশনও ব্যবহার করে ))

টমাস পর্নিনের পরামর্শ অনুসারে এই প্রয়োগটি জিএফ (2 8 ) বিপরীত গণনা করতে লোগারিথম টেবিল ব্যবহার করে । কয়েকটি অক্ষর সংরক্ষণ করতে, প্রতিটি লগ ইনকাম বাইটের জন্য পুরো লোগারিদম টেবিলটি পুনরায় গণনা করা হয়; তবুও, এবং গল্ফস্ক্রিপ্ট সাধারণভাবে খুব ধীর ভাষা হওয়া সত্ত্বেও, এই কোডটি আমার পুরানো ল্যাপটপটিতে একটি বাইট প্রসেস করতে প্রায় 10 এমএস লাগে। লোগারিদম টেবিলকে প্রাক্কলিতকরণ (যেমন L) আরও তিনটি অক্ষরের ব্যয়বহুল ব্যয়ে এটি প্রতি বাইট প্রতি 0.5 মাইল গতিবেগ করে:

[0 1{.283{1$2*.255>@*^}:r~^}255*]:L;{[L?~)L={257r}4*99]{^}*}:S;

সুবিধার্থে, এখানে একটি সাধারণ পরীক্ষার জোতা যা Sউপরের সংজ্ঞায়িত হিসাবে ফাংশনটিকে কল করে , উইকিপিডিয়ায় পছন্দ করে পুরো এস-বাক্সটি হেক্সে প্রিন্ট করতে :

"0123456789abcdef"1/:h; 256, {S .16/h= \16%h= " "++ }% 16/ n*

এই কোডটি অনলাইনে চেষ্টা করে দেখুন।

(খুব বেশি সময় না নিরূপণে অনলাইন ডেমো লোগারিথম টেবিলকে প্রাক্কলিত করে Even তবুও, অনলাইন গল্ফস্ক্রিপ্ট সাইটটি মাঝে মাঝে এলোমেলোভাবে সময় শেষ করতে পারে; এটি সাইটের সাথে একটি পরিচিত সমস্যা এবং একটি পুনরায় লোড সাধারণত এটি ঠিক করে দেয়))

ব্যাখ্যা:

আসুন লগারিদম টেবিল গণনা এবং বিশেষত সহায়ক ফাংশন দিয়ে শুরু করুন r:

{1$2*.255>@*^}:r

এই ফাংশনটি স্ট্যাকের দুটি ইনপুট নেয়: একটি বাইট এবং হ্রাস বিটমাস্ক (256 এবং 511 এর মধ্যে একটি ধ্রুবক)। এটি ইনপুট বাইটটিকে সদৃশ করে, অনুলিপিটিকে 2 দ্বারা গুণিত করে এবং ফলাফলটি 255 ছাড়িয়ে যায়, বিটমাস্কের সাহায্যে এটি এক্সওর করে এটি 256 এর নীচে ফিরিয়ে আনতে।

লগ-টেবিল উত্পন্ন কোডের মধ্যে, ফাংশনটি rহ্রাস বিটমাস্ক 283 = 0x11b (যা রিজান্ডেল জিএফ (2 8 ) হ্রাস বহুপদী x 8 + x 4 + x 3 + x + 1) এর সাথে ডাকা হয় এবং ফলাফলটি XORed হয় আসল বাইট সহ, কার্যকরভাবে এটিকে 3 (= x + 1, একটি বহুবর্ষ হিসাবে) রিজান্ডেল সসীম ক্ষেত্রে। এই গুণটি বাইট 1 থেকে শুরু করে 255 বার পুনরাবৃত্তি হয় এবং ফলাফলগুলি (একটি প্রাথমিক শূন্য বাইট) 257-উপাদান অ্যারেতে সংগ্রহ করা হয় Lযা দেখতে এটির (মাঝের অংশ বাদ দেওয়া):

[0 1 3 5 15 17 51 85 255 26 46 ... 180 199 82 246 1]

257 টি উপাদান রয়েছে তার কারণ হ'ল, প্রেনপেন্ড 0 এবং 1 এর সাথে দু'বার ঘটছে, আমরা প্রদত্ত যে কোনও বাইটের মডুলার ইনভার্সটি কেবলমাত্র এই অ্যারেটিতে তার (শূন্য-ভিত্তিক) সূচীটি অনুসন্ধান করে, এটিকে অবহেলা করে এবং সন্ধান করতে পারি একই অ্যারে অবহেলিত সূচীতে বাইট আপ করুন। (গল্ফস্ক্রিপ্টে, অন্যান্য অনেক প্রোগ্রামিং ভাষার মতো, নেগেটিভ অ্যারে সূচকগুলি অ্যারের প্রান্ত থেকে পিছনের দিকে গণনা করে)) প্রকৃতপক্ষে, L?~)L=ফাংশনের শুরুতে কোডটি ঠিক এটিই Sকরে।

উল্টানো ইনপুট বাইটের চার বিট-ঘোরানো অনুলিপি তৈরি করতে বাকী কোডটি rহ্রাস বিটমাস্ক 257 = 2 8 + 1 এর সাহায্যে চারবার সহায়তা ফাংশনকে কল করে । এগুলি সমস্ত ধীরে ধীরে 99 = 0x63 এর সাথে একত্রে সংগ্রহ করা হয় এবং চূড়ান্ত আউটপুট উত্পাদনের জন্য একসাথে XORed করা হয়।


7

x86-64 মেশিন কোড - 23 22 20 19 বাইট

AES-NI নির্দেশিকা সেট ব্যবহার করে

66 0F 6E C1          movd        xmm0,ecx
66 0F 38 DD C1       aesenclast  xmm0,xmm1
0F 57 C1             xorps       xmm0,xmm1  
66 0F 3A 14 C0 00    pextrb      eax,xmm0,0
C3                   ret

উইন্ডোজ কলিং কনভেনশনগুলি ব্যবহার করে, একটি বাইট নেয় এবং একটি বাইট আউটপুট দেয়। এটি ShiftRowsপ্রথম বাইট প্রভাবিত করে না কারণ এটি বিপরীত করা প্রয়োজন হয় না।


2
একবারের জন্য, x86_64 একটি গণিতকে টেনে নিয়েছে এবং এর জন্য একটি বিল্টিন রয়েছে।
moonheart08

6

লগারিদম ব্যবহার করে সীমাবদ্ধ ক্ষেত্র জিএফ (256) এ বিপরীতে গণনা ছাড়াই টেবিলটি তৈরি করা যেতে পারে। এটি দেখতে (জাভা কোড, intস্বাক্ষরিত byteধরণের সমস্যাগুলি এড়াতে ব্যবহার করে ) এর মতো দেখাবে :

int[] t = new int[256];
for (int i = 0, x = 1; i < 256; i ++) {
    t[i] = x;
    x ^= (x << 1) ^ ((x >>> 7) * 0x11B);
}
int[] S = new int[256];
S[0] = 0x63;
for (int i = 0; i < 255; i ++) {
    int x = t[255 - i];
    x |= x << 8;
    x ^= (x >> 4) ^ (x >> 5) ^ (x >> 6) ^ (x >> 7);
    S[t[i]] = (x ^ 0x63) & 0xFF;
}

ধারণাটি হ'ল 3 হ'ল জিএফ (256) * এর গুণক জেনারেটর। টেবিলটি t[]এমন যা t[x]3 x এর সমান ; 3 255 = 1 থেকে, আমরা সেই 1 / (3 x ) = 3 255-x পাই ।


এটি 0x1B(হেক্স আক্ষরিক এক 1) এর পরিবর্তে হওয়া উচিত নয়0x11B
ratchet freak

@ আর্টচেটফ্রাক: না, এটি অবশ্যই 0x11 বি হতে হবে (আমি চেষ্টা করেছি)। intটাইপ জাভা 32 বিট হয়; আমি উচ্চতর বিট বাতিল করতে হবে।
টমাস পর্নিন

আহ তা বুঝতে পারেনি
রাচেট ফ্রিক

4 নং লাইনে এটি >>> এর পরিবর্তে >>>?
জো জেড।

@ জোজেং: দু'জনেই কাজ করবে। জাভাতে '>>>' হ'ল "স্বাক্ষরযুক্ত শিফট", '>>' হ'ল "স্বাক্ষরিত শিফট"। তারা কীভাবে সাইন বিট পরিচালনা করে তা দ্বারা পৃথক। এখানে, সাইন বিটটি শূন্য -হীন হওয়ার জন্য মানগুলি কখনই যথেষ্ট প্রশস্ত হবে না, সুতরাং এটি কোনও বাস্তব পার্থক্য করে না।
টমাস পর্নিন

6

গল্ফস্ক্রিপ্ট (৮২ টি চর)

{256:B,{0\2${@1$3$1&*^@2/@2*.B/283*^}8*;;1=},\+0=B)*:A.2*^4A*^8A*^128/A^99^B(&}:S;

গ্লোবাল ভেরিয়েবল Aএবং ব্যবহার Bকরে এবং গ্লোবাল ভেরিয়েবল হিসাবে ফাংশন তৈরি করে S

গ্যালোয়াই উল্টানো নিষ্ঠুর-শক্তি; আমি একটি পৃথক mulফাংশন নিয়ে পরীক্ষা-নিরীক্ষা করেছি যা বিবর্তন-পরবর্তী অ্যাফাইন ট্রান্সফর্মের জন্য পুনরায় ব্যবহার করা যেতে পারে তবে ভিন্ন ওভারফ্লো আচরণের কারণে এটি আরও ব্যয়বহুল হয়ে উঠেছে।

এটি একটি অনলাইন ডেমোর জন্য খুব ধীর - এটি টেবিলের প্রথম দুটি সারিতেও শেষ হয়ে যাবে।


খনি দ্রুত (এবং সংক্ষিপ্ত;)। যাইহোক, +1।
ইলমারি করোনেন

4

পাইথন, 176 অক্ষর

এই উত্তরটি হ'ল ফাংশনটি ধ্রুবক সময় তৈরির বিষয়ে পাওলো ইবারম্যানের মন্তব্য-প্রশ্নের জন্য। এই কোডটি বিল ফিট করে।

def S(x):
 i=0
 for y in range(256):
  p,a,b=0,x,y
  for j in range(8):p^=b%2*a;a*=2;a^=a/256*283;b/=2
  m=(p^1)-1>>8;i=y&m|i&~m
 i|=i*256;return(i^i/16^i/32^i/64^i/128^99)&255

গুণটি স্থির-সময় হওয়া প্ল্যাটফর্ম নির্ভর (এমনকি 32-বিট প্ল্যাটফর্মগুলিতে যেমন, এআরএম কর্টেক্স এম0)। এই সম্পর্কিত প্রশ্নটি দেখুন
fgrieu

1
@ এফগ্রিউ শিওর, তবে এগুলি ধ্রুবক দ্বারা সমস্ত গুণ, যা শিফট এবং সংযোজনগুলি ব্যবহার করে ধ্রুব সময়ে সহজেই প্রয়োগ করা যেতে পারে।
কিথ র্যান্ডাল

2

ubyte[256] getLookup(){

    ubyte[256] t=void;
    foreach(i;0..256){
        t[i] = x;
        x ^= (x << 1) ^ ((x >>> 7) * 0x1B);
    }
    ubyte[256] S=void;
    S[0] = 0x63;
    foreach(i;0..255){
        int x = t[255 - i];
        x |= x << 8;
        x ^= (x >> 4) ^ (x >> 5) ^ (x >> 6) ^ (x >> 7);
        S[t[i]] = cast(ubyte)(x & 0xFF) ^ 0x63 ;
    }
    return S;

}

এটি সংকলনের সময় অনুসন্ধানের টেবিলটি তৈরি করতে পারে, আমি ইউবিটকে জেনেরিক প্যারাম তৈরি করে কিছু সঞ্চয় করতে পারি

সম্পাদন করা নির্দেশ ubyteকরার ubyteঅ্যারের লুক-ছাড়া, কোন শাখাবিন্যাস এবং সম্পূর্ণরূপে unrollable লুপ

B[256] S(B:ubyte)(B i){
    B mulInv(B x){
        B r;
        foreach(i;0..256){
            B p=0,h,a=i,b=x;
            foreach(c;0..8){
                p^=(b&1)*a;
                h=a>>>7;
                a<<=1;
                a^=h*0x1b;//h is 0 or 1
                b>>=1;
            }
            if(p==1)r=i;//happens 1 or less times over 256 iterations
        }
        return r;
    }
    B s= x=mulInv(i);
    foreach(j,0..4){
        x^=(s=s<<1|(s>>>7));
    }
    return x^99;
}

edit2 অনুসন্ধান টেবিল তৈরি করার জন্য @ থমাসের আলগো ব্যবহার করেছেন


0

স্ট্যাক্স , 53 বাইট

ë■ÿÆ♂◄º5hUø√!«mr¿¡ƒR3Å←ç≥#/$taJkαn∩╓▒ÿ╔τy╫π§╪S♫╔┴H╔║Ö

এটি চালান এবং এটি ডিবাগ করুন

এস-বাক্স সম্পর্কে আমার বিশেষ ধারণা নেই। এটি টমাস পর্নিনের (8 বছর বয়সী!) সমাধানের রূপান্তর ।

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