S-Boxes
Sbox 的固定點和相對固定點的安全隱患
定點是指當 Sbox 輸入等於 Sbox 輸出時,而相反定點是指當 Sbox 輸入是 Sbox 輸出的補碼時。Fixed 和 Opposite Fixed Point 如何影響 Sbox 的強度/安全性?
一種可能的安全威脅是不變數子空間攻擊。一個實際的例子是 midori cipher 。
Midori sbox 有 4 個固定點 (3, 7, 8, 9)。在本文中,使用由 (8 和 9) 組成的明文和由 (0 和 1) 組合的密鑰,它將為您提供由 (8 和 9) 組成的密文。它的工作原理不僅是因為固定點,還因為二進制矩陣屬性和常數值。
為了理解定點的效果,我們改變輪常數值,用 4 代替 1。然後使用 3 和 7 組成的明文和 0 和 4 組合的密鑰,它會產生由 3 和 7 組成的密文(下面的程式碼中的插圖)。
這是我知道的一種情況(例如)固定點的安全含義,但我沒有遇到相反的固定點
#include <stdio.h> #include <stdlib.h> // 7 3 , constant 4 0; weak keys : 0 4 // 8 9 , constant 1 0; weak keys : 0 1 uint64_t SBox0[16]= {0XC,0XA,0XD,0X3,0XE,0XB,0XF,0X7,0X8,0X9,0X1,0X5,0X0,0X2,0X4,0X6}; /* uint64_t RC[19] = { 0X0001010110110011, 0X0111100011000000, 0X1010010000110101, 0X0110001000010011, 0X0001000001001111, 0X1101000101110000, 0X0000001001100110, 0X0000101111001100, 0X1001010010000001, 0X0100000010111000, 0X0111000110010111, 0X0010001010001110, 0X0101000100110000, 0X1111100011001010, 0X1101111110010000, 0X0111110010000001, 0X0001110000100100, 0X0010001110110100, 0X0110001010001010 }; */ uint64_t RC[19] = { 0X0004040440440044, 0X0444400044000000, 0X4040040000440404, 0X0440004000040044, 0X0004000004004444, 0X4404000404440000, 0X0000004004400440, 0X0000404444004400, 0X4004040040000004, 0X0400000040444000, 0X0444000440040444, 0X0040004040004440, 0X0404000400440000, 0X4444400044004040, 0X4404444440040000, 0X0444440040000004, 0X0004440000400400, 0X0040004440440400, 0X0440004040004040 }; uint64_t mask=0xF; uint64_t SK[15]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; void subKey(uint64_t K0,uint64_t K1){ SK[0]= RC[0]^K0; SK[1]= RC[1]^K1; for(int i=2;i<15;i++){ if(i%2==0) SK[i]= RC[i]^K0; else if(i%2==1) SK[i]= RC[i]^K1; } } uint64_t Permutate(uint64_t input){ uint64_t x[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint64_t y[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint16_t P[16]= {0,10,5,15,14,4,11,1,9,3,12,6,7,13,2,8}; uint64_t output; uint64_t i = input; x[15]= (input &(mask<<0))>>0; x[14]= (input &(mask<<4))>>4; x[13]= (input &(mask<<8))>>8; x[12]= (input &(mask<<12))>>12; x[11]= (input&(mask<<16))>>16; x[10]= (input&(mask<<20))>>20; x[9]= (input&(mask<<24))>>24; x[8]= (input&(mask<<28))>>28; x[7]= (input&(mask<<32))>>32; x[6]= (input&(mask<<36))>>36; x[5]= (input&(mask<<40))>>40; x[4]= (input&(mask<<44))>>44; x[3]= (input&(mask<<48))>>48; x[2]= (input&(mask<<52))>>52; x[1]= (input&(mask<<56))>>56; x[0]= (input&(mask<<60))>>60; y[0]= x[P[0]]; y[1]= x[P[1]]; y[2]= x[P[2]]; y[3]= x[P[3]]; y[4]= x[P[4]]; y[5]= x[P[5]]; y[6]= x[P[6]]; y[7]= x[P[7]]; y[8]= x[P[8]]; y[9]= x[P[9]]; y[10]= x[P[10]]; y[11]= x[P[11]]; y[12]= x[P[12]]; y[13]= x[P[13]]; y[14]= x[P[14]]; y[15]= x[P[15]]; output= y[15]<<0|y[14]<<4|y[13]<<8|y[12]<<12|y[11]<<16|y[10]<<20|y[9]<<24|y[8]<<28|y[7]<<32|y[6]<<36| y[5]<<40|y[4]<<44|y[3]<<48|y[2]<<52|y[1]<<56|y[0]<<60; return output; } uint64_t SubCell(uint64_t input){ uint64_t x[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint64_t y[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint64_t output; uint64_t i = input; x[0]= (input &(mask<<0))>>0; x[1]= (input &(mask<<4))>>4; x[2]= (input &(mask<<8))>>8; x[3]= (input &(mask<<12))>>12; x[4]= (input&(mask<<16))>>16; x[5]= (input&(mask<<20))>>20; x[6]= (input&(mask<<24))>>24; x[7]= (input&(mask<<28))>>28; x[8]= (input&(mask<<32))>>32; x[9]= (input&(mask<<36))>>36; x[10]= (input&(mask<<40))>>40; x[11]= (input&(mask<<44))>>44; x[12]= (input&(mask<<48))>>48; x[13]= (input&(mask<<52))>>52; x[14]= (input&(mask<<56))>>56; x[15]= (input&(mask<<60))>>60; y[0]=SBox0[x[0]]; y[1]=SBox0[x[1]]; y[2]=SBox0[x[2]]; y[3]=SBox0[x[3]]; y[4]=SBox0[x[4]]; y[5]=SBox0[x[5]]; y[6]=SBox0[x[6]]; y[7]=SBox0[x[7]]; y[8]=SBox0[x[8]]; y[9]=SBox0[x[9]]; y[10]=SBox0[x[10]]; y[11]=SBox0[x[11]]; y[12]=SBox0[x[12]]; y[13]=SBox0[x[13]]; y[14]=SBox0[x[14]]; y[15]=SBox0[x[15]]; output= y[0]<<0|y[1]<<4|y[2]<<8|y[3]<<12|y[4]<<16|y[5]<<20|y[6]<<24|y[7]<<28|y[8]<<32|y[9]<<36| y[10]<<40|y[11]<<44|y[12]<<48|y[13]<<52|y[14]<<56|y[15]<<60; return output; } uint16_t M(uint16_t I){ // matrix multiplication uint16_t x0,x1,x2,x3; uint16_t y0,y1,y2,y3; uint16_t O; x0= (I&(mask<<0))>>0; x1= (I&(mask<<4))>>4; x2= (I&(mask<<8))>>8; x3= (I&(mask<<12))>>12; y0= x1^x2^x3; y1= x0^x2^x3; y2= x0^x1^x3; y3= x0^x1^x2; O= y0<<0|y1<<4|y2<<8|y3<<12; return O; } uint64_t Mixcolumn(uint64_t I){ uint16_t x0,x1,x2,x3; uint64_t y0,y1,y2,y3; uint64_t S=0xFFFF; uint64_t O; x0= (I&(S<<0))>>0; x1= (I&(S<<16))>>16; x2= (I&(S<<32))>>32; x3= (I&(S<<48))>>48; y0= M(x0); y1= M(x1); y2= M(x2); y3= M(x3); O= y0<<0|y1<<16|y2<<32|y3<<48; return O; } uint64_t AK(uint64_t i,uint64_t K){ return i^K; } void Cipher (uint64_t PT, uint64_t K0,uint64_t K1){ uint64_t temp; int i; temp=AK(PT,K0^K1); // whitening; printf("KT:%08llx%08llx\n",K0,K1); printf("PT:%016llx\n",PT); for(i=0;i<15;i++){ temp=SubCell(temp); temp=Permutate(temp); temp=Mixcolumn(temp); temp=AK(temp,SK[i]); } temp=SubCell(temp); temp=AK(temp,K0^K1); // whitening; printf("CT:%016llx\n",temp); } int main(){ // This section for RC table that contains 0 and 4 as constants. /* uint64_t k0= 0x4044400444444444; uint64_t k1= 0x4444000044444400; uint64_t PT= 0x3333333333333333; */ uint64_t k0= 0x4044400444444444; uint64_t k1= 0x4444000044444400; uint64_t PT= 0x3737373737373737; // This section for RC table that contains 0 and 1 as constants. Rememeber to uncomment the RC table of 0,1 and comment the other one. /* uint64_t k0=0x0000101001001110; uint64_t k1=0x1101010100010001; uint64_t PT=0x9889898898898989; */ /* uint64_t k0=0x1100110011001100; uint64_t k1=0x0011001100110011; uint64_t PT=0x9999999999999999; */ subKey(k0,k1); Cipher(PT,k0,k1); return 0; }