1. 程式人生 > 其它 >使用PLC程式設計(ST語言)開發的DES加密解密功能塊

使用PLC程式設計(ST語言)開發的DES加密解密功能塊

技術標籤:python程式語言演算法

本例使用施耐德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編寫:
 PLC程式
解釋:
明文: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