日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

生成DES的S盒

發(fā)布時(shí)間:2023/12/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 生成DES的S盒 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 1. DES的S盒滿足的規(guī)則
  • 2. 設(shè)計(jì)思路
    • 2.1 總的思路
    • 2.2 滿足S盒規(guī)則
      • 2.2.1 滿足①+②
      • 2.2.2 滿足③
      • 2.2.3 滿足④
      • 2.2.4 滿足⑤
  • 3. 編程實(shí)現(xiàn)
    • 3.1 矛盾組
    • 3.2 ⑤的不等組
    • 3.3 S盒存放
    • 3.4 ③④規(guī)則實(shí)現(xiàn)
    • 3.5 ⑤的實(shí)現(xiàn)
    • 3.6 擺放數(shù)字
  • 4. 結(jié)果呈現(xiàn)
  • 5. 完整代碼

1. DES的S盒滿足的規(guī)則

①S盒的每一行是整數(shù)0-15的一個(gè)置換;
② 每個(gè)S盒的傳輸函數(shù)都不是線性的或仿射的;
③對一個(gè)S盒而言,輸入端每改變一位,至少引起輸出端改變兩位;
④S(x)和S(x⊕001100)至少有2位不同;
⑤對于任何e與f,S(x)≠S(x⊕11ef00)
⑥當(dāng)輸入端任何一位保持不變時(shí),S盒應(yīng)保證在其輸出端0和1的個(gè)數(shù)之差達(dá)到最小。

  • 文中實(shí)現(xiàn)了①~⑤條,第⑥條是統(tǒng)計(jì)規(guī)律。實(shí)際上主要需要實(shí)現(xiàn)的是3、4、5這3條規(guī)則。

2. 設(shè)計(jì)思路

2.1 總的思路

??總的思路是,類比用棧實(shí)現(xiàn)走迷宮的方法,生成一個(gè)符合要求的S盒,實(shí)際上就是把數(shù)字按照順序從(0,0)一個(gè)個(gè)擺放到(3,15)。所以實(shí)現(xiàn)時(shí),就依順序,從(0,0)開始放置數(shù)字,直到成功放到(3,15)。如果在擺放數(shù)字到(r,c)失敗時(shí),回退一步,消除影響,再次嘗試換一個(gè)數(shù)據(jù)來進(jìn)行擺放。

2.2 滿足S盒規(guī)則

2.2.1 滿足①+②

??因?yàn)楸旧頂[放數(shù)字的時(shí)候,每行是獨(dú)立的,所以實(shí)現(xiàn)第①條很容易,并且在滿足③和④后,不滿足第②的幾率很小很小。用數(shù)組haveput[16]來防止生成的S盒出現(xiàn)列內(nèi)重復(fù)數(shù)字。

2.2.2 滿足③

??要滿足第③條,輸入變化1位,輸出至少變化2位。
??首先考慮簡單的,輸入變化導(dǎo)致選擇到了同一列中的不同行。只改變S=b1b2b3b4b5b6中的1/6位,實(shí)際上就是在列內(nèi)行變化。原來是第0(00)行,可能會(huì)變到第1行(01)或者第2行(10)。再考慮行內(nèi)的列變化,如果改變b2b3b4b5中的某一位,則會(huì)導(dǎo)致行內(nèi)列變化,變化到同一行中的不同列。
??實(shí)現(xiàn)行內(nèi)列變化,引入矛盾組的概念,相當(dāng)于黑名單。組<x>內(nèi)的數(shù)字,都是與<x>只有一位差別,或者為x。例如,下圖中每列為1個(gè)組,組<1>={0,3,5,9},組<9>={8,11,13,1}。

??先實(shí)現(xiàn)輸入變化一位導(dǎo)致的行內(nèi)列變化,輸出變化2位。實(shí)現(xiàn)時(shí),在放置(2,4)時(shí),需要讓(2,4)與(2,0),(2,5),(2,6),(2,12)內(nèi)的數(shù)字相差至少2位。因?yàn)?2,5),(2,6),(2,12)還沒有擺放,所以在放置(2,4)只需要考慮(2,0),如果(2,0)中現(xiàn)在擺放著6,擺放(2,4)時(shí),擺放的數(shù)字只要滿足不在組<6>中即可,就滿足了擺放的不是相差1位的要求。

??再實(shí)現(xiàn)輸入變化一位導(dǎo)致的列內(nèi)行變化,輸出變化2位。放置(3,3)時(shí),需要檢查<3>的矛盾組<3>={2,1,7,11},因?yàn)?,1都小于3,所以放(3,3)時(shí)需要考慮(2,3)和(1,3)中放的數(shù)字γ和β,(3,3)中放的數(shù)字不能是<γ>和<β>中的數(shù)字,也就是不能只相差一位。

??對于不能相同數(shù)字,行內(nèi)不同列數(shù)字不相同是用haveput數(shù)組保證的,列內(nèi)則需要第一次擴(kuò)展矛盾組。組<3>擴(kuò)展為<3> ={3,2,1,7,11},組中第一個(gè)數(shù)字就是組號,這樣檢查矛盾組的時(shí)候,就能檢查是否相同和相差一位。這樣,放(3,3)時(shí)需要考慮(2,3)和(1,3)中放的數(shù)字γ和β,(3,3)中放的數(shù)字不能是<γ>和<β>中的數(shù)字,就考慮到了相同和只相差一位。
??到此為止,S盒就滿足了輸入相差一位,輸出變化至少兩位。

2.2.3 滿足④

??用滿足第三條的方法,只不過在矛盾組中再加入一個(gè)數(shù)字即可。如<4>={4, 5, 6, 0, 12},滿足第四條,就再次擴(kuò)展<4>,加入4與0110異或的結(jié)果2,擴(kuò)展后的<4>={4, 5, 6, 0, 12, 2}, ,因?yàn)榈谒臈l僅僅是行內(nèi)的列規(guī)則,所以實(shí)現(xiàn)時(shí)只需要檢查行內(nèi)的列即可。
??如放置(2,4)時(shí),<4>的最后一位存放著與0110異或結(jié)果,為2,所以考慮中(2,2)存放的數(shù)字,假設(shè)為8,那么(2,4)中不能存放與8相差一位的數(shù)字即<8>中的9, 10, 12, 0。

2.2.4 滿足⑤

??類比滿足前面準(zhǔn)則的方法,引入不等組。觀察以后發(fā)現(xiàn),⑤的實(shí)現(xiàn)實(shí)際上是先選擇行,在選擇列不相等。第0行和第1行的擺放不受⑤的影響,因?yàn)閎1=1,b6=0不會(huì)讓第0和第1之間影響。但是第0行和第2行、第1行與第3行間有影響,擺放第2、3行數(shù)據(jù)的時(shí)候,要對應(yīng)考慮第0、1內(nèi)的數(shù)據(jù)。
??具體來說,2/3行中元素,需要查不等表: 0/2/4/6列查0/1行的8/10/12/14列不等,1/3/5/7列查0/1行的9/11/13/15列不等,8/10/12/14列的查0/1行的0/2/4/6列不等,9/11/13/15列的查0/1行的1/3/5/7列不等。
??這樣一來,就實(shí)現(xiàn)了模2變化11ef00元素的不相等。


3. 編程實(shí)現(xiàn)

3.1 矛盾組

int exgroup[16][6] = {//列矛盾是[0]--[4].行矛盾是[1]--[5]{0, 1, 2, 4, 8, 6}, //0 group{1, 0, 3, 5, 9, 7}, //1 group{2, 3, 0, 6, 10, 4}, //2 group{3, 2, 1, 7, 11, 5}, //3 group{4, 5, 6, 0, 12, 2}, //4 group{5, 4, 7, 1, 13, 3}, //5 group{6, 7, 4, 2, 14, 0}, //6 group{7, 6, 5, 3, 15, 1}, //7 group{8, 9, 10, 12, 0, 14}, //8 group{9, 8, 11, 13, 1, 15}, //9 group{10, 11, 8, 14, 2, 12}, //10 group{11, 10, 9, 15, 3, 13}, //11 group{12, 13,14, 8, 4, 10}, //12 group{13, 12,15, 9, 5, 11}, //13 group{14, 15,12, 10, 6, 8}, //14 group{15, 14,13, 11, 7, 9} //15 group };

3.2 ⑤的不等組

int forrule4[4][4]{{8,10,12,14}, // 0/2/4/6{9,11,13,15}, // 1/3/5/7{0, 2, 4, 6}, // 8/10/12/14{1, 3, 5, 7} // 9/11/13/15 };

3.3 S盒存放

typedef struct {int x = 0; //當(dāng)前單元格的行號int num; //num is the current num of the cellset <int>tried;//some have try but fail } Cell; //定義單元格類型 typedef struct {Cell data[4][BoxSize];//存放1個(gè)S盒int top; //棧頂指針 } StType; //順序棧類型

3.4 ③④規(guī)則實(shí)現(xiàn)

//行內(nèi)規(guī)則 for (int k = 1; k < 6; k++)//考慮行內(nèi)規(guī)則{if (exgroup[i][k] < i)for (int m = 1; m < 5; m++)//因?yàn)橛衕avaput檢查,所以行里面本身不會(huì)有相同的{notchoose.insert(exgroup[st.data[row][exgroup[i][k]].num][m]);}}

??行內(nèi)規(guī)則③,就遍歷矛盾組的[1]-[5]列,如果它們比當(dāng)前列號小,已經(jīng)擺放上了,就得考慮??紤]時(shí),不用擔(dān)心重復(fù)0-15,有haveput保證。保證不是只相差1位就行,也就是內(nèi)部考慮矛盾組的[1]-[4]列。
??行內(nèi)規(guī)則④,存在矛盾組的第[5]列,所以合并以后就可以和③一起實(shí)現(xiàn)。

//列內(nèi)規(guī)則 for (int k = 1; k < 5; k++)//考慮列內(nèi)規(guī)則 { if (exgroup[row][k] < row)//行號小于row的,需要考慮for (int m = 0; m < 5; m++)//與矛盾的列中數(shù)字相差一位不能選,相同也不能選,所以要到m=4 {notchoose.insert(exgroup[st.data[exgroup[row][k]][i].num][m]);//索引次序不能搞錯(cuò)} }

??列內(nèi)規(guī)則,也是遍歷矛盾組的[1]-[4]列,如果如果它們比當(dāng)前行號小,已經(jīng)擺放上了,就得考慮。haveput是一維的,所以需要考慮重復(fù)和差一位,內(nèi)部考慮矛盾組[0]-[4]列。

3.5 ⑤的實(shí)現(xiàn)

mod = i % 2;if (row > 1)//第2/3行開始才要和前面對比,第2行對比第0行,第3行對比第1行{if (mod==0 && i < 8)notequal = 0;else if(mod==1 && i < 8)notequal = 1;else if (mod == 0 && i >7)notequal = 2;else if (mod == 1 && i > 7)notequal = 3;for (int q = 0; q < 4; q++)notchoose.insert(st.data[row - 2][forrule4[notequal][q]].num);}

??只有row>1才要判斷,判斷當(dāng)前列號大于8還是小于8,奇數(shù)還是偶數(shù),0/2/4/6列查0/1行的8/10/12/14列不等notequal = 0, 1/3/5/7列查0/1行的9/11/13/15列不等notequal = 1,8/10/12/14列的查0/1行的0/2/4/6列不等notequal = 2, 9/11/13/15列的查0/1行的1/3/5/7列不等notequal = 3,然后對應(yīng)到索引查表即可。

3.6 擺放數(shù)字

//數(shù)字?jǐn)[放//當(dāng)前單元格選哪個(gè)數(shù)字好呢? for (int j = 0; j < 16; j++)if (haveput[j] == 1)notchoose.insert(j);//不僅要滿足矛盾組規(guī)則,還要滿足同一行不重復(fù)if (notchoose.size() < 16){//做差集,全集與不能選的相減,得到的就是可以選的it = set_difference(U.begin(), U.end(), notchoose.begin(), notchoose.end(), canchoose.begin());canchoose.resize(it - canchoose.begin());if (canchoose.size() > 1)random_shuffle(canchoose.begin(), canchoose.end());//不然就隨機(jī)選一個(gè)currentnum = *canchoose.begin();//重排列以后選第一個(gè)flag = 1;//OhYeah!找到一個(gè)可以放在這個(gè)單元格的了canchoose.resize(16);//把那個(gè)向量大小復(fù)原}

??判斷能不能放數(shù)字,做全集U=[0-15]差集就可以了,如果差集非空就說明可以放,找到這樣的數(shù)字,就立下flag=1。如果flag=1說明可以放數(shù)字,那就放。

if (flag == 1)//可以在當(dāng)前單元格放數(shù)字 {st.top++; st.data[row][st.top].x = i; st.data[row][st.top].num = currentnum;st.data[row][st.top].tried.insert(currentnum);//記住這個(gè)單元格放過這個(gè)數(shù)字haveput[currentnum] = 1;//放好了,行內(nèi)重復(fù)標(biāo)記notchoose.clear();//清空,準(zhǔn)備下一個(gè)單元格flag = 0;if (st.top < 15)//可能現(xiàn)在是之前的回溯,把下一個(gè)單元格的黑歷史清空{if (!st.data[row][st.top + 1].tried.empty())st.data[row][st.top + 1].tried.clear();}else if (st.top == 15 && row < 3)//如果在最后一列,要清空下一行第一個(gè)的黑歷史if (!st.data[row + 1][0].tried.empty())st.data[row + 1][0].tried.clear();}

??放數(shù)字放下以后,haveput進(jìn)行標(biāo)記,不能重復(fù)放,放完以后,flag=0復(fù)位準(zhǔn)備下一次,同時(shí)為了回溯時(shí)不走重復(fù)的路,S盒結(jié)構(gòu)的那個(gè)單元需要記住自己放了這個(gè)數(shù)字。如果不湊巧這個(gè)單元格沒有數(shù)字可以放,那就怪前面的單元格放錯(cuò)了,回溯,如下:

else {//不湊巧,這個(gè)單元格沒有數(shù)字可以放,回溯notchoose.clear();haveput[st.data[row][st.top].num] = 0;//退一步,之前放的更改,其它單元可以放notchoose.insert(st.data[row][st.top].tried.begin(), st.data[row][st.top].tried.end());//不在同一個(gè)地方摔倒兩次st.top--;if (st.top == -1 && row > 0)//注意放置在哪里!!!{st.top = 15;//最右上row--;for (int m = 0; m < 16; m++) haveput[m] = 1;haveput[st.data[row][st.top].num] = 0;} }

??什么時(shí)候會(huì)知道放完了呢,那就是i=16(只有[15]列且row為3),跳出while循環(huán):

i = st.data[row][st.top].x + 1;//現(xiàn)在在放第row行第i個(gè)單元格if (row == 3 && i == 16) break;//已經(jīng)做完了!注意順序!!!if (i == 16)//往下走一行,走到下一行的最左邊{row++;st.top = -1;i = 0;for (int m = 0; m < 16; m++) haveput[m] = 0;//新起一行了,把行內(nèi)重復(fù)標(biāo)記清空}

4. 結(jié)果呈現(xiàn)


??總共有8個(gè)S盒:

5. 完整代碼

#include <cstdlib> #include <set> #include <vector> #include <iostream> #include <algorithm> const int BoxSize = 16; using namespace std; typedef struct {int x = 0; //當(dāng)前單元格的行號int num; //num is the current num of the cellset <int>tried;//some have try but fail } Cell; //定義單元格類型 typedef struct {Cell data[4][BoxSize];//存放1個(gè)S盒int top; //棧頂指針 } StType; //順序棧類型// the neibough of a is exgroup[a],they diff 1 bit from a int exgroup[16][6] = {//列矛盾是[0]--[4].行矛盾是[1]--[5]{0, 1, 2, 4, 8, 6}, //0 group{1, 0, 3, 5, 9, 7}, //1 group{2, 3, 0, 6, 10, 4}, //2 group{3, 2, 1, 7, 11, 5}, //3 group{4, 5, 6, 0, 12, 2}, //4 group{5, 4, 7, 1, 13, 3}, //5 group{6, 7, 4, 2, 14, 0}, //6 group{7, 6, 5, 3, 15, 1}, //7 group{8, 9, 10, 12, 0, 14}, //8 group{9, 8, 11, 13, 1, 15}, //9 group{10, 11, 8, 14, 2, 12}, //10 group{11, 10, 9, 15, 3, 13}, //11 group{12, 13,14, 8, 4, 10}, //12 group{13, 12,15, 9, 5, 11}, //13 group{14, 15,12, 10, 6, 8}, //14 group{15, 14,13, 11, 7, 9} //15 group };int forrule4[4][4]{{8,10,12,14}, // 0/2/4/6{9,11,13,15}, // 1/3/5/7{0, 2, 4, 6}, // 8/10/12/14{1, 3, 5, 7} // 9/11/13/15 };void genSbox(int times, FILE*&fid) {StType st; st.top = -1;//初始化結(jié)構(gòu)int haveput[16] = { 0 };//行內(nèi)重復(fù)標(biāo)記,行內(nèi)不能有重復(fù)的!int currentnum;//當(dāng)前單元格決定擺放的數(shù)字int a[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };vector<int>U(a, a + 16);//全集,用于與不能擺的數(shù)字集合notchoose做差運(yùn)算,得到可以擺的set<int> notchoose;//當(dāng)前單元格不能擺放的數(shù)字vector<int> canchoose(16);//當(dāng)前單元格可以擺的數(shù)字,由全集U和不能擺的數(shù)字集合notchoose做差運(yùn)算得到vector<int>::iterator it;//用于獲得當(dāng)前單元格可以擺的所有數(shù)字int flag = 0;//當(dāng)前單元格擺成功了,flag=1.當(dāng)前單元格擺不了,要回溯,flag=0int i = 0;//列號,正在擺的那一列int row = 0;//行號,擺到哪一行了int notequal = 0;currentnum = rand() % 16;//擺第一個(gè),啟動(dòng)st.top++; st.data[row][st.top].x = i; st.data[row][st.top].num = currentnum;haveput[currentnum] = 1;int mod = 0;while (1){i = st.data[row][st.top].x + 1;//現(xiàn)在在放第row行第i個(gè)單元格if (row == 3 && i == 16) break;//已經(jīng)做完了!注意順序!!!//printf("(row,i,st.top)===(%d,%d,%d)\n", row, i, st.top);if (i == 16)//往下走一行,走到下一行的最左邊{row++;st.top = -1;i = 0;for (int m = 0; m < 16; m++) haveput[m] = 0;//新起一行了,把行內(nèi)重復(fù)標(biāo)記清空}for (int k = 1; k < 6; k++)//考慮行內(nèi)規(guī)則{if (exgroup[i][k] < i)for (int m = 1; m < 5; m++)//因?yàn)橛衕avaput檢查,所以行里面本身不會(huì)有相同的{notchoose.insert(exgroup[st.data[row][exgroup[i][k]].num][m]);}}for (int k = 1; k < 5; k++)//考慮列內(nèi)規(guī)則{if (exgroup[row][k] < row)//行號小于row的,需要考慮for (int m = 0; m < 5; m++)//與矛盾的列中數(shù)字相差一位不能選,相同也不能選,所以要到m=4{notchoose.insert(exgroup[st.data[exgroup[row][k]][i].num][m]);//索引次序不能搞錯(cuò)}}mod = i % 2;if (row > 1)//第2/3行開始才要和前面對比,第2行對比第0行,第3行對比第1行{if (mod == 0 && i < 8)notequal = 0;else if (mod == 1 && i < 8)notequal = 1;else if (mod == 0 && i > 7)notequal = 2;else if (mod == 1 && i > 7)notequal = 3;for (int q = 0; q < 4; q++)notchoose.insert(st.data[row - 2][forrule4[notequal][q]].num);}//當(dāng)前單元格選哪個(gè)數(shù)字好呢? for (int j = 0; j < 16; j++)if (haveput[j] == 1)notchoose.insert(j);//不僅要滿足矛盾組規(guī)則,還要滿足同一行不重復(fù)if (notchoose.size() < 16){//做差集,全集與不能選的相減,得到的就是可以選的it = set_difference(U.begin(), U.end(), notchoose.begin(), notchoose.end(), canchoose.begin());canchoose.resize(it - canchoose.begin());if (canchoose.size() > 1)random_shuffle(canchoose.begin(), canchoose.end());//不然就隨機(jī)選一個(gè)currentnum = *canchoose.begin();//重排列以后選第一個(gè)flag = 1;//OhYeah!找到一個(gè)可以放在這個(gè)單元格的了canchoose.resize(16);//把那個(gè)向量大小復(fù)原}if (flag == 1)//可以在當(dāng)前單元格放數(shù)字{st.top++; st.data[row][st.top].x = i; st.data[row][st.top].num = currentnum;st.data[row][st.top].tried.insert(currentnum);//記住這個(gè)單元格放過這個(gè)數(shù)字haveput[currentnum] = 1;//放好了,行內(nèi)重復(fù)標(biāo)記notchoose.clear();//清空,準(zhǔn)備下一個(gè)單元格flag = 0;if (st.top < 15)//可能現(xiàn)在是之前的回溯,把下一個(gè)單元格的黑歷史清空{if (!st.data[row][st.top + 1].tried.empty())st.data[row][st.top + 1].tried.clear();}else if (st.top == 15 && row < 3)//如果在最后一列,要清空下一行第一個(gè)的黑歷史if (!st.data[row + 1][0].tried.empty())st.data[row + 1][0].tried.clear();}else {//不湊巧,這個(gè)單元格沒有數(shù)字可以放,回溯notchoose.clear();haveput[st.data[row][st.top].num] = 0;//退一步,之前放的更改,其它單元可以放notchoose.insert(st.data[row][st.top].tried.begin(), st.data[row][st.top].tried.end());//不在同一個(gè)地方摔倒兩次st.top--;if (st.top == -1 && row > 0)//注意放置在哪里!!!{st.top = 15;//最右上row--;for (int m = 0; m < 16; m++) haveput[m] = 1;haveput[st.data[row][st.top].num] = 0;}}}fprintf(fid, "%s%d%s", "-------------------S[", times + 1, "]----------------------\n");for (int h = 0; h < 4; h++){for (int n = 0; n <= 15; n++){fprintf(fid, "%d", st.data[h][n].num);if (n < 15) fprintf(fid, "%s", ",");}fprintf(fid, "%s", "\n");}fprintf(fid, "%s", "\n");}int main() {cout << "please enter your rand seed,an integer like 123:" << endl;int myseed;cin >> myseed;srand(myseed);char sboxpath[81] = "Sbox.csv";FILE * fid = fopen(sboxpath, "w");for (int i = 0; i < 8; i++)genSbox(i, fid);fclose(fid);cout << "Your Sbox has stored in " << sboxpath << ". Please check it!";system("pause");return 0; }

總結(jié)

以上是生活随笔為你收集整理的生成DES的S盒的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。