使用PLC程式設計(ST語言)開發的DES加密解密功能塊
本例使用施耐德M218,M258,M241型號PLC ,其他品牌PLC,理論上只要支援IEC61131-3標準,都有IL/ST/FBD/LD/CFC/SFC六種程式語言,本例使用ST語言。
一、定義功能塊
FUNCTION_BLOCK DES VAR_INPUT // i_Exe :BOOL; //使用者的 64b, 金鑰 {attribute 'displaymode':='binary'} i_Key :ARRAY[0..3] OF uINT; // 64bit 明文 {attribute 'displaymode':='binary'} i_Data: ARRAY[0..3] OF UINT; // TRUE = 加密, FALSE = 解密 i_Mode :BOOL; END_VAR VAR_OUTPUT {attribute 'displaymode':='hex'} q_Ciphertext :ARRAY[0..3] OF UINT; END_VAR VAR // 上升沿 Exe_R_TRIG :R_TRIG; // 臨時變數 i,j,m,n,Index: INT; // 64bit 金鑰 M_KeyBit: ARRAY [1..64] OF BOOL; // 64bit 資料 M_DataBit: ARRAY [1..64] OF BOOL; // 置換選擇 1 的矩陣 C0_Table :ARRAY[1..28] OF INT:=[ 57,49,41,33,25,17,9, 1,58,50,42,34,26,18, 10,2,59,51,43,35,27, 19,11,3,60,52,44,36]; D0_Table :ARRAY[1..28] OF INT:=[ 63,55,47,39,31,23,15, 7,62,54,46,38,30,22, 14,6,61,53,45,37,29, 21,13,5,28,20,12,4]; // Ci :ARRAY[0..16,1..28] OF BOOL;// C0 -- C16 , 28bit , CO(左28bit) 是 C1 -- C16 的最原始的基礎 ,C1 -- C16 稱為 16 個子金鑰 Di :ARRAY[0..16,1..28] OF BOOL;// D0 -- D16 , 28bit , DO(右28bit) 是 D1 -- D16 的最原始的基礎 ,D1 -- D16 稱為 16 個子金鑰 // 迴圈左移 的矩陣 RotateLeft_Table:ARRAY[0..15] OF INT:=[1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1]; // C0、D0組合而成的中間資料 M_CiDi :ARRAY[1..56] OF BOOL; // 置換選擇 2 的矩陣為一個 8 * 6 的矩陣,將上面得到的16個子鑰按照下表的規律進行位的交換 // 在此過程中,第9,18,22,25, 35,38,43,54位丟棄。 K48_Table :ARRAY[1..48] OF INT:=[ 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32]; // 子金鑰 K Ki:ARRAY[1..16,1..48] OF BOOL; // 64bit 明文換位表 Data_Table:ARRAY[1..64] OF INT:=[ 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,// Li 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7];// Ri // 置換後的 64bit 明文 Displaced_DataBit: ARRAY [1..64] OF BOOL; // 擴充套件表 Extend_Table:ARRAY[1..48] OF INT:=[ 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1]; // 置換後的 64bit 明文分成兩部分 Li:ARRAY[0..16,1..32] OF BOOL; Ri:ARRAY[0..16,1..32] OF BOOL; ER:ARRAY[1..16,1..48] OF BOOL; Result48:ARRAY[1..16,1..48] OF BOOL; // S1:ARRAY[0..3,0..15] OF INT:=[ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]; S2:ARRAY[0..3,0..15] OF INT:=[ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]; S3:ARRAY[0..3,0..15] OF INT:=[ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]; S4:ARRAY[0..3,0..15] OF INT:=[ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]; S5:ARRAY[0..3,0..15] OF INT:=[ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]; S6:ARRAY[0..3,0..15] OF INT:=[ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]; S7:ARRAY[0..3,0..15] OF INT:=[ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]; S8:ARRAY[0..3,0..15] OF INT:=[ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]; // 行、列 Row,Col:INT; S_Result:ARRAY[1..16,1..8] OF INT; ToBinary:ARRAY[1..16,1..32] OF BOOL; P_Table :ARRAY[1..32] OF INT:=[ 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25]; AfterP:ARRAY[1..16,1..32] OF BOOL; AfterXOR:ARRAY[1..16,1..32] OF BOOL; {attribute 'displaymode':='hex'} L_Show:ARRAY[1..16] OF DINT; // 僅僅為了顯示十六進位制,程式設計時檢查程式碼使用 {attribute 'displaymode':='hex'} R_Show:ARRAY[1..16] OF DINT; // 僅僅為了顯示十六進位制,程式設計時檢查程式碼使用 R16L16:ARRAY[1..64] OF BOOL; IP_1_Table :ARRAY[1..64] OF INT:=[ 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25]; Finally_Result :ARRAY[1..64] OF BOOL; END_VAR
二、功能塊中的程式碼
// 參考https://blog.csdn.net/m0_37962600/article/details/79912654
// DES 即 DataEncryptionStandard (資料加密標準)
// 加密演算法
Exe_R_TRIG(CLK:=i_Exe);
IF Exe_R_TRIG.Q AND i_Mode THEN
DisposeCipher();// 處理金鑰,得到子金鑰
DisposePlaintext();// 處理明文格式
Encryption();// 使用子金鑰對明文進行加密
END_IF
三、3個方法具體程式碼
DisposeCipher()的程式碼如下:
// M_KeyBit[0..63] 是約定的 64bit 金鑰 // Key[0] Key[1] Key[2] Key[3] // 11110000 11110000 11110000 11110000 11110000 11110000 11110000 11110000 置換表都是從左向右數的 1 - 64 FOR i:=0 TO 3 DO M_KeyBit[i*16+1]:=i_Key[i].15; M_KeyBit[i*16+2]:=i_Key[i].14; M_KeyBit[i*16+3]:=i_Key[i].13; M_KeyBit[i*16+4]:=i_Key[i].12; M_KeyBit[i*16+5]:=i_Key[i].11; M_KeyBit[i*16+6]:=i_Key[i].10; M_KeyBit[i*16+7]:=i_Key[i].9; M_KeyBit[i*16+8]:=i_Key[i].8; M_KeyBit[i*16+9]:=i_Key[i].7; M_KeyBit[i*16+10]:=i_Key[i].6; M_KeyBit[i*16+11]:=i_Key[i].5; M_KeyBit[i*16+12]:=i_Key[i].4; M_KeyBit[i*16+13]:=i_Key[i].3; M_KeyBit[i*16+14]:=i_Key[i].2; M_KeyBit[i*16+15]:=i_Key[i].1; M_KeyBit[i*16+16]:=i_Key[i].0; END_FOR // 對輸入的 64bit 金鑰進行置換,得到有用的 56bit 金鑰 ,且將前28位作為C0,後28位作為D0。 // 置換選擇1 // 64位金鑰分為8個位元組。每個位元組的前7位是真正的金鑰位,第8位是奇偶校驗位。 // 奇偶校驗位可以從前7位金鑰位計算得出,不是隨機的,因而不起金鑰的作用。因此,DES真正的金鑰只有56位。 // 置換選擇1的作用有兩個:一是從64位金鑰中去掉8個奇偶校驗位;二是把其餘56位金鑰位打亂重排,且將前28位作為C0,後28位作為D0。 FOR i:=1 TO 28 BY 1 DO Ci[0,i] :=M_KeyBit[C0_Table[i]]; // C0 Di[0,i] :=M_KeyBit[D0_Table[i]]; // D0 END_FOR // 迴圈左移分別得到Ci和Di ,將Ci和Di合併成一個56位的中間資料,置換選擇從中選擇出一個48位的子金鑰Ki。 // 最終得到了 C0 D0 , C1 D1 , C2 D2 ... ... C16 D16 ,其中 C1 D1 , C2 D2 ... ... C16 D16 稱為 16 輪子金鑰 FOR i:=1 TO 16 DO // 迴圈左移分別得到 Ci 和 Di (1--16) FOR j:=1 TO RotateLeft_Table[i-1] DO // 首先左移 C (前面28個位) CASE RotateLeft_Table[i-1] OF 1: Ci[i,28]:=Ci[i-1,1]; FOR m:=1 TO 27 BY 1 DO Ci[i,m]:=Ci[i-1,m + 1]; END_FOR 2: Ci[i,27]:=Ci[i-1,1]; Ci[i,28]:=Ci[i-1,2]; FOR m:=1 TO 26 BY 1 DO Ci[i,m]:=Ci[i-1,m + 2]; END_FOR END_CASE // 然後左移 D (前面28個位) CASE RotateLeft_Table[i-1] OF 1: Di[i,28]:=Di[i-1,1]; FOR m:=1 TO 27 BY 1 DO Di[i,m]:=Di[i-1,m + 1]; END_FOR 2: Di[i,27]:=Di[i-1,1]; Di[i,28]:=Di[i-1,2]; FOR m:=1 TO 26 BY 1 DO Di[i,m]:=Di[i-1,m + 2]; END_FOR END_CASE END_FOR // 將 Ci 和 Di 合併成一個 56 位的中間資料 FOR n:=1 TO 56 DO IF n <= 28 THEN M_CiDi[n] :=Ci[i,n]; ELSE M_CiDi[n] :=Di[i,n - 28]; END_IF END_FOR // 置換選擇,從中選擇出一個48位的子金鑰 Kn 。 FOR n:=1 TO 48 DO Ki[i,n]:=M_CiDi[K48_Table[n]]; END_FOR // 以上 i = 1 -- 16 步驟,便得到了 K1 ,K2 ,K3 ... ... K16 END_FOR
DisposePlaintext()的程式碼如下:
// 64bit (明文)資料 // M_DataBit[1..64] 是 64bit 資料 // M_DataBit[0] M_DataBit[1] M_DataBit[2] M_DataBit[3] // 11110000 11110000 11110000 11110000 11110000 11110000 11110000 11110000 置換表都是從左向右數的 1 - 64 FOR i:=0 TO 3 DO M_DataBit[i*16+1]:=i_Data[i].15; M_DataBit[i*16+2]:=i_Data[i].14; M_DataBit[i*16+3]:=i_Data[i].13; M_DataBit[i*16+4]:=i_Data[i].12; M_DataBit[i*16+5]:=i_Data[i].11; M_DataBit[i*16+6]:=i_Data[i].10; M_DataBit[i*16+7]:=i_Data[i].9; M_DataBit[i*16+8]:=i_Data[i].8; M_DataBit[i*16+9]:=i_Data[i].7; M_DataBit[i*16+10]:=i_Data[i].6; M_DataBit[i*16+11]:=i_Data[i].5; M_DataBit[i*16+12]:=i_Data[i].4; M_DataBit[i*16+13]:=i_Data[i].3; M_DataBit[i*16+14]:=i_Data[i].2; M_DataBit[i*16+15]:=i_Data[i].1; M_DataBit[i*16+16]:=i_Data[i].0; END_FOR // 對輸入的資料(明文)進行資料置換 // 資料置換,將64位資料前後分成兩塊L[0][32], R[0][32]。 FOR i:=1 TO 64 DO Displaced_DataBit[i]:=M_DataBit[Data_Table[i]]; END_FOR // L0 為前32位,R0 為後32位 FOR i:=1 TO 32 DO Li[0,i]:=Displaced_DataBit[i]; Ri[0,i]:=Displaced_DataBit[i+32]; END_FOR
Encryption()的程式碼如下
// 為了得到 L1R1 ... L16R16 , m=1 時得到 L1R1
FOR m:=1 TO 16 DO
// 由32位數擴充套件成48位數
FOR i:=1 TO 48 DO
ER[m,i]:=Ri[m-1,Extend_Table[i]];//按照表格來
END_FOR
// ER 與 Ki 做異或運算
FOR i:=1 TO 48 DO
Result48[m,i]:=ER[m,i] XOR Ki[m,i];
END_FOR
// 將異或運算得到的 48 位結果 Result48 資料分成8個6位的塊
// 將每一塊通過對應的一個 S 盒產生一個 4 位的輸出
// S盒接收6位的輸入,經過置換輸出4位的資料
FOR i:=0 TO 7 DO
Row:=0;
Row.0:=Result48[m,6+i*6];
Row.1:=Result48[m,1+i*6];
Col:=0;
Col.0:=Result48[m,5+i*6];
Col.1:=Result48[m,4+i*6];
Col.2:=Result48[m,3+i*6];
Col.3:=Result48[m,2+i*6];
CASE i OF
0: S_Result[m,i+1]:=S1[Row,Col];
1: S_Result[m,i+1]:=S2[Row,Col];
2: S_Result[m,i+1]:=S3[Row,Col];
3: S_Result[m,i+1]:=S4[Row,Col];
4: S_Result[m,i+1]:=S5[Row,Col];
5: S_Result[m,i+1]:=S6[Row,Col];
6: S_Result[m,i+1]:=S7[Row,Col];
7: S_Result[m,i+1]:=S8[Row,Col];
END_CASE
END_FOR
// 將十進位制轉換為二進位制
FOR i:=0 TO 7 DO
ToBinary[m,i*4+1] := S_Result[m,i+1].3;
ToBinary[m,i*4+2] := S_Result[m,i+1].2;
ToBinary[m,i*4+3] := S_Result[m,i+1].1;
ToBinary[m,i*4+4] := S_Result[m,i+1].0;
END_FOR
// 將S盒輸出結果再通過一個P盒置換產生一個32位輸出
FOR i:=1 TO 32 DO
AfterP[m,i] := ToBinary[m,P_Table[i]];
END_FOR
// 將此結果與 L0(32位)進行異或運算
FOR i:=1 TO 32 DO
AfterXOR[m,i] := AfterP[m,i] XOR Li[m-1,i];
END_FOR
// 左右交換位置,將上步的結果賦給R1
FOR i:=1 TO 32 DO
Ri[m,i] := AfterXOR[m,i];
END_FOR
// R0則原封不動的賦給 L1
FOR i:=1 TO 32 DO
Li[m,i] := Ri[m-1,i] ;
END_FOR
// 之後進入下一輪迭代。最後生成L16和R16,其中R16為L15與P盒置換結果做異或運算的結果,L16是R15的直接賦值
END_FOR
// 除錯檢視
// Show();
// 將 L16 和 R16 調換後,合併成 R16L16 (64BIT)
FOR n:=1 TO 64 DO
IF n <= 32 THEN
R16L16[n] :=Ri[16,n];
ELSE
R16L16[n] :=Li[16,n-32];
END_IF
END_FOR
// 對 R16L16 運用 IP-1
FOR i:=1 TO 64 DO
Finally_Result[i] := R16L16[IP_1_Table[i]];
END_FOR
// 顯示密文
FOR i:=0 TO 3 DO
q_Ciphertext[i].15 :=Finally_Result[i*16+1];
q_Ciphertext[i].14 :=Finally_Result[i*16+2];
q_Ciphertext[i].13 :=Finally_Result[i*16+3];
q_Ciphertext[i].12 :=Finally_Result[i*16+4];
q_Ciphertext[i].11 :=Finally_Result[i*16+5];
q_Ciphertext[i].10 :=Finally_Result[i*16+6];
q_Ciphertext[i].9 :=Finally_Result[i*16+7];
q_Ciphertext[i].8 :=Finally_Result[i*16+8];
q_Ciphertext[i].7 :=Finally_Result[i*16+9];
q_Ciphertext[i].6 :=Finally_Result[i*16+10];
q_Ciphertext[i].5 :=Finally_Result[i*16+11];
q_Ciphertext[i].4 :=Finally_Result[i*16+12];
q_Ciphertext[i].3 :=Finally_Result[i*16+13];
q_Ciphertext[i].2 :=Finally_Result[i*16+14];
q_Ciphertext[i].1 :=Finally_Result[i*16+15];
q_Ciphertext[i].0 :=Finally_Result[i*16+16];
END_FOR
除錯檢視的show()程式碼(可有可無)如下:
// 僅僅為了顯示十六進位制,程式設計時檢查程式碼使用
FOR m:=1 TO 16 BY 1 DO
L_Show[m].31 :=Li[m,1];
L_Show[m].30 :=Li[m,2];
L_Show[m].29 :=Li[m,3];
L_Show[m].28 :=Li[m,4];
L_Show[m].27 :=Li[m,5];
L_Show[m].26 :=Li[m,6];
L_Show[m].25 :=Li[m,7];
L_Show[m].24 :=Li[m,8];
L_Show[m].23 :=Li[m,9];
L_Show[m].22 :=Li[m,10];
L_Show[m].21 :=Li[m,11];
L_Show[m].20 :=Li[m,12];
L_Show[m].19 :=Li[m,13];
L_Show[m].18 :=Li[m,14];
L_Show[m].17 :=Li[m,15];
L_Show[m].16 :=Li[m,16];
L_Show[m].15 :=Li[m,17];
L_Show[m].14 :=Li[m,18];
L_Show[m].13 :=Li[m,19];
L_Show[m].12 :=Li[m,20];
L_Show[m].11 :=Li[m,21];
L_Show[m].10 :=Li[m,22];
L_Show[m].9 :=Li[m,23];
L_Show[m].8 :=Li[m,24];
L_Show[m].7 :=Li[m,25];
L_Show[m].6 :=Li[m,26];
L_Show[m].5 :=Li[m,27];
L_Show[m].4 :=Li[m,28];
L_Show[m].3 :=Li[m,29];
L_Show[m].2 :=Li[m,30];
L_Show[m].1 :=Li[m,31];
L_Show[m].0 :=Li[m,32];
R_Show[m].31 :=Ri[m,1];
R_Show[m].30 :=Ri[m,2];
R_Show[m].29 :=Ri[m,3];
R_Show[m].28 :=Ri[m,4];
R_Show[m].27 :=Ri[m,5];
R_Show[m].26 :=Ri[m,6];
R_Show[m].25 :=Ri[m,7];
R_Show[m].24 :=Ri[m,8];
R_Show[m].23 :=Ri[m,9];
R_Show[m].22 :=Ri[m,10];
R_Show[m].21 :=Ri[m,11];
R_Show[m].20 :=Ri[m,12];
R_Show[m].19 :=Ri[m,13];
R_Show[m].18 :=Ri[m,14];
R_Show[m].17 :=Ri[m,15];
R_Show[m].16 :=Ri[m,16];
R_Show[m].15 :=Ri[m,17];
R_Show[m].14 :=Ri[m,18];
R_Show[m].13 :=Ri[m,19];
R_Show[m].12 :=Ri[m,20];
R_Show[m].11 :=Ri[m,21];
R_Show[m].10 :=Ri[m,22];
R_Show[m].9 :=Ri[m,23];
R_Show[m].8 :=Ri[m,24];
R_Show[m].7 :=Ri[m,25];
R_Show[m].6 :=Ri[m,26];
R_Show[m].5 :=Ri[m,27];
R_Show[m].4 :=Ri[m,28];
R_Show[m].3 :=Ri[m,29];
R_Show[m].2 :=Ri[m,30];
R_Show[m].1 :=Ri[m,31];
R_Show[m].0 :=Ri[m,32];
END_FOR
四、資料驗證
編寫程式塊,程式碼如下:
PROGRAM Main
VAR
DES_1: DES;
Exe :BOOL;
//使用者的 64bit 金鑰
{attribute 'displaymode':='hex'}
Key :ARRAY[0..3] OF UINT:=[4916,22393,39868,57329];
// 64bit 明文
{attribute 'displaymode':='hex'}
Data: ARRAY[0..3] OF UINT:=[291,17767,35243,52719];
// TRUE = 加密, FALSE = 解密
Mode :BOOL :=TRUE;
END_VAR
本例使用CFC編寫:
解釋:
明文:Data: ARRAY[0…3] OF UINT:=[291,17767,35243,52719];
金鑰:Key:ARRAY[0…3] OF UINT:=[4916,22393,39868,57329];
明文16進位制顯示為M(Data) = 0123456789ABCDEF
即M(Data) =
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
L(32位) = 0000 0001 0010 0011 0100 0101 0110 0111
R(32位) = 1000 1001 1010 1011 1100 1101 1110 1111
金鑰16進位制顯示為:133457799BBCDFF1
即K(Key) = 00010011 00110100 01010111 01111001 10011011 10111100 11011111 11110001
加密後的結果是 85e813540f0ab405
五、使用其他語言程式設計再次驗證
本例使用Python語言編寫
參考https://blog.csdn.net/qq_43094622/article/details/105251281
import os
IP = [
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
]
IP_I = [
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25
]
S_BOX = [
[
[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
[0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
[4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0],
[15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]
],
[
[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
[3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
[0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
[13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]
],
[
[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
[13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
[13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
[1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]
],
[
[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15],
[13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9],
[10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4],
[3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]
],
[
[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9],
[14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6],
[4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
[11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]
],
[
[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
[10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
[9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
[4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]
],
[
[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1],
[13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
[1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2],
[6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]
],
[
[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7],
[1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
[7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
[2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]
]
]
E_TRANS = [
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1
]
P_TRANS = [
16, 7, 20, 21, 29, 12, 28, 17,
1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9,
19, 13, 30, 6, 22, 11, 4, 25
]
KEY_MOVE = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
KEY_TRANS_1 = [
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4,
]
KEY_TRANS_2 = [
14, 17, 11, 24, 1, 5, 3, 28,
15, 6, 21, 10, 23, 19, 12, 4,
26, 8, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 30, 40,
51, 45, 33, 48, 44, 49, 39, 56,
34, 53, 46, 42, 50, 36, 29, 32
]
def DES(p, key, mode):
p_IP, p_IP_I = 0, 0
# e_trans
p_IP = IP_Trans(p)
print("IP(p): " + hex(p_IP))
# divide p into L and R
L, R = p_IP >> 32, p_IP & (int("0xffffffff", 16))
print("L0: " + hex(L))
print("R0: " + hex(R))
# create key_list
key_list = Key_Creater(key, mode)[:]
# feistel strcture
for i in range(16):
L, R = R, Function(R, key_list[i]) ^ L
print("Round {}: L={}, R={}".format(
i + 1,
hex(L).replace("0x", "").zfill(8),
hex(R).replace("0x", "").zfill(8)))
p = (R << 32) + L
p_IP_I = IP_I_Trans(p)
print("IP_I(p): ", hex(p_IP_I).zfill(16))
return hex(p_IP_I).replace("0x", "").zfill(16)
def Key_Creater(key, mode):
key_list, key_in = [], 0
key_in = PC_1(key)
# divide key_in into C and D
C, D = key_in >> 28, key_in & (int("0xfffffff", 16))
for i in range(16):
# left move
C, D = KeyMove(C, D, i)
key, key_out = (C << 28) + D, 0
# key_trans_2
key_out = PC_2(key)
key_list.append(key_out)
if mode == 2:
key_list.reverse()
return key_list
def IP_Trans(p):
p_IP = 0
# e_trans
for i in range(64):
p_IP <<= 1
if p & (1 << (64 - IP[i])) != 0:
p_IP += 1
return p_IP
def IP_I_Trans(p):
p_IP_I = 0
for i in range(64):
p_IP_I <<= 1
if p & (1 << (64 - IP_I[i])) != 0:
p_IP_I += 1
return p_IP_I
def E_Trans(R):
R_E = 0
# e_trans
for i in range(48):
R_E <<= 1
if R & (1 << (32 - E_TRANS[i])) != 0:
R_E += 1
return R_E
def P_Trans(s_out):
R_P = 0
for i in range(32):
R_P <<= 1
if s_out & (1 << (32 - P_TRANS[i])) != 0:
R_P += 1
return R_P
def S_box(s_in):
extract, s_out = int("0b111111", 2), 0
# s_box
for i in range(8):
s_out <<= 4
# get 6 bits input
s = (s_in >> ((7 - i) * 6)) & extract
# select is used to determine which list will be chose
select = ((s >> 5) << 1) + (s & 1)
index = (s & int("0b011110", 2)) >> 1
s_out += S_BOX[i][select][index]
return s_out
def PC_1(key):
key_in = 0
# key_trans_1
for i in range(56):
key_in <<= 1
if key & (1 << (64 - KEY_TRANS_1[i])) != 0:
key_in += 1
return key_in
def PC_2(key):
key_out = 0
for k in range(48):
key_out <<= 1
if key & (1 << (56 - KEY_TRANS_2[k])) != 0:
key_out += 1
return key_out
def KeyMove(C, D, i):
for j in range(KEY_MOVE[i]):
C = ((C << 1) & int("0xfffffff", 16)) + (C >> 27)
D = ((D << 1) & int("0xfffffff", 16)) + (D >> 27)
return C, D
def Function(R, key):
R_E, R_P = 0, 0
# e_trans
R_E = E_Trans(R)
# s_in is a 48-bit input, extract is used to divide s_in into 8 4-bit pieces
s_in, extract, s_out = R_E ^ key, int("0b111111", 2), 0
# s_box
s_out = S_box(s_in)
# p_trans
R_P = P_Trans(s_out)
return R_P
if __name__ == "__main__":
mode = int(input("mode: [1]crypt [2]decrypt "))
p = int(input("input text: "), 16)
key = int(input("input key: "), 16)
print("\nciphertext is: " + DES(p, key, mode))
os.system("pause")
執行結果:
input text: 0123456789ABCDEF
input key: 133457799BBCDFF1
IP§: 0xcc00ccfff0aaf0aa
L0: 0xcc00ccff
R0: 0xf0aaf0aa
Round 1: L=f0aaf0aa, R=ef4a6544
Round 2: L=ef4a6544, R=cc017709
Round 3: L=cc017709, R=a25c0bf4
Round 4: L=a25c0bf4, R=77220045
Round 5: L=77220045, R=8a4fa637
Round 6: L=8a4fa637, R=e967cd69
Round 7: L=e967cd69, R=064aba10
Round 8: L=064aba10, R=d5694b90
Round 9: L=d5694b90, R=247cc67a
Round 10: L=247cc67a, R=b7d5d7b2
Round 11: L=b7d5d7b2, R=c5783c78
Round 12: L=c5783c78, R=75bd1858
Round 13: L=75bd1858, R=18c3155a
Round 14: L=18c3155a, R=c28c960d
Round 15: L=c28c960d, R=43423234
Round 16: L=43423234, R=0a4cd995
IP_I§: 0x85e813540f0ab405
ciphertext is: 85e813540f0ab405