飘云 发表于 2014-4-22 12:54:56

DES/3DES -- CBC模式 -- 飘云修改版


/************************************************************************/
/*DES、3DES CBC加密解密                                             */
/*原作者:不详--仍然表示感谢                                          */
/*修改:飘云(添加 DES CBC模式加密、解密算法)                        */
/************************************************************************/

#include <windows.h>

enum {ENCRYPT, DECRYPT};

//////////////////////////////////////////////////////////////////////////

// 加/解密 Type—ENCRYPT:加密,DECRYPT:解密
void Des_Run(char Out, char In, bool Type = ENCRYPT);
// 设置密钥
void Des_SetKey(const char Key);
int DESede_CBC_decode(byte *lpIndata, int nlen, byte *lpOutData, byte lpK1, byte lpK2, byte lpK3, byte lpvi);
int DESede_CBC_encode(byte *lpIndata, int nlen, byte *lpOutData, byte lpK1, byte lpK2, byte lpK3, byte lpvi);

// DES算法CBC模式 -- 飘云
int DES_CBC_encode(byte *lpIndata,int nlen, byte *lpOutData, byte lpKey, byte lpIV);
int DES_CBC_decode(byte *lpIndata, int nlen, byte *lpOutData, byte lpKey, byte lpIV);

void DES_encode(byte *lpIndata, int nlen, byte *lpOut, byte *lpkey);
void DES_decode(byte *lpIndata, int nlen, byte *lpOut, byte *lpkey);

//////////////////////////////////////////////////////////////////////////





/************************************************************************/
/*DES、3DES CBC加密解密                                             */
/*原作者:不详--仍然表示感谢                                          */
/*修改:飘云(添加 DES CBC模式加密、解密算法)                        */
/************************************************************************/

#include "3DES.h"
#include <stdio.h>

//////////////////////////////////////////////////////////////////////////

static void F_func(bool In, const bool Ki);// f 函数
static void S_func(bool Out, const bool In);// S 盒代替
static void Transform(bool *Out, bool *In, const char *Table, int len);// 变换
static void Xor(bool *InA, const bool *InB, int len);// 异或
static void RotateL(bool *In, int len, int loop);// 循环左移
static void ByteToBit(bool *Out, const char *In, int bits);// 字节组转换成位组
static void BitToByte(char *Out, const bool *In, int bits);// 位组转换成字节组

//////////////////////////////////////////////////////////////////////////

// initial permutation IP
const static char IP_Table = {
        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
};

// final permutation IP^-1
const static char IPR_Table = {
        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
};

// expansion operation matrix
static const char E_Table = {
        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
};

// 32-bit permutation function P used on the output of the S-boxes
const static char P_Table = {
        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
};

// permuted choice table (key)
const static char PC1_Table = {
        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
};

// permuted choice key (table)
const static char PC2_Table = {
        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
};

// number left rotations of pc1
const static char LOOP_Table = {
        1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
};

// The (in)famous S-boxes
const static char S_Box = {
        // S1
        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
    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
    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
   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
   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
    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
   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
    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
};

//////////////////////////////////////////////////////////////////////////

static bool SubKey; // 16圈子密钥

//////////////////////////////////////////////////////////////////////////
void Des_Run(char Out, char In, bool Type)
{
    bool M, Tmp, *Li = &M, *Ri = &M;
    ByteToBit(M, In, 64);
    Transform(M, M, IP_Table, 64);
        if(ENCRYPT != Type)
        {
                bool M2;
                memcpy(M2,M,32);
                memcpy(M,M + 32,32);
                memcpy(M + 32,M2,32);
        }

    if( Type == ENCRYPT ){
      for(int i=0; i<16; i++) {
            memcpy(Tmp, Ri, 32);
            F_func(Ri, SubKey);
            Xor(Ri, Li, 32);
            memcpy(Li, Tmp, 32);
      }
    }else{
      for(int i=15; i>=0; i--) {
            memcpy(Tmp, Li, 32);
            F_func(Li, SubKey);
            Xor(Li, Ri, 32);
            memcpy(Ri, Tmp, 32);
      }
        }
        if(ENCRYPT == Type)
        {
                bool M2;
                memcpy(M2,M,32);
                memcpy(M,M + 32,32);
                memcpy(M + 32,M2,32);
        }
    Transform(M, M, IPR_Table, 64);
    BitToByte(Out, M, 64);
}
void Des_SetKey(const char Key)
{
    bool K, *KL = &K, *KR = &K;
        unsigned char K2;
        ByteToBit((bool*)K2,Key,64);
    Transform(K, (bool *)K2, PC1_Table, 56);
    for(int i=0; i<16; i++) {
      RotateL(KL, 28, LOOP_Table);
      RotateL(KR, 28, LOOP_Table);
      Transform(SubKey, K, PC2_Table, 48);
    }
}
void F_func(bool In, const bool Ki)
{
   bool MR;
    Transform(MR, In, E_Table, 48);
    Xor(MR, Ki, 48);
    S_func(In, MR);
    Transform(In, In, P_Table, 32);
}
void S_func(bool Out, const bool In)
{
    for(char i=0,j,k; i<8; i++,In+=6,Out+=4) {
      j = (In<<1) + In;
      k = (In<<3) + (In<<2) + (In<<1) + In;
                ByteToBit(Out, &S_Box, 4);
    }
}
void Transform(bool *Out, bool *In, const char *Table, int len)
{
    char Tmp;
    for(int i=0; i<len; i++)
      Tmp = (char)In[ Table-1 ];
    memcpy(Out,(bool*)Tmp, len);
}
void Xor(bool *InA, const bool *InB, int len)
{
    for(int i=0; i<len; i++)
      InA ^= InB;
}
void RotateL(bool *In, int len, int loop)
{
    static bool Tmp;
    memcpy(Tmp, In, loop);
    memcpy(In, In+loop, len-loop);
    memcpy(In+len-loop, Tmp, loop);
}
void ByteToBit(bool *Out, const char *In, int bits)
{
        int j = 0;
                if( bits / 8)
                {
                        j = 7;
                }
                else
                {
                        j = 3;
                }
    for(int i=0; i<bits; i++)
        {
      Out = (In>>(j - i%8)) & 1;
        }
}
void BitToByte(char *Out, const bool *In, int bits)
{
    memset(Out, 0, (bits+7)/8);
    for(int i=0; i<bits; i++)
        {
      Out |= In<<(7 - i%8);
        }
}

/**************************************************
//
// 函数名称:                DES_encode
// 函数功能:                标准DES算法ECB模式加密函数
// 函数参数:                lpIndata:        数据       
// 函数参数:                nlen:                数据的长度
// 函数参数:                lpOut:                加密数据
// 函数参数:                lpkey:                DES算法的Key
// 函数返回值:                无
//
************************************************/
void DES_encode(byte *lpIndata,int nlen,byte *lpOut,byte *lpkey)
{
        Des_SetKey((char*)lpkey);
        int i = 0;
        for(i = 0;i < nlen; i += 8)
        {
                Des_Run((char*)(lpOut + i),(char*)(lpIndata + i),ENCRYPT);
        }
}
/**************************************************
//
// 函数名称:                DES_decode
// 函数功能:                标准DES算法ECB模式解密函数
// 函数参数:                lpIndata:        密文数据       
// 函数参数:                nlen:                密文数据的长度
// 函数参数:                lpOut:                解密数据
// 函数参数:                lpkey:                DES算法的Key
// 函数返回值:                无
//
************************************************/
void DES_decode(byte *lpIndata, int nlen, byte *lpOut, byte *lpkey)
{
        Des_SetKey((char*)lpkey);
        int i = 0;
       
        for(i = 0; i < nlen; i += 8)
        {
                Des_Run((char*)(lpOut + i), (char*)(lpIndata + i), DECRYPT);
        }
}

/**************************************************
//
// 函数名称:                DES_CBC_encode
// 函数功能:                DES算法CBC模式的加密算法
// 函数参数:                lpIndata:        数据       
// 函数参数:                nlen:                数据的长度
// 函数参数:                lpOutData:        加密数据
// 函数参数:                lpKey:                DES_CBC算法的Key
// 函数参数:                lpIV:                DES_CBC算法的向量
// 函数返回值:                返回加密后数据的长度
//
************************************************/
int DES_CBC_encode(byte *lpIndata, int nlen, byte *lpOutData, byte lpKey, byte lpIV)
{
        byte *data = (byte*)malloc(nlen + 8);
        int nFillSize = 8 - nlen % 8;
        memcpy(data, lpIndata, nlen);
        int i = 0;
        int nLoop = nlen / 8 + 1;
        for(i = 0; i < nFillSize; i++)
        {
                data = (byte)nFillSize;
        }
        byte bytmp = {0};
        int j = 0;
        for(i = 0; i < 8; i++)
        {
                bytmp = data ^ lpIV;
        }
        memcpy(lpOutData, lpIV, 8);
        for(i = 0; i < nLoop; i)
        {
                DES_encode(bytmp, 8, lpOutData + i * 8, lpKey);
                for(j = 0; j < 8; j++)
                {
                        bytmp = data[(i + 1) * 8 + j] ^ lpOutData;
                }
                i++;
        }
        free(data);
        return nLoop * 8;
}

/**************************************************
//
// 函数名称:                DES_CBC_decode
// 函数功能:                DES算法CBC模式的解密算法
// 函数参数:                lpIndata:        密文数据       
// 函数参数:                nlen:                密文数据的长度
// 函数参数:                lpOutData:        解密数据
// 函数参数:                lpKey:                DES_CBC算法的Key
// 函数参数:                lpIV:                DES_CBC算法的向量
// 函数返回值:                返回解密后数据的长度
//
************************************************/
int DES_CBC_decode(byte *lpIndata, int nlen, byte *lpOutData, byte lpKey, byte lpIV)
{
        int i = 0;
        int nLoop = nlen / 8;
        byte vi = {0};
        int j = 0;
        memcpy(vi, lpIV, 8);
        for(i = 0; i < nLoop; i)
        {
                DES_decode(lpIndata + i * 8, 8, lpOutData + i * 8, lpKey);
                for(j = 0; j < 8; j++)
                {
                        *(byte*)(lpOutData + i * 8 + j) ^= vi;
                }
                memcpy(vi, lpIndata + i * 8, 8);
                i++;
        }
       
        return nlen - lpOutData;
}
/**************************************************
//
// 函数名称:                DESede_CBC_encode
// 函数功能:                3DES算法CBC模式的加密算法
// 函数参数:                lpIndata:        数据       
// 函数参数:                nlen:                数据的长度
// 函数参数:                lpOutData:        加密数据
// 函数参数:                lpk1:                3DES_CBC算法的Key1
// 函数参数:                lpk2:                3DES_CBC算法的Key2
// 函数参数:                lpk3:                3DES_CBC算法的Key3
// 函数参数:                lpvi:                3DES_CBC算法的向量
// 函数返回值:                返回加密后数据的长度
//
************************************************/
int DESede_CBC_encode(byte *lpIndata, int nlen, byte *lpOutData, byte lpK1, byte lpK2, byte lpK3, byte lpIV)
{
        byte *data = (byte*)malloc(nlen + 8);
        int nFillSize = 8 - nlen % 8;
        memcpy(data, lpIndata, nlen);
        int i = 0;
        int nLoop = nlen / 8 + 1;
        for(i = 0; i < nFillSize; i++)
        {
                data = (byte)nFillSize;
        }
        byte bytmp = {0};
        int j = 0;
        for(i = 0; i < 8; i++)
        {
                bytmp = data ^ lpIV;
        }
        memcpy(lpOutData,lpIV,8);
        for(i = 0; i < nLoop; i)
        {
               
                DES_encode(bytmp, 8, data, lpK1);
                DES_decode(data, 8, bytmp, lpK2);
                DES_encode(bytmp, 8, lpOutData + i * 8, lpK3);
                for(j = 0; j < 8; j++)
                {
                        bytmp = data[(i + 1) * 8 + j] ^ lpOutData;
                }
                i++;
        }
        free(data);
        return nLoop * 8;
}


/**************************************************
//
// 函数名称:                DESede_CBC_decode
// 函数功能:                3DES算法CBC模式的解密算法
// 函数参数:                lpIndata:        密文数据       
// 函数参数:                nlen:                密文数据的长度
// 函数参数:                lpOutData:        解密数据
// 函数参数:                lpk1:                3DES_CBC算法的Key1
// 函数参数:                lpk2:                3DES_CBC算法的Key2
// 函数参数:                lpk3:                3DES_CBC算法的Key3
// 函数参数:                lpvi:                3DES_CBC算法的向量
// 函数返回值:                返回解密后数据的长度
//
************************************************/
int DESede_CBC_decode(byte *lpIndata, int nlen, byte *lpOutData, byte lpK1, byte lpK2, byte lpK3, byte lpvi)
{
        int i = 0;
        int nLoop = nlen / 8;
        byte bytmp = {0};
        byte vi = {0};
        int j = 0;
        memcpy(vi,lpvi,8);
        for(i = 0;i < nLoop;i)
        {
                DES_decode(lpIndata + i * 8, 8, bytmp, lpK1);
                DES_encode(bytmp, 8, bytmp, lpK2);
                DES_decode(bytmp, 8, lpOutData + i * 8, lpK3);
                for(j = 0;j < 8;j++)
                {
                        *(byte*)(lpOutData + i * 8 + j) ^= vi;
                }
                memcpy(vi,lpIndata + i * 8,8);
                i++;
        }

        return nlen - lpOutData;
}






#include <windows.h>
#include <stdio.h>
#include "3DES.h"                                                                                                                        

int main(int argc, char* argv[])
{
        byte data = {0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
        byte retdata = {0};
        byte desKey = {0x20, 0x73, 0x12, 0x4d, 0x68, 0x59, 0xdd, 0x4c};
        byte desIV = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
       
        DES_CBC_encode(data, sizeof(data), retdata, desKey, desIV);
        int i = 0;

        printf("DES_CBC_encode:\n");
        for(i = 0; i < sizeof(retdata); i++)
        {
                printf("%.2X\n", retdata);
        }
       
        ZeroMemory(&data, sizeof(data));
        DES_CBC_decode(retdata, sizeof(retdata), data, desKey, desIV);
       
        printf("DES_CBC_decode:\n");
        for(i = 0; i < sizeof(data); i++)
        {
                printf("%.2X\n", data);
        }

        return 0;
}


qfhy123 发表于 2014-4-22 13:25:14

{:sweat:}看不懂是啥东东

sdnyzjzx 发表于 2014-4-22 15:25:20

要是给打个包就更好了{:titter:}

ochchina 发表于 2014-4-23 07:54:37

有点看不懂。。。。。。

lhl8730 发表于 2014-4-23 14:17:21

好东西,....学习了..

924410377 发表于 2014-4-27 18:57:19

学习学习.........

wjrice 发表于 2014-12-8 10:30:10

飘云出品,必属精品!

蓝色天空 发表于 2015-9-16 13:20:56

看不明白,3DES.h 这个文件在哪?

vitamin 发表于 2016-7-4 09:45:43

谢谢分享,最近学习密码学

lucious 发表于 2016-12-24 16:57:54

支持一下!!
页: [1]
查看完整版本: DES/3DES -- CBC模式 -- 飘云修改版