C語言實現DES算法


用C語言實現DES(數據加密算法)的一個例子,密文和密鑰都是8個字符。

/*-------------------------------------------------------
      Data Encryption Standard  56位密鑰加密64位數據 
                  2011.10
--------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include "bool.h"   // 位處理 
#include "tables.h"

void BitsCopy(bool *DatOut,bool *DatIn,int Len);  // 數組復制 

void ByteToBit(bool *DatOut,char *DatIn,int Num); // 字節到位 
void BitToByte(char *DatOut,bool *DatIn,int Num); // 位到字節

void BitToHex(char *DatOut,bool *DatIn,int Num);  // 二進制到十六進制 64位 to 4*16字符
void HexToBit(bool *DatOut,char *DatIn,int Num);  // 十六進制到二進制 

void TablePermute(bool *DatOut,bool *DatIn,const char *Table,int Num); // 位表置換函數 
void LoopMove(bool *DatIn,int Len,int Num);     // 循環左移 Len長度 Num移動位數 
void Xor(bool *DatA,bool *DatB,int Num);         // 異或函數 

void S_Change(bool DatOut[32],bool DatIn[48]);   // S盒變換 
void F_Change(bool DatIn[32],bool DatKi[48]);    // F函數                                  

void SetKey(char KeyIn[8]);                         // 設置密鑰
void PlayDes(char MesOut[8],char MesIn[8]);       // 執行DES加密
void KickDes(char MesOut[8],char MesIn[8]);             // 執行DES解密 

 

int main()
{
    int i=0; 
    char MesHex[16]={0};         // 16個字符數組用於存放 64位16進制的密文
     char MyKey[8]={0};           // 初始密鑰 8字節*8
    char YourKey[8]={0};         // 輸入的解密密鑰 8字節*8
    char MyMessage[8]={0};       // 初始明文 
    
/*-----------------------------------------------*/

    printf("Welcome! Please input your Message(64 bit):\n");
    gets(MyMessage);            // 明文
    printf("Please input your Secret Key:\n");
    gets(MyKey);                // 密鑰

    while(MyKey[i]!='\0')        // 計算密鑰長度
    {
        i++;
    }

    while(i!=8)                  // 不是8 提示錯誤
    {
        printf("Please input a correct Secret Key!\n");
        gets(MyKey);
        i=0;
        while(MyKey[i]!='\0')    // 再次檢測
        {
            i++;
        }
    }

    SetKey(MyKey);               // 設置密鑰 得到子密鑰Ki
    
    PlayDes(MesHex,MyMessage);   // 執行DES加密

    printf("Your Message is Encrypted!:\n");  // 信息已加密
    for(i=0;i<16;i++)           
    {
        printf("%c ",MesHex[i]);
    }
    printf("\n");
    printf("\n");
    
    printf("Please input your Secret Key to Deciphering:\n");  // 請輸入密鑰以解密
    gets(YourKey);                                         // 得到密鑰
    SetKey(YourKey);                                       // 設置密鑰

    KickDes(MyMessage,MesHex);                     // 解密輸出到MyMessage
    
    printf("Deciphering Over !!:\n");                     // 解密結束
    for(i=0;i<8;i++)
    {
        printf("%c ",MyMessage[i]);
    }
    printf("\n");
    system("pause");
        
/*------------------------------------------------*/    
}

/*-------------------------------
 把DatIn開始的長度位Len位的二進制
 復制到DatOut后
--------------------------------*/
void BitsCopy(bool *DatOut,bool *DatIn,int Len)     // 數組復制 OK 
{
    int i=0;
    for(i=0;i<Len;i++)
    {
        DatOut[i]=DatIn[i];
    }
}

/*-------------------------------
 字節轉換成位函數 
 每8次換一個字節 每次向右移一位
 和1與取最后一位 共64位 
--------------------------------*/
void ByteToBit(bool *DatOut,char *DatIn,int Num)       // OK
{
    int i=0;
    for(i=0;i<Num;i++)
    {
        DatOut[i]=(DatIn[i/8]>>(i%8))&0x01;   
    }                                       
}

/*-------------------------------
 位轉換成字節函數
 字節數組每8次移一位
 位每次向左移 與上一次或   
---------------------------------*/
void BitToByte(char *DatOut,bool *DatIn,int Num)        // OK
{
    int i=0;
    for(i=0;i<(Num/8);i++)
    {
        DatOut[i]=0;
    } 
    for(i=0;i<Num;i++)
    {
        DatOut[i/8]|=DatIn[i]<<(i%8);    
    }        
}


/*----------------------------------
 二進制密文轉換為十六進制
 需要16個字符表示
-----------------------------------*/
void BitToHex(char *DatOut,bool *DatIn,int Num)
{
    int i=0;
    for(i=0;i<Num/4;i++)
    {
        DatOut[i]=0;
    }
    for(i=0;i<Num/4;i++)
    {
        DatOut[i] = DatIn[i*4]+(DatIn[i*4+1]<<1)
                    +(DatIn[i*4+2]<<2)+(DatIn[i*4+3]<<3);
        if((DatOut[i]%16)>9)
        {
            DatOut[i]=DatOut[i]%16+'7';       //  余數大於9時處理 10-15 to A-F
        }                                     //  輸出字符 
        else
        {
            DatOut[i]=DatOut[i]%16+'0';       //  輸出字符       
        }
    }
    
}

/*---------------------------------------------
 十六進制字符轉二進制
----------------------------------------------*/
void HexToBit(bool *DatOut,char *DatIn,int Num)
{
    int i=0;                        // 字符型輸入 
    for(i=0;i<Num;i++)
    {
        if((DatIn[i/4])>'9')         //  大於9 
        {
            DatOut[i]=((DatIn[i/4]-'7')>>(i%4))&0x01;               
        }
        else
        {
            DatOut[i]=((DatIn[i/4]-'0')>>(i%4))&0x01;     
        } 
    }    
}

// 表置換函數  OK
void TablePermute(bool *DatOut,bool *DatIn,const char *Table,int Num)  
{
    int i=0;
    static bool Temp[256]={0};
    for(i=0;i<Num;i++)                // Num為置換的長度 
    {
        Temp[i]=DatIn[Table[i]-1];  // 原來的數據按對應的表上的位置排列 
    }
    BitsCopy(DatOut,Temp,Num);       // 把緩存Temp的值輸出 
} 

// 子密鑰的移位
void LoopMove(bool *DatIn,int Len,int Num) // 循環左移 Len數據長度 Num移動位數
{
    static bool Temp[256]={0};    // 緩存   OK
    BitsCopy(Temp,DatIn,Num);       // 將數據最左邊的Num位(被移出去的)存入Temp 
    BitsCopy(DatIn,DatIn+Num,Len-Num); // 將數據左邊開始的第Num移入原來的空間
    BitsCopy(DatIn+Len-Num,Temp,Num);  // 將緩存中移出去的數據加到最右邊 
} 

// 按位異或
void Xor(bool *DatA,bool *DatB,int Num)           // 異或函數
{
    int i=0;
    for(i=0;i<Num;i++)
    {
        DatA[i]=DatA[i]^DatB[i];                  // 異或 
    }
} 

// 輸入48位 輸出32位 與Ri異或
void S_Change(bool DatOut[32],bool DatIn[48])     // S盒變換
{
    int i,X,Y;                                    // i為8個S盒 
    for(i=0,Y=0,X=0;i<8;i++,DatIn+=6,DatOut+=4)   // 每執行一次,輸入數據偏移6位 
    {                                              // 每執行一次,輸出數據偏移4位
        Y=(DatIn[0]<<1)+DatIn[5];                          // af代表第幾行
        X=(DatIn[1]<<3)+(DatIn[2]<<2)+(DatIn[3]<<1)+DatIn[4]; // bcde代表第幾列
        ByteToBit(DatOut,&S_Box[i][Y][X],4);      // 把找到的點數據換為二進制    
    }
}

// F函數
void F_Change(bool DatIn[32],bool DatKi[48])       // F函數
{
    static bool MiR[48]={0};             // 輸入32位通過E選位變為48位
    TablePermute(MiR,DatIn,E_Table,48); 
    Xor(MiR,DatKi,48);                   // 和子密鑰異或
    S_Change(DatIn,MiR);                 // S盒變換
    TablePermute(DatIn,DatIn,P_Table,32);   // P置換后輸出
}



void SetKey(char KeyIn[8])               // 設置密鑰 獲取子密鑰Ki 
{
    int i=0;
    static bool KeyBit[64]={0};                // 密鑰二進制存儲空間 
    static bool *KiL=&KeyBit[0],*KiR=&KeyBit[28];  // 前28,后28共56
    ByteToBit(KeyBit,KeyIn,64);                    // 把密鑰轉為二進制存入KeyBit 
    TablePermute(KeyBit,KeyBit,PC1_Table,56);      // PC1表置換 56次
    for(i=0;i<16;i++)
    {
        LoopMove(KiL,28,Move_Table[i]);       // 前28位左移 
        LoopMove(KiR,28,Move_Table[i]);          // 后28位左移 
         TablePermute(SubKey[i],KeyBit,PC2_Table,48); 
         // 二維數組 SubKey[i]為每一行起始地址 
         // 每移一次位進行PC2置換得 Ki 48位 
    }        
}

void PlayDes(char MesOut[8],char MesIn[8])  // 執行DES加密
{                                           // 字節輸入 Bin運算 Hex輸出 
    int i=0;
    static bool MesBit[64]={0};        // 明文二進制存儲空間 64位
    static bool Temp[32]={0};
    static bool *MiL=&MesBit[0],*MiR=&MesBit[32]; // 前32位 后32位 
    ByteToBit(MesBit,MesIn,64);                 // 把明文換成二進制存入MesBit
    TablePermute(MesBit,MesBit,IP_Table,64);    // IP置換 
    for(i=0;i<16;i++)                       // 迭代16次 
    {
        BitsCopy(Temp,MiR,32);            // 臨時存儲
        F_Change(MiR,SubKey[i]);           // F函數變換
        Xor(MiR,MiL,32);                  // 得到Ri 
        BitsCopy(MiL,Temp,32);            // 得到Li 
    }                    
    TablePermute(MesBit,MesBit,IPR_Table,64);
    BitToHex(MesOut,MesBit,64);
}

void KickDes(char MesOut[8],char MesIn[8])       // 執行DES解密
{                                                // Hex輸入 Bin運算 字節輸出 
    int i=0;
    static bool MesBit[64]={0};        // 密文二進制存儲空間 64位
    static bool Temp[32]={0};
    static bool *MiL=&MesBit[0],*MiR=&MesBit[32]; // 前32位 后32位
    HexToBit(MesBit,MesIn,64);                 // 把密文換成二進制存入MesBit
    TablePermute(MesBit,MesBit,IP_Table,64);    // IP置換 
    for(i=15;i>=0;i--)
    {
        BitsCopy(Temp,MiL,32);
        F_Change(MiL,SubKey[i]);
        Xor(MiL,MiR,32);
        BitsCopy(MiR,Temp,32);
    }    
    TablePermute(MesBit,MesBit,IPR_Table,64);
    BitToByte(MesOut,MesBit,64);        
} 

所有源碼下載:10081509&DES.rar


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM