रिजंडल के एस-बॉक्स को लागू करें


15

रिजेंडेल का एस-बॉक्स एईएस एन्क्रिप्शन और डिक्रिप्शन में अक्सर इस्तेमाल किया जाने वाला ऑपरेशन है । यह आमतौर पर 256-बाइट लुकअप टेबल के रूप में लागू किया जाता है। यह तेज़ है, लेकिन इसका मतलब है कि आपको अपने कोड में 256-बाइट लुकअप टेबल की गणना करनी होगी। मैं शर्त लगाता हूं कि इस भीड़ में कोई इसे कम कोड के साथ कर सकता है, अंतर्निहित गणितीय संरचना को देखते हुए।

अपनी पसंदीदा भाषा में एक फ़ंक्शन लिखें जो रिजेंडेल के एस-बॉक्स को लागू करता है। सबसे छोटा कोड जीतता है।


1
बोनस अंक (मुझ से upvotes) यदि परिणामी फ़ंक्शन निरंतर-समय है (अर्थात कोई डेटा-निर्भर कोड पथ या सरणी एक्सेस या आपकी भाषा जो भी समर्थन करती है)।
पाओलो एबरमन

@ Pa @loEbermann सरणी अभिगम कई भाषाओं में लगातार समय होता है (यह एक सूचक में एक (स्केल किया गया) मान जोड़ रहा है और इसे dereferencing कर रहा है, यही कारण है कि एक लुकअप तालिका बहुत तेज़ है)
शाफ़्ट सनकी

@ratchetfreak एरे एक्सेस ओ (1) हैं, लेकिन वास्तविक एक्सेस समय कैश हिट्स या मिस पर निर्भर करता है, उदाहरण के लिए, जो एईएस पर साइड-चैनल हमलों की ओर जाता है।
पाओलो एबरमन

@ Pa @loEbermann, लेकिन आप लुकअप टेबल को भरने के लिए छोटे कोड का उपयोग कर सकते हैं, जो तब मेमोरी के एक पेज के नीचे अच्छी तरह से फिट होगा।
पीटर टेलर

@ Pa @loEbermann और यदि 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

GolfScript, 60 अक्षर

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

यह कोड एक फ़ंक्शन को परिभाषित करता है जिसका नाम Sएक बाइट में होता है और उस पर रिजेंडेल एस-बॉक्स लागू होता है। (यह rकुछ वर्णों को बचाने के लिए नामित आंतरिक सहायक फ़ंक्शन का भी उपयोग करता है ।)

यह कार्यान्वयन GF (2 8 ) के व्युत्क्रमों के लिए एक लघुगणक तालिका का उपयोग करता है , जैसा कि थॉमस पोर्निन द्वारा सुझाया गया है । कुछ वर्णों को बचाने के लिए, पूरे लघुगणक तालिका को प्रत्येक इनपुट बाइट के लिए पुनर्गणना किया जाता है; फिर भी, और गोल्फस्क्रिप्ट सामान्य रूप से बहुत धीमी भाषा में होने के बावजूद, यह कोड मेरे पुराने लैपटॉप पर एक बाइट को संसाधित करने में केवल 10 एमएस लेता है। लघुगणक तालिका (as L) को बढ़ाकर इसे तीन बाइट्स की मामूली लागत पर लगभग 0.5 ms प्रति बाइट तक गति प्रदान करता है:

[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*

इस कोड को ऑनलाइन आज़माएं।

(ऑनलाइन डेमो बहुत अधिक समय लेने से बचने के लिए लघुगणक सारणी का पूर्वाभ्यास करता है। फिर भी, ऑनलाइन गोल्फस्क्रिप्ट साइट कभी-कभी बेतरतीब ढंग से समय निकाल सकती है; यह साइट के साथ एक ज्ञात समस्या है, और एक पुनः लोड आमतौर पर इसे ठीक करता है।)

स्पष्टीकरण:

चलो लघुगणक तालिका गणना के साथ शुरू करते हैं, और विशेष रूप से सहायक समारोह के साथ r:

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

यह फ़ंक्शन स्टैक पर दो इनपुट लेता है: एक बाइट और एक कमी बिटमास्क (256 और 511 के बीच एक स्थिर)। यह इनपुट बाइट को डुप्लिकेट करता है, कॉपी को 2 से गुणा करता है, और यदि परिणाम 255 से अधिक हो जाता है, तो इसे 256 के नीचे लाने के लिए इसे बिटकोस्क के साथ XORs करता है।

लॉग-टेबल जनरेटिंग कोड के भीतर, फंक्शन rको बिटमस्क 283 = 0x11b (जो कि रिजेन्डेल GF (2 8 ) रिडक्शन पॉलीनोमियल x 8 + x 4 + x 3 + x + 1) के साथ कहा जाता है, और परिणाम XORed है) मूल बाइट के साथ, रिझंडेल परिमित क्षेत्र में प्रभावी रूप से इसे 3 (= x + 1, एक बहुपद के रूप में) से गुणा करें । यह गुणन 255 बार दोहराया जाता है, बाइट 1 से शुरू होता है, और परिणाम (एक प्रारंभिक शून्य बाइट) 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 बाइट्स

एईएस-एनआई अनुदेश सेट का उपयोग करता है

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 एक गणितज्ञ को खींचता है, और उसके लिए एक अंतर्निहित है।
चाँदहर्ट ०

6

तालिका को परिमित क्षेत्र GF (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 GF (256) * का एक गुणक जनरेटर है। तालिका t[]ऐसी है जो t[x]3 x के बराबर है ; 3 255 = 1 के बाद से , हमें वह 1 / (3 x ) = 3 255-x मिलता है


0x1Bइसके बजाय (हेक्स शाब्दिक में 1) नहीं होना चाहिए0x11B
शाफ़्ट फ्रीक

@ratchetfreak: नहीं, यह 0x11B होना चाहिए (मैंने कोशिश की)। intप्रकार जावा में 32-बिट है; मुझे उच्चतर बिट को रद्द करना होगा।
थॉमस पोर्निन

आह महसूस नहीं किया कि
शाफ़्ट सनकी

क्या पंक्ति 4 में >> के बजाय >>> है?
जो

@ जोज़ेंग: दोनों काम करेंगे। जावा में, ">>>" "अहस्ताक्षरित पारी" है, ">>" "हस्ताक्षरित पारी" है। वे इस बात से भिन्न होते हैं कि वे साइन बिट को कैसे संभालते हैं। यहां, संकेत बिट के शून्य न होने के लिए मान कभी भी व्यापक नहीं होंगे, इसलिए यह कोई वास्तविक अंतर नहीं करता है।
थॉमस पोर्निन

6

गोल्फस्क्रिप्ट (82 वर्ण)

{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
@fgrieu ज़रूर, लेकिन ये सभी स्थिरांक द्वारा गुणा हैं, जिन्हें शिफ़्ट और ऐड के उपयोग से निरंतर समय में आसानी से लागू किया जा सकता है।
कीथ रान्डेल

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करने के लिए 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 ने @Thomas 'algo का उपयोग किया


0

स्टेक्स , 53 बाइट्स

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

इसे चलाएं और डीबग करें

मुझे एस-बॉक्स की कोई विशेष समझ नहीं है। यह थॉमस पोर्निन (8 वर्ष पुराना!) समाधान का रूपांतरण है ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.