加密算法归类-附上3DES c代码

最近有要用到加密,于是找了一下相关的资料,为了防止忘记,把找到的有用的资料整理一下

一般的加密通常都是块加密,如果要加密超过块大小的数据,就需要涉及填充和链加密模式,一般是以8个字节为单位


作者:爱情小傻蛋
链接:https://www.jianshu.com/p/463e8df0a045
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

对称加密算法

定义

对称加密算法是应用较早的加密算法,技术成熟。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。

优缺点

     优点:算法公开、计算量小、加密速度快、加密效率高。

     缺点:

(1)交易双方都使用同样钥匙,安全性得不到保证。

(2)每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。

常用对称加密算法

基于“对称密钥”的加密算法主要有DES、3DES(TripleDES)、AES、RC2、RC4、RC5和Blowfish等。本文只介绍最常用的对称加密算法DES、3DES(TripleDES)和AES。

DES

概述

DES算法全称为Data Encryption Standard,即数据加密算法,它是IBM公司于1975年研究成功并公开发表的。DES算法的入口参数有三个:Key、Data、Mode。其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密。

算法原理

DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位,其算法主要分为两步:

(1)初始置换

其功能是把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则为将输入的第58位换到第一位,第50位换到第2位……依此类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0是右32位,例:设置换前的输入值为D1D2D3……D64,则经过初始置换后的结果为:L0=D58D50……D8;R0=D57D49……D7。

(2)逆置换

经过16次迭代运算后,得到L16、R16,将此作为输入,进行逆置换,逆置换正好是初始置换的逆运算,由此即得到密文输出。

五种分组模式

电码本模式 Electronic Codebook Book (ECB)

概述
这种模式是将整个明文分成若干段相同的小段,然后对每一小段进行加密。
在这里插入图片描述
特点分析
优点:

简单;
有利于并行计算;
误差不会被传送;
缺点:
不能隐藏明文的模式;
可能对明文进行主动攻击;

/**
*@autho stardust
*@time 2013-10-10
*@param 实现AES五种加密模式的测试
*/
#include <iostream>
using namespace std;

//加密编码过程函数,16位1和0
int dataLen = 16;   //需要加密数据的长度
int encLen = 4;     //加密分段的长度
int encTable[4] = {1,0,1,0};  //置换表
int data[16] = {1,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0}; //明文
int ciphertext[16]; //密文

//切片加密函数
void encode(int arr[])
{
    for(int i=0;i<encLen;i++)
    {
        arr[i] = arr[i] ^ encTable[i];
    }
}

//电码本模式加密,4位分段
void ECB(int arr[])
{
    //数据明文切片
    int a[4][4];
    int dataCount = 0;  //位置变量
    for(int k=0;k<4;k++)
    {
        for(int t=0;t<4;t++)
        {
            a[k][t] = data[dataCount];
            dataCount++;
        }
    }
    dataCount = 0;//重置位置变量
    for(int i=0;i<dataLen;i=i+encLen)
    {
        int r = i/encLen;//行
        int l = 0;//列
        int encQue[4]; //编码片段
        for(int j=0;j<encLen;j++)
        {
            encQue[j] = a[r][l];
            l++;
        }
        encode(encQue); //切片加密
        //添加到密文表中
        for(int p=0;p<encLen;p++)
        {
            ciphertext[dataCount] = encQue[p];
            dataCount++;
        }
    }
    cout<<"ECB加密的密文为:"<<endl;
    for(int t1=0;t1<dataLen;t1++) //输出密文
    {
        if(t1!=0 && t1%4==0)
            cout<<endl;
        cout<<ciphertext[t1]<<" ";
    }
    cout<<endl;
    cout<<"---------------------------------------------"<<endl;
}

密码分组链接模式 Cipher Block Chaining (CBC)

概述
这种模式是先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。
在这里插入图片描述
特点分析
优点:

不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
缺点:
不利于并行计算;
误差传递;
需要初始化向量IV

#include <iostream>
using namespace std;

//加密编码过程函数,16位1和0
int dataLen = 16;   //需要加密数据的长度
int encLen = 4;     //加密分段的长度
int encTable[4] = {1,0,1,0};  //置换表
int data[16] = {1,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0}; //明文
int ciphertext[16]; //密文

//切片加密函数
void encode(int arr[])
{
    for(int i=0;i<encLen;i++)
    {
        arr[i] = arr[i] ^ encTable[i];
    }
}
//CBC
//密码分组链接模式,4位分段
void CBC(int arr[])
{
    //数据明文切片
    int a[4][4];
    int dataCount = 0;  //位置变量
    for(int k=0;k<4;k++)
    {
        for(int t=0;t<4;t++)
        {
            a[k][t] = data[dataCount];
            dataCount++;
        }
    }
    dataCount = 0;//重置位置变量

    int init[4] = {1,1,0,0};  //初始异或运算输入
    //初始异或运算
    for(int i=0;i<dataLen;i=i+encLen)
    {
        int r = i/encLen;//行
        int l = 0;//列
        int encQue[4]; //编码片段
        //初始化异或运算
        for(int k=0;k<encLen;k++)
        {
            a[r][k] = a[r][k] ^ init[k];
        }
         //与Key加密的单切片
        for(int j=0;j<encLen;j++)
        {
            encQue[j] = a[r][j];
        }
        encode(encQue); //切片加密
        //添加到密文表中
        for(int p=0;p<encLen;p++)
        {
            ciphertext[dataCount] = encQue[p];
            dataCount++;
        }
        //变换初始输入
        for(int t=0;t<encLen;t++)
        {
            init[t] = encQue[t];
        }
    }

    cout<<"CBC加密的密文为:"<<endl;
    for(int t1=0;t1<dataLen;t1++) //输出密文
    {
        if(t1!=0 && t1%4==0)
            cout<<endl;
        cout<<ciphertext[t1]<<" ";
    }
    cout<<endl;
    cout<<"---------------------------------------------"<<endl;
}
//CBC
//密码分组链接模式,4位分段
void CBC(int arr[])
{
    //数据明文切片
    int a[4][4];
    int dataCount = 0;  //位置变量
    for(int k=0;k<4;k++)
    {
        for(int t=0;t<4;t++)
        {
            a[k][t] = data[dataCount];
            dataCount++;
        }
    }
    dataCount = 0;//重置位置变量

    int init[4] = {1,1,0,0};  //初始异或运算输入
    //初始异或运算
    for(int i=0;i<dataLen;i=i+encLen)
    {
        int r = i/encLen;//行
        int l = 0;//列
        int encQue[4]; //编码片段
        //初始化异或运算
        for(int k=0;k<encLen;k++)
        {
            a[r][k] = a[r][k] ^ init[k];
        }
         //与Key加密的单切片
        for(int j=0;j<encLen;j++)
        {
            encQue[j] = a[r][j];
        }
        encode(encQue); //切片加密
        //添加到密文表中
        for(int p=0;p<encLen;p++)
        {
            ciphertext[dataCount] = encQue[p];
            dataCount++;
        }
        //变换初始输入
        for(int t=0;t<encLen;t++)
        {
            init[t] = encQue[t];
        }
    }

    cout<<"CBC加密的密文为:"<<endl;
    for(int t1=0;t1<dataLen;t1++) //输出密文
    {
        if(t1!=0 && t1%4==0)
            cout<<endl;
        cout<<ciphertext[t1]<<" ";
    }
    cout<<endl;
    cout<<"---------------------------------------------"<<endl;
}

计算器模式Counter (CTR)

概述
计算器模式不常见,在CTR模式中, 有一个自增的算子,这个算子用密钥加密之后的输出和明文异或的结果得到密文,相当于一次一密。这种加密方式简单快速,安全可靠,而且可以并行加密,但是 在计算器不能维持很长的情况下,密钥只能使用一次 。
CTR的示意图如下所示:
在这里插入图片描述
特点分析
优点:

无填
同明文不同密
每个块单独运算,适合并行运算。
缺点:
可能导致明文攻击。

#include <iostream>
using namespace std;

//加密编码过程函数,16位1和0
int dataLen = 16;   //需要加密数据的长度
int encLen = 4;     //加密分段的长度
int encTable[4] = {1,0,1,0};  //置换表
int data[16] = {1,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0}; //明文
int ciphertext[16]; //密文

//切片加密函数
void encode(int arr[])
{
    for(int i=0;i<encLen;i++)
    {
        arr[i] = arr[i] ^ encTable[i];
    }
}
//CTR
//计算器模式,4位分段
void CTR(int arr[])
{
    //数据明文切片
    int a[4][4];
    int dataCount = 0;  //位置变量
    for(int k=0;k<4;k++)
    {
        for(int t=0;t<4;t++)
        {
            a[k][t] = data[dataCount];
            dataCount++;
        }
    }
    dataCount = 0;//重置位置变量

    int init[4][4] = {{1,0,0,0},{0,0,0,1},{0,0,1,0},{0,1,0,0}};  //算子表
    int l = 0; //明文切片表列
    //初始异或运算
    for(int i=0;i<dataLen;i=i+encLen)
    {
        int r = i/encLen;//行
        int encQue[4]; //编码片段
        //将算子切片
        for(int t=0;t<encLen;t++)
        {
            encQue[t] = init[r][t];
        }
        encode(encQue); //算子与key加密
        //最后的异或运算
        for(int k=0;k<encLen;k++)
        {
            encQue[k] = encQue[k] ^ a[l][k];
        }
        l++;

        //添加到密文表中
        for(int p=0;p<encLen;p++)
        {
            ciphertext[dataCount] = encQue[p];
            dataCount++;
        }
    }

    cout<<"CTR加密的密文为:"<<endl;
    for(int t1=0;t1<dataLen;t1++) //输出密文
    {
        if(t1!=0 && t1%4==0)
            cout<<endl;
        cout<<ciphertext[t1]<<" ";
    }
    cout<<endl;
    cout<<"---------------------------------------------"<<endl;
}

密码反馈模式(Cipher FeedBack (CFB)

在这里插入图片描述
特点分析
优点:

隐藏了明文模式;
分组密码转化为流模式;
可以及时加密传送小于分组的数据;
缺点:
不利于并行计算;
误差传送:一个明文单元损坏影响多个单元;
唯一的IV;。

/**
*@autho stardust
*@time 2013-10-10
*@param 实现AES五种加密模式的测试
*/
#include <iostream>
using namespace std;

//加密编码过程函数,16位1和0
int dataLen = 16;   //需要加密数据的长度
int encLen = 4;     //加密分段的长度
int encTable[4] = {1,0,1,0};  //置换表
int data[16] = {1,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0}; //明文
int ciphertext[16]; //密文

//切片加密函数
void encode(int arr[])
{
    for(int i=0;i<encLen;i++)
    {
        arr[i] = arr[i] ^ encTable[i];
    }
}
//CFB
//密码反馈模式,4位分段
void CFB(int arr[])
{
    //数据明文切片,切成2 * 8 片
    int a[8][2];
    int dataCount = 0;  //位置变量
    for(int k=0;k<8;k++)
    {
        for(int t=0;t<2;t++)
        {
            a[k][t] = data[dataCount];
            dataCount++;
        }
    }
    dataCount = 0;  //恢复初始化设置
    int lv[4] = {1,0,1,1};  //初始设置的位移变量
    int encQue[2]; //K的高两位
    int k[4]; //K

    for(int i=0;i<2 * encLen;i++) //外层加密循环
    {
        //产生K
        for(int vk=0;vk<encLen;vk++)
        {
            k[vk] = lv[vk];
        }
        encode(k);
        for(int k2=0;k2<2;k2++)
        {
            encQue[k2] = k[k2];
        }
        //K与数据明文异或产生密文
        for(int j=0;j<2;j++)
        {
            ciphertext[dataCount] = a[dataCount/2][j] ^ encQue[j];
            dataCount++;
        }
        //lv左移变换
        lv[0] = lv[2];
        lv[1] = lv[3];
        lv[2] = ciphertext[dataCount-2];
        lv[3] = ciphertext[dataCount-1];
    }

    cout<<"CFB加密的密文为:"<<endl;
    for(int t1=0;t1<dataLen;t1++) //输出密文
    {
        if(t1!=0 && t1%4==0)
            cout<<endl;
        cout<<ciphertext[t1]<<" ";
    }
    cout<<endl;
    cout<<"---------------------------------------------"<<endl;
}

输出反馈模式Output FeedBack (OFB)

在这里插入图片描述
特点分析
优点:

同明文不同密文,分组密钥转换为流密码。
缺点:
串行运算不利并行
传输错误可能导致后续传输块错误。

/**
*@autho stardust
*@time 2013-10-10
*@param 实现AES五种加密模式的测试
*/
#include <iostream>
using namespace std;

//加密编码过程函数,16位1和0
int dataLen = 16;   //需要加密数据的长度
int encLen = 4;     //加密分段的长度
int encTable[4] = {1,0,1,0};  //置换表
int data[16] = {1,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0}; //明文
int ciphertext[16]; //密文

//切片加密函数
void encode(int arr[])
{
    for(int i=0;i<encLen;i++)
    {
        arr[i] = arr[i] ^ encTable[i];
    }
}
//OFB
//输出反馈模式,4位分段
void OFB(int arr[])
{
    //数据明文切片,切成2 * 8 片
    int a[8][2];
    int dataCount = 0;  //位置变量
    for(int k=0;k<8;k++)
    {
        for(int t=0;t<2;t++)
        {
            a[k][t] = data[dataCount];
            dataCount++;
        }
    }
    dataCount = 0;  //恢复初始化设置
    int lv[4] = {1,0,1,1};  //初始设置的位移变量
    int encQue[2]; //K的高两位
    int k[4]; //K

    for(int i=0;i<2 * encLen;i++) //外层加密循环
    {
        //产生K
        for(int vk=0;vk<encLen;vk++)
        {
            k[vk] = lv[vk];
        }
        encode(k);
        for(int k2=0;k2<2;k2++)
        {
            encQue[k2] = k[k2];
        }
        //K与数据明文异或产生密文
        for(int j=0;j<2;j++)
        {
            ciphertext[dataCount] = a[dataCount/2][j] ^ encQue[j];
            dataCount++;
        }
        //lv左移变换
        lv[0] = lv[2];
        lv[1] = lv[3];
        lv[2] = encQue[0];
        lv[3] = encQue[1];
    }

    cout<<"CFB加密的密文为:"<<endl;
    for(int t1=0;t1<dataLen;t1++) //输出密文
    {
        if(t1!=0 && t1%4==0)
            cout<<endl;
        cout<<ciphertext[t1]<<" ";
    }
    cout<<endl;
    cout<<"---------------------------------------------"<<endl;
}

常用的填充方式

     在Java进行DES、3DES和AES三种对称加密算法时,常采用的是NoPadding(不填充)、Zeros填充(0填充)、PKCS5Padding填充。

ZerosPadding

全部填充为0的字节,结果如下:

   F1 F2 F3 F4 F5 F6 F7 F8   //第一块

  F9 00 00 00 00 00 00 00 //第二块

PKCS5Padding

每个填充的字节都记录了填充的总字节数,结果如下:

F1 F2 F3 F4 F5 F6 F7 F8 //第一块

F9 07 07 07 07 07 07 07 //第二块

————————————————
版权声明:本文为CSDN博主「MikeEm」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/beyondmike/article/details/95600085

3DES又称Triple DES,是DES加密算法的一种模式,它使用3条56位的密钥对数据进行三次加密。数据加密标准(DES)是美国的一种由来已久的加密标准,它使用对称密钥加密法,并于1981年被ANSI组织规范为ANSI X.3.92。DES使用56位密钥和密码块的方法,而在密码块的方法中,文本被分成64位大小的文本块然后再进行加密。比起最初的DES,3DES更为安全。

3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),加密算法,其具体实现如下:设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,M代表明文,C代表密文,这样:

3DES加密过程为:C=Ek3(Dk2(Ek1(M)))

3DES解密过程为:M=Dk1(EK2(Dk3©))

/*****************************************************************************
FileName : 3des.c
Function : 3DES加密算法
Author   : mike
Email    : hxtiou@163.com	
Version  : V1.0
Date     : 2019-07-12
*****************************************************************************/
#include <string.h>
#include <stdlib.h>
#include "typedef.h"
#include "des3.h"
 
#if USE_DES_EN
typedef struct
{
    uint32_t sk[32];            //DES subkeys
}des_context;
#endif
 
#if USE_3DES_EN
//brief Triple-DES context structure
typedef struct
{
    uint32_t sk[96];            //3DES subkeys
}des3_context;
#endif
 
 
//Implementation that should never be optimized out by the compiler
static void zeroize( void *v, size_t n ) 
{
    volatile unsigned char *p = (unsigned char*)v; 
	while( n-- ) 
		*p++ = 0;
}
 
//32-bit integer manipulation macros (big endian)
#define GET_UINT32_BE(n,b,i)                            \
{                                                       \
    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
        | ( (uint32_t) (b)[(i) + 3]       );            \
}
 
#define PUT_UINT32_BE(n,b,i)                            \
{                                                       \
    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
}
 
//Expanded DES S-boxes
static const uint32_t SB1[64] =
{
    0x01010400, 0x00000000, 0x00010000, 0x01010404,
    0x01010004, 0x00010404, 0x00000004, 0x00010000,
    0x00000400, 0x01010400, 0x01010404, 0x00000400,
    0x01000404, 0x01010004, 0x01000000, 0x00000004,
    0x00000404, 0x01000400, 0x01000400, 0x00010400,
    0x00010400, 0x01010000, 0x01010000, 0x01000404,
    0x00010004, 0x01000004, 0x01000004, 0x00010004,
    0x00000000, 0x00000404, 0x00010404, 0x01000000,
    0x00010000, 0x01010404, 0x00000004, 0x01010000,
    0x01010400, 0x01000000, 0x01000000, 0x00000400,
    0x01010004, 0x00010000, 0x00010400, 0x01000004,
    0x00000400, 0x00000004, 0x01000404, 0x00010404,
    0x01010404, 0x00010004, 0x01010000, 0x01000404,
    0x01000004, 0x00000404, 0x00010404, 0x01010400,
    0x00000404, 0x01000400, 0x01000400, 0x00000000,
    0x00010004, 0x00010400, 0x00000000, 0x01010004
};
 
static const uint32_t SB2[64] =
{
    0x80108020, 0x80008000, 0x00008000, 0x00108020,
    0x00100000, 0x00000020, 0x80100020, 0x80008020,
    0x80000020, 0x80108020, 0x80108000, 0x80000000,
    0x80008000, 0x00100000, 0x00000020, 0x80100020,
    0x00108000, 0x00100020, 0x80008020, 0x00000000,
    0x80000000, 0x00008000, 0x00108020, 0x80100000,
    0x00100020, 0x80000020, 0x00000000, 0x00108000,
    0x00008020, 0x80108000, 0x80100000, 0x00008020,
    0x00000000, 0x00108020, 0x80100020, 0x00100000,
    0x80008020, 0x80100000, 0x80108000, 0x00008000,
    0x80100000, 0x80008000, 0x00000020, 0x80108020,
    0x00108020, 0x00000020, 0x00008000, 0x80000000,
    0x00008020, 0x80108000, 0x00100000, 0x80000020,
    0x00100020, 0x80008020, 0x80000020, 0x00100020,
    0x00108000, 0x00000000, 0x80008000, 0x00008020,
    0x80000000, 0x80100020, 0x80108020, 0x00108000
};
 
static const uint32_t SB3[64] =
{
    0x00000208, 0x08020200, 0x00000000, 0x08020008,
    0x08000200, 0x00000000, 0x00020208, 0x08000200,
    0x00020008, 0x08000008, 0x08000008, 0x00020000,
    0x08020208, 0x00020008, 0x08020000, 0x00000208,
    0x08000000, 0x00000008, 0x08020200, 0x00000200,
    0x00020200, 0x08020000, 0x08020008, 0x00020208,
    0x08000208, 0x00020200, 0x00020000, 0x08000208,
    0x00000008, 0x08020208, 0x00000200, 0x08000000,
    0x08020200, 0x08000000, 0x00020008, 0x00000208,
    0x00020000, 0x08020200, 0x08000200, 0x00000000,
    0x00000200, 0x00020008, 0x08020208, 0x08000200,
    0x08000008, 0x00000200, 0x00000000, 0x08020008,
    0x08000208, 0x00020000, 0x08000000, 0x08020208,
    0x00000008, 0x00020208, 0x00020200, 0x08000008,
    0x08020000, 0x08000208, 0x00000208, 0x08020000,
    0x00020208, 0x00000008, 0x08020008, 0x00020200
};
 
static const uint32_t SB4[64] =
{
    0x00802001, 0x00002081, 0x00002081, 0x00000080,
    0x00802080, 0x00800081, 0x00800001, 0x00002001,
    0x00000000, 0x00802000, 0x00802000, 0x00802081,
    0x00000081, 0x00000000, 0x00800080, 0x00800001,
    0x00000001, 0x00002000, 0x00800000, 0x00802001,
    0x00000080, 0x00800000, 0x00002001, 0x00002080,
    0x00800081, 0x00000001, 0x00002080, 0x00800080,
    0x00002000, 0x00802080, 0x00802081, 0x00000081,
    0x00800080, 0x00800001, 0x00802000, 0x00802081,
    0x00000081, 0x00000000, 0x00000000, 0x00802000,
    0x00002080, 0x00800080, 0x00800081, 0x00000001,
    0x00802001, 0x00002081, 0x00002081, 0x00000080,
    0x00802081, 0x00000081, 0x00000001, 0x00002000,
    0x00800001, 0x00002001, 0x00802080, 0x00800081,
    0x00002001, 0x00002080, 0x00800000, 0x00802001,
    0x00000080, 0x00800000, 0x00002000, 0x00802080
};
 
static const uint32_t SB5[64] =
{
    0x00000100, 0x02080100, 0x02080000, 0x42000100,
    0x00080000, 0x00000100, 0x40000000, 0x02080000,
    0x40080100, 0x00080000, 0x02000100, 0x40080100,
    0x42000100, 0x42080000, 0x00080100, 0x40000000,
    0x02000000, 0x40080000, 0x40080000, 0x00000000,
    0x40000100, 0x42080100, 0x42080100, 0x02000100,
    0x42080000, 0x40000100, 0x00000000, 0x42000000,
    0x02080100, 0x02000000, 0x42000000, 0x00080100,
    0x00080000, 0x42000100, 0x00000100, 0x02000000,
    0x40000000, 0x02080000, 0x42000100, 0x40080100,
    0x02000100, 0x40000000, 0x42080000, 0x02080100,
    0x40080100, 0x00000100, 0x02000000, 0x42080000,
    0x42080100, 0x00080100, 0x42000000, 0x42080100,
    0x02080000, 0x00000000, 0x40080000, 0x42000000,
    0x00080100, 0x02000100, 0x40000100, 0x00080000,
    0x00000000, 0x40080000, 0x02080100, 0x40000100
};
 
static const uint32_t SB6[64] =
{
    0x20000010, 0x20400000, 0x00004000, 0x20404010,
    0x20400000, 0x00000010, 0x20404010, 0x00400000,
    0x20004000, 0x00404010, 0x00400000, 0x20000010,
    0x00400010, 0x20004000, 0x20000000, 0x00004010,
    0x00000000, 0x00400010, 0x20004010, 0x00004000,
    0x00404000, 0x20004010, 0x00000010, 0x20400010,
    0x20400010, 0x00000000, 0x00404010, 0x20404000,
    0x00004010, 0x00404000, 0x20404000, 0x20000000,
    0x20004000, 0x00000010, 0x20400010, 0x00404000,
    0x20404010, 0x00400000, 0x00004010, 0x20000010,
    0x00400000, 0x20004000, 0x20000000, 0x00004010,
    0x20000010, 0x20404010, 0x00404000, 0x20400000,
    0x00404010, 0x20404000, 0x00000000, 0x20400010,
    0x00000010, 0x00004000, 0x20400000, 0x00404010,
    0x00004000, 0x00400010, 0x20004010, 0x00000000,
    0x20404000, 0x20000000, 0x00400010, 0x20004010
};
 
static const uint32_t SB7[64] =
{
    0x00200000, 0x04200002, 0x04000802, 0x00000000,
    0x00000800, 0x04000802, 0x00200802, 0x04200800,
    0x04200802, 0x00200000, 0x00000000, 0x04000002,
    0x00000002, 0x04000000, 0x04200002, 0x00000802,
    0x04000800, 0x00200802, 0x00200002, 0x04000800,
    0x04000002, 0x04200000, 0x04200800, 0x00200002,
    0x04200000, 0x00000800, 0x00000802, 0x04200802,
    0x00200800, 0x00000002, 0x04000000, 0x00200800,
    0x04000000, 0x00200800, 0x00200000, 0x04000802,
    0x04000802, 0x04200002, 0x04200002, 0x00000002,
    0x00200002, 0x04000000, 0x04000800, 0x00200000,
    0x04200800, 0x00000802, 0x00200802, 0x04200800,
    0x00000802, 0x04000002, 0x04200802, 0x04200000,
    0x00200800, 0x00000000, 0x00000002, 0x04200802,
    0x00000000, 0x00200802, 0x04200000, 0x00000800,
    0x04000002, 0x04000800, 0x00000800, 0x00200002
};
 
static const uint32_t SB8[64] =
{
    0x10001040, 0x00001000, 0x00040000, 0x10041040,
    0x10000000, 0x10001040, 0x00000040, 0x10000000,
    0x00040040, 0x10040000, 0x10041040, 0x00041000,
    0x10041000, 0x00041040, 0x00001000, 0x00000040,
    0x10040000, 0x10000040, 0x10001000, 0x00001040,
    0x00041000, 0x00040040, 0x10040040, 0x10041000,
    0x00001040, 0x00000000, 0x00000000, 0x10040040,
    0x10000040, 0x10001000, 0x00041040, 0x00040000,
    0x00041040, 0x00040000, 0x10041000, 0x00001000,
    0x00000040, 0x10040040, 0x00001000, 0x00041040,
    0x10001000, 0x00000040, 0x10000040, 0x10040000,
    0x10040040, 0x10000000, 0x00040000, 0x10001040,
    0x00000000, 0x10041040, 0x00040040, 0x10000040,
    0x10040000, 0x10001000, 0x10001040, 0x00000000,
    0x10041040, 0x00041000, 0x00041000, 0x00001040,
    0x00001040, 0x00040040, 0x10000000, 0x10041000
};
 
/*
 * PC1: left and right halves bit-swap
 */
static const uint32_t LHs[16] =
{
    0x00000000, 0x00000001, 0x00000100, 0x00000101,
    0x00010000, 0x00010001, 0x00010100, 0x00010101,
    0x01000000, 0x01000001, 0x01000100, 0x01000101,
    0x01010000, 0x01010001, 0x01010100, 0x01010101
};
 
static const uint32_t RHs[16] =
{
    0x00000000, 0x01000000, 0x00010000, 0x01010000,
    0x00000100, 0x01000100, 0x00010100, 0x01010100,
    0x00000001, 0x01000001, 0x00010001, 0x01010001,
    0x00000101, 0x01000101, 0x00010101, 0x01010101,
};
 
/*
 * Initial Permutation macro
 */
#define DES_IP(X,Y)                                             \
{                                                               \
    T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
    T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
    T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
    T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
    Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF;                    \
    T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T;                   \
    X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF;                    \
}
 
/*
 * Final Permutation macro
 */
#define DES_FP(X,Y)                                             \
{                                                               \
    X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF;                    \
    T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T;                   \
    Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF;                    \
    T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
    T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
    T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
    T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
}
 
/*
 * DES round macro
 */
#define DES_ROUND(X,Y)                          \
{                                               \
    T = *SK++ ^ X;                              \
    Y ^= SB8[ (T      ) & 0x3F ] ^              \
         SB6[ (T >>  8) & 0x3F ] ^              \
         SB4[ (T >> 16) & 0x3F ] ^              \
         SB2[ (T >> 24) & 0x3F ];               \
                                                \
    T = *SK++ ^ ((X << 28) | (X >> 4));         \
    Y ^= SB7[ (T      ) & 0x3F ] ^              \
         SB5[ (T >>  8) & 0x3F ] ^              \
         SB3[ (T >> 16) & 0x3F ] ^              \
         SB1[ (T >> 24) & 0x3F ];               \
}
 
#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; }
 
#if USE_DES_EN
void des_init( des_context *ctx )
{
    memset( ctx, 0, sizeof( des_context ) );
}
 
void des_free( des_context *ctx )
{
    if( ctx == NULL )
        return;
 
    zeroize( ctx, sizeof( des_context ) );
}
#endif
 
#if USE_3DES_EN
void des3_init( des3_context *ctx )
{
    memset( ctx, 0, sizeof( des3_context ) );
}
 
void des3_free( des3_context *ctx )
{
    if( ctx == NULL )
        return;
 
    zeroize( ctx, sizeof( des3_context ) );
}
#endif
 
#if 0
static const unsigned char odd_parity_table[128] = { 1,  2,  4,  7,  8,
        11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
        47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
        82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
        115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
        143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
        171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
        199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
        227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
        254 };
 
void des_key_set_parity( unsigned char key[DES_KEY_SIZE] )
{
    int i;
 
    for( i = 0; i < DES_KEY_SIZE; i++ )
        key[i] = odd_parity_table[key[i] / 2];
}
 
//Check the given key's parity, returns 1 on failure, 0 on SUCCESS
int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] )
{
    int i;
 
    for( i = 0; i < DES_KEY_SIZE; i++ )
        if( key[i] != odd_parity_table[key[i] / 2] )
            return( 1 );
 
    return( 0 );
}
#endif //#if 0
 
/*
 * Table of weak and semi-weak keys
 *
 * Source: http://en.wikipedia.org/wiki/Weak_key
 *
 * Weak:
 * Alternating ones + zeros (0x0101010101010101)
 * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
 * '0xE0E0E0E0F1F1F1F1'
 * '0x1F1F1F1F0E0E0E0E'
 *
 * Semi-weak:
 * 0x011F011F010E010E and 0x1F011F010E010E01
 * 0x01E001E001F101F1 and 0xE001E001F101F101
 * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
 * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
 * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
 * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
 *
 */
#if 0
#define WEAK_KEY_COUNT 16
static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] =
{
    { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
    { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
    { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
    { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
 
    { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
    { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
    { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
    { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
    { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
    { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
    { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
    { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
    { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
    { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
    { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
    { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
};
 
int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] )
{
    int i;
 
    for( i = 0; i < WEAK_KEY_COUNT; i++ )
        if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0 )
            return( 1 );
 
    return( 0 );
}
#endif
 
void des_setkey( uint32_t SK[32], const unsigned char key[DES_KEY_SIZE] )
{
    int i;
    uint32_t X, Y, T;
 
    GET_UINT32_BE( X, key, 0 );
    GET_UINT32_BE( Y, key, 4 );
 
    /*
     * Permuted Choice 1
     */
    T =  ((Y >>  4) ^ X) & 0x0F0F0F0F;  X ^= T; Y ^= (T <<  4);
    T =  ((Y      ) ^ X) & 0x10101010;  X ^= T; Y ^= (T      );
 
    X =   (LHs[ (X      ) & 0xF] << 3) | (LHs[ (X >>  8) & 0xF ] << 2)
        | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ]     )
        | (LHs[ (X >>  5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
        | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
 
    Y =   (RHs[ (Y >>  1) & 0xF] << 3) | (RHs[ (Y >>  9) & 0xF ] << 2)
        | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ]     )
        | (RHs[ (Y >>  4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
        | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
 
    X &= 0x0FFFFFFF;
    Y &= 0x0FFFFFFF;
 
    //calculate subkeys
    for( i = 0; i < 16; i++ )
    {
        if( i < 2 || i == 8 || i == 15 )
        {
            X = ((X <<  1) | (X >> 27)) & 0x0FFFFFFF;
            Y = ((Y <<  1) | (Y >> 27)) & 0x0FFFFFFF;
        }
        else
        {
            X = ((X <<  2) | (X >> 26)) & 0x0FFFFFFF;
            Y = ((Y <<  2) | (Y >> 26)) & 0x0FFFFFFF;
        }
 
        *SK++ =   ((X <<  4) & 0x24000000) | ((X << 28) & 0x10000000)
                | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
                | ((X <<  6) & 0x01000000) | ((X <<  9) & 0x00200000)
                | ((X >>  1) & 0x00100000) | ((X << 10) & 0x00040000)
                | ((X <<  2) & 0x00020000) | ((X >> 10) & 0x00010000)
                | ((Y >> 13) & 0x00002000) | ((Y >>  4) & 0x00001000)
                | ((Y <<  6) & 0x00000800) | ((Y >>  1) & 0x00000400)
                | ((Y >> 14) & 0x00000200) | ((Y      ) & 0x00000100)
                | ((Y >>  5) & 0x00000020) | ((Y >> 10) & 0x00000010)
                | ((Y >>  3) & 0x00000008) | ((Y >> 18) & 0x00000004)
                | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
 
        *SK++ =   ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
                | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
                | ((X >>  2) & 0x02000000) | ((X <<  1) & 0x01000000)
                | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
                | ((X <<  3) & 0x00080000) | ((X >>  6) & 0x00040000)
                | ((X << 15) & 0x00020000) | ((X >>  4) & 0x00010000)
                | ((Y >>  2) & 0x00002000) | ((Y <<  8) & 0x00001000)
                | ((Y >> 14) & 0x00000808) | ((Y >>  9) & 0x00000400)
                | ((Y      ) & 0x00000200) | ((Y <<  7) & 0x00000100)
                | ((Y >>  7) & 0x00000020) | ((Y >>  3) & 0x00000011)
                | ((Y <<  2) & 0x00000004) | ((Y >> 21) & 0x00000002);
    }
}
 
#if USE_DES_EN
//DES key schedule (56-bit, encryption)
int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
{
    des_setkey( ctx->sk, key );
 
    return( 0 );
}
 
//DES key schedule (56-bit, decryption)
int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
{
    int i;
 
    des_setkey( ctx->sk, key );
 
    for( i = 0; i < 16; i += 2 )
    {
        SWAP( ctx->sk[i    ], ctx->sk[30 - i] );
        SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
    }
 
    return( 0 );
}
#endif //#if USE_DES_EN
 
#if USE_3DES_EN
static void des3_set2key( uint32_t esk[96],
                          uint32_t dsk[96],
                          const unsigned char key[DES_KEY_SIZE*2] )
{
    int i;
 
    des_setkey( esk, key );
    des_setkey( dsk + 32, key + 8 );
 
    for( i = 0; i < 32; i += 2 )
    {
        dsk[i     ] = esk[30 - i];
        dsk[i +  1] = esk[31 - i];
 
        esk[i + 32] = dsk[62 - i];
        esk[i + 33] = dsk[63 - i];
 
        esk[i + 64] = esk[i    ];
        esk[i + 65] = esk[i + 1];
 
        dsk[i + 64] = dsk[i    ];
        dsk[i + 65] = dsk[i + 1];
    }
}
 
/*
 * Triple-DES key schedule (112-bit, encryption)
 */
int des3_set2key_enc( des3_context *ctx,
                      const unsigned char key[DES_KEY_SIZE * 2] )
{
    uint32_t sk[96];
 
    des3_set2key( ctx->sk, sk, key );
    zeroize( sk,  sizeof( sk ) );
 
    return( 0 );
}
 
/*
 * Triple-DES key schedule (112-bit, decryption)
 */
int des3_set2key_dec( des3_context *ctx,
                      const unsigned char key[DES_KEY_SIZE * 2] )
{
    uint32_t sk[96];
 
    des3_set2key( sk, ctx->sk, key );
    zeroize( sk,  sizeof( sk ) );
 
    return( 0 );
}
 
static void des3_set3key( uint32_t esk[96],
                          uint32_t dsk[96],
                          const unsigned char key[24] )
{
    int i;
 
    des_setkey( esk, key );
    des_setkey( dsk + 32, key +  8 );
    des_setkey( esk + 64, key + 16 );
 
    for( i = 0; i < 32; i += 2 )
    {
        dsk[i     ] = esk[94 - i];
        dsk[i +  1] = esk[95 - i];
 
        esk[i + 32] = dsk[62 - i];
        esk[i + 33] = dsk[63 - i];
 
        dsk[i + 64] = esk[30 - i];
        dsk[i + 65] = esk[31 - i];
    }
}
 
/*
 * Triple-DES key schedule (168-bit, encryption)
 */
int des3_set3key_enc( des3_context *ctx,
                      const unsigned char key[DES_KEY_SIZE * 3] )
{
    uint32_t sk[96];
 
    des3_set3key( ctx->sk, sk, key );
    zeroize( sk,  sizeof( sk ) );
 
    return( 0 );
}
 
/*
 * Triple-DES key schedule (168-bit, decryption)
 */
int des3_set3key_dec( des3_context *ctx,
                      const unsigned char key[DES_KEY_SIZE * 3] )
{
    uint32_t sk[96];
 
    des3_set3key( sk, ctx->sk, key );
    zeroize( sk,  sizeof( sk ) );
 
    return( 0 );
}
#endif //#if USE_3DES_EN
 
/*
 * DES-ECB block encryption/decryption
 */
 
#if USE_DES_EN
#if (USE_DES_ECB_EN || USE_DES_CBC_EN)
int des_crypt_ecb( des_context *ctx,
                    const unsigned char input[8],
                    unsigned char output[8] )
{
    int i;
    uint32_t X, Y, T, *SK;
 
    SK = ctx->sk;
 
    GET_UINT32_BE( X, input, 0 );
    GET_UINT32_BE( Y, input, 4 );
 
    DES_IP( X, Y );
 
    for( i = 0; i < 8; i++ )
    {
        DES_ROUND( Y, X );
        DES_ROUND( X, Y );
    }
 
    DES_FP( Y, X );
 
    PUT_UINT32_BE( Y, output, 0 );
    PUT_UINT32_BE( X, output, 4 );
 
    return( 0 );
}
#endif //#if (USE_DES_ECB_EN || USE_DES_CBC_EN)
 
#if USE_DES_ECB_EN
//DES-ECB buffer encryption API
unsigned int des_ecb_encrypt(unsigned char *pout,
                             unsigned char *pdata,
                             unsigned int nlen,
                             unsigned char *pkey)
{
    unsigned char *tmp;
    unsigned int len,i;
    unsigned char ch = '\0';
    des_context ctx;
 
    des_setkey_enc( &ctx, pkey );
 
    len = (nlen / 8 + (nlen % 8 ? 1: 0)) * 8;
 
    //ch = 8 - nlen % 8;
    for(i = 0;i < nlen;i += 8)
    {
        des_crypt_ecb( &ctx, (pdata + i), (pout + i) );
    }
    if(len > nlen)
    {
        tmp = (unsigned char *)malloc(len);
        i -= 8;
        memcpy(tmp,pdata + i,nlen - i);
        memset(tmp + nlen % 8, ch, (8 - nlen % 8) % 8);
        des_crypt_ecb( &ctx, tmp, (pout + i));
        free(tmp);
    }
 
    des_free( &ctx );
    return len;
 
 
}
 
//DES-ECB buffer decryption API
unsigned int des_ecb_decrypt(unsigned char *pout,
                             unsigned char *pdata,
                             unsigned int nlen,
                             unsigned char *pkey)
{
 
    unsigned int i;
    des_context ctx;
 
    if(nlen % 8)
        return 1;
 
    des_setkey_dec( &ctx, pkey );
 
 
    for(i = 0;i < nlen;i += 8)
    {
        des_crypt_ecb(&ctx, (pdata + i), (pout + i));
    }
    des_free( &ctx );
    return 0;
 
}
#endif //#if USE_DES_ECB_EN
 
#if USE_DES_CBC_EN
//DES-CBC buffer encryption/decryption
int des_crypt_cbc( des_context *ctx,
                    int mode,
                    size_t length,
                    unsigned char iv[8],
                    const unsigned char *input,
                    unsigned char *output )
{
    int i;
    unsigned char temp[8];
 
    if( length % 8 )
        return( 1 );//原来的MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH未定义,找个代替的
 
    if( mode == MBEDTLS_DES_ENCRYPT )
    {
        while( length > 0 )
        {
            for( i = 0; i < 8; i++ )
                output[i] = (unsigned char)( input[i] ^ iv[i] );
 
            des_crypt_ecb( ctx, output, output );
            memcpy( iv, output, 8 );
 
            input  += 8;
            output += 8;
            length -= 8;
        }
    }
    else /* MBEDTLS_DES_DECRYPT */
    {
        while( length > 0 )
        {
            memcpy( temp, input, 8 );
            des_crypt_ecb( ctx, input, output );
 
            for( i = 0; i < 8; i++ )
                output[i] = (unsigned char)( output[i] ^ iv[i] );
 
            memcpy( iv, temp, 8 );
 
            input  += 8;
            output += 8;
            length -= 8;
        }
    }
 
    return( 0 );
}
 
//DES-CBC buffer encryption API
unsigned int des_cbc_encrypt(unsigned char *pout,
                             unsigned char *pdata,
                             unsigned int nlen,
                             unsigned char *pkey,
                             unsigned char *piv)
{
    des_context ctx;
    unsigned char iv[8] = {0};
    unsigned char *pivb;
 
    if(piv == NULL)
        pivb = iv;
    else
        pivb = piv;
 
    des_setkey_enc( &ctx, pkey );
 
    des_crypt_cbc( &ctx, 1, nlen, pivb, pdata, (pout));
 
    des_free( &ctx );
 
    return nlen;
 
 
}
/*
 * DES-CBC buffer decryption API
 */
unsigned int des_cbc_decrypt(unsigned char *pout,
                             unsigned char *pdata,
                             unsigned int nlen,
                             unsigned char *pkey,
                             unsigned char *piv)
{
 
    des_context ctx;
    unsigned char iv[8] = {0};
    unsigned char *pivb;
 
    if(piv == NULL)
        pivb = iv;
    else
        pivb = piv;
 
    des_setkey_dec( &ctx, pkey );
 
    des_crypt_cbc( &ctx, 0, nlen, pivb, pdata, (pout));
 
    des_free( &ctx );
 
    return 0;
 
}
#endif //#if USE_DES_CBC_EN
#endif //#if USE_DES_EN
 
 
#if USE_3DES_EN
#if (USE_3DES_ECB_EN || USE_3DES_CBC_EN)
//3DES-ECB block encryption/decryption
int des3_crypt_ecb( des3_context *ctx,
                     const unsigned char input[8],
                     unsigned char output[8] )
{
    int i;
    uint32_t X, Y, T, *SK;
 
    SK = ctx->sk;
 
    GET_UINT32_BE( X, input, 0 );
    GET_UINT32_BE( Y, input, 4 );
 
    DES_IP( X, Y );
 
    for( i = 0; i < 8; i++ )
    {
        DES_ROUND( Y, X );
        DES_ROUND( X, Y );
    }
 
    for( i = 0; i < 8; i++ )
    {
        DES_ROUND( X, Y );
        DES_ROUND( Y, X );
    }
 
    for( i = 0; i < 8; i++ )
    {
        DES_ROUND( Y, X );
        DES_ROUND( X, Y );
    }
 
    DES_FP( Y, X );
 
    PUT_UINT32_BE( Y, output, 0 );
    PUT_UINT32_BE( X, output, 4 );
 
    return( 0 );
}
#endif //#if (USE_3DES_ECB_EN || USE_3DES_CBC_EN)
 
#if USE_3DES_ECB_EN
//3DES-ECB buffer encryption API
unsigned int des3_ecb_encrypt(unsigned char *pout,
                              unsigned char *pdata,
                              unsigned int nlen,
                              unsigned char *pkey,
                              unsigned int klen)
{
    unsigned char *tmp;
    unsigned int len,i;
    unsigned char ch = '\0';
    des3_context ctx3;
 
    if(klen == DES3_KEY2_SIZE)//16字节
        des3_set2key_enc( &ctx3, pkey );//根据长度设置key
    else if(klen == DES3_KEY3_SIZE)//24字节
        des3_set3key_enc( &ctx3, pkey );
 
    len = (nlen / 8 + (nlen % 8 ? 1: 0)) * 8;
 
    //ch = 8 - nlen % 8;//可以设置补齐内容,常用0或0xFF
    for(i = 0;i < nlen;i += 8)
    {
        des3_crypt_ecb( &ctx3, (pdata + i), (pout + i) );
    }
    if(len > nlen)//不足8字节补齐
    {
        tmp = (unsigned char *)malloc(len);
        i -= 8;
        memcpy(tmp,pdata + i,nlen - i);
        memset(tmp + nlen % 8, ch, (8 - nlen % 8) % 8);
        des3_crypt_ecb( &ctx3, tmp, (pout + i));
        free(tmp);
    }
 
    des3_free( &ctx3 );
    return len;
 
 
}
 
// 3DES-ECB buffer decryption API
unsigned int des3_ecb_decrypt(unsigned char *pout,
                              unsigned char *pdata,
                              unsigned int nlen,
                              unsigned char *pkey,
                              unsigned int klen)
{
 
    unsigned int i;
    des3_context ctx3;
 
    if(nlen % 8)
        return 1;
 
    if(klen == DES3_KEY2_SIZE)
        des3_set2key_dec( &ctx3, pkey );
    else if(klen == DES3_KEY3_SIZE)
        des3_set3key_dec( &ctx3, pkey );
 
 
    for(i = 0;i < nlen;i += 8)
    {
        des3_crypt_ecb(&ctx3, (pdata + i), (pout + i));
    }
    des3_free( &ctx3 );
    return 0;
 
}
#endif //#if USE_3DES_ECB_EN
 
 
#if USE_3DES_CBC_EN
//3DES-CBC buffer encryption/decryption
int des3_crypt_cbc( des3_context *ctx,
                     int mode,
                     size_t length,
                     unsigned char iv[8],
                     const unsigned char *input,
                     unsigned char *output )
{
    int i;
    unsigned char temp[8];
 
    if( length % 8 )
        return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH );
 
    if( mode == MBEDTLS_DES_ENCRYPT )
    {
        while( length > 0 )
        {
            for( i = 0; i < 8; i++ )
                output[i] = (unsigned char)( input[i] ^ iv[i] );
 
            des3_crypt_ecb( ctx, output, output );
            memcpy( iv, output, 8 );
 
            input  += 8;
            output += 8;
            length -= 8;
        }
    }
    else /* DES_DECRYPT */
    {
        while( length > 0 )
        {
            memcpy( temp, input, 8 );
            des3_crypt_ecb( ctx, input, output ); //des3_crypt_cbc( ctx, 1, length, iv, temp, output);
            for( i = 0; i < 8; i++ )
                output[i] = (unsigned char)( output[i] ^ iv[i] );
 
            memcpy( iv, temp, 8 );
 
            input  += 8;
            output += 8;
            length -= 8;
        }
    }
 
    return( 0 );
}
 
//3DES-CBC buffer encryption API
unsigned int des3_cbc_encrypt(unsigned char *pout,
                              unsigned char *pdata,
                              unsigned int nlen,
                              unsigned char *pkey,
                              unsigned int klen,
                              unsigned char *piv)
{
    des3_context ctx;
    unsigned char iv[8] = {0};
    unsigned char *pivb;
    unsigned int len;
    unsigned char *tmp;
 
    if(piv == NULL)
        pivb = iv;
    else
        pivb = piv;
 
    if(klen == DES3_KEY2_SIZE)
        des3_set2key_enc( &ctx, pkey );
    else if(klen == DES3_KEY3_SIZE)
        des3_set3key_enc( &ctx, pkey );
 
    if(nlen % 8)
    {
        len = nlen + 8 - nlen % 8;
        tmp = (unsigned char *)calloc(1, len);
        memcpy(tmp, pdata, nlen);
        des3_crypt_cbc( &ctx, 1, len, pivb, tmp, (pout));
        free(tmp);
    }
    else
    {
        des3_crypt_cbc( &ctx, 1, nlen, pivb, pdata, (pout));
    }
 
    des3_free( &ctx );
 
    return nlen;
 
 
}
 
//3DES-CBC buffer decryption API
unsigned int des3_cbc_decrypt(unsigned char *pout,
                              unsigned char *pdata,
                              unsigned int nlen,
                              unsigned char *pkey,
                              unsigned int klen,
                              unsigned char *piv)
{
 
    des3_context ctx;
    unsigned char iv[8] = {0};
    unsigned char *pivb;
 
    if(nlen % 8)
        return 1;
 
    if(piv == NULL)
        pivb = iv;
    else
        pivb = piv;
 
    if(klen == DES3_KEY2_SIZE)
        des3_set2key_dec( &ctx, pkey );
    else if(klen == DES3_KEY3_SIZE)
        des3_set3key_dec( &ctx, pkey );
 
    des3_crypt_cbc( &ctx, 0, nlen, pivb, pdata, (pout));
 
    des3_free( &ctx );
 
    return 0;
}
#endif //#if USE_3DES_CBC_EN
#endif //#if USE_3DES_EN
 
 
//这些函数接口可以直接调用,很方便,代码内容也比较清晰,结合DES的算法原理很容易理解
//main函数测试
int des_test_self(void)
{
    int ret = 0;
    int len = 0;
    int i = 0;
 
    unsigned char buff[1024] = {0};
    
	unsigned char data []= {0x20,0x16,0x08,0x24,0x15,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};	//明文
	
	unsigned char key []= {0x5D,0xFE,0xB0,0xBC,0xCF,0x04,0x0F,0x5D,0x65,0x80,0xF7,0xE0,0xAB,0x60,0x14,0xD9};		//秘钥
 
    //len = strlen((char*)data); //strlen计算长度错误,遇到连续两个0会终止计算
    len = (((sizeof(data)-2)/ 8+1 )*8); //计算明文长度
	ret = (len / 8 + (len % 8 ? 1: 0)) * 8;
 
	//printf("len = %d\n",len);
	printf("明文数据 = ");
    for(i = 0;i < len;i++)
    {
        printf("%02X",data[i]); //打印明文
    }
    printf("\n");
 
#if USE_DES_EN
#if USE_DES_ECB_EN
    //DES ECB 加密
    printf("DES ECB ENC = ");
    ret = des_ecb_encrypt(buff,data,len,key);
    for(i = 0;i < ret;i++)
    {
        printf("%02X",buff[i]);
    }
    printf("\n");
    //DES ECB 解密
    printf("DES ECB DEC = ");
    memset(data,0,sizeof(data));
    des_ecb_decrypt(data,buff,ret,key);
    for(i = 0;i < ret;i++)
    {
        printf("%02X",data[i]);
    }
    printf("\n");
#endif //#if USE_DES_ECB_EN
 
#if USE_DES_CBC_EN
    //DES CBC 加密
    printf("DES CBC ENC = ");
    memset(buff,0,sizeof(buff));
    des_cbc_encrypt(buff,data,ret,key,NULL);
    for(i = 0;i < ret;i++)
    {
        printf("%02X",buff[i]);
    }
    printf("\n");
 
    //DES CBC 解密
    printf("DES CBC DEC = ");
    memset(data,0,sizeof(data));
    des_cbc_decrypt(data,buff,ret,key,NULL);
    for(i = 0;i < ret;i++)
    {
        printf("%02X",data[i]);
    }
    printf("\n");
    printf("\n");
#endif //#if USE_DES_CBC_EN
#endif //#if USE_DES_EN
 
#if USE_3DES_EN
#if USE_3DES_ECB_EN //明文8byte使用ECB和CBC都可以 ,16byte使用ECB
    //3DES ECB 加密
    printf("3DES ECB ENC = ");
    ret = des3_ecb_encrypt(buff,data,len,key,16);
    for(i = 0;i < ret;i++)
    {
        printf("%02X",buff[i]);
    }
    printf("\n");
    //3DES ECB 解密
    printf("3DES ECB DEC = ");
    memset(data,0,sizeof(data));
    des3_ecb_decrypt(data,buff,ret,key,16);
    for(i = 0;i < ret;i++)
    {
        printf("%02X",data[i]);
    }
    printf("\n");
#endif //#if USE_3DES_ECB_EN
 
#if USE_3DES_CBC_EN
    //3DES CBC 加密
    printf("3DES CBC ENC = ");
    memset(buff,0,sizeof(buff));
 
	//printf("ret = %d\n", ret);
    des3_cbc_encrypt(buff,data,ret,key,16,NULL);
    for(i = 0;i < ret;i++)
    {
        printf("%02X",buff[i]);
    }
    printf("\n");
 
    //3DES CBC 解密
    printf("3DES CBC DEC = ");
    memset(data,0,sizeof(data));
    des3_cbc_decrypt(data,buff,ret,key,16,NULL);
    for(i = 0;i < ret;i++)
    {
        printf("%02X",data[i]);
    }
    printf("\n");
#endif //#if USE_3DES_CBC_EN
#endif //#if USE_3DES_EN
 
    return 0;
}
 
 
 
int main()
{
	des_test_self();
 
	getchar();
 
	return 0;
}
 
 

/*****************************************************************************
 * Module    : 
 * File      : des3.h
 * Author    : Mike
 * Email     : 
 * Function  : 常用的类型定义
 *****************************************************************************/
#ifndef DES3_H
#define DES3_H
 
#define MBEDTLS_DES_ENCRYPT			1  
#define MBEDTLS_DES_DECRYPT			0  
 
 
#define USE_DES_EN					0 //使用DES
#define USE_DES_ECB_EN				0 //使用DES的ECB模式
#define USE_DES_CBC_EN				0 //使用DES的CBC模式
 
#define USE_3DES_EN					1 //使用3DES
#define USE_3DES_ECB_EN				1 //使用3DES的ECB模式
#define USE_3DES_CBC_EN				0 //使用3DES的CBC模式
 
#define DES_INPUT_LENGTH			-0x0002 //The data input has an invalid length
 
#define MBEDTLS_DES_KEY_SIZE		8  
#define DES_KEY_SIZE				(8)  
#define DES3_KEY2_SIZE				(16)  
#define DES3_KEY3_SIZE				(24) 
 
 
#if USE_DES_EN
#if USE_DES_ECB_EN
unsigned int des_ecb_encrypt(unsigned char *pout,
                             unsigned char *pdata,
                             unsigned int nlen,
                             unsigned char *pkey);
unsigned int des_ecb_decrypt(unsigned char *pout,
                             unsigned char *pdata,
                             unsigned int nlen,
                             unsigned char *pkey);
#endif //#if USE_DES_ECB_EN
 
#if USE_DES_CBC_EN
int des_crypt_cbc( des_context *ctx,
                    int mode,
                    size_t length,
                    unsigned char iv[8],
                    const unsigned char *input,
                    unsigned char *output );
unsigned int des_cbc_encrypt(unsigned char *pout,
                             unsigned char *pdata,
                             unsigned int nlen,
                             unsigned char *pkey,
                             unsigned char *piv);
#endif //#if USE_DES_CBC_EN
#endif //#if USE_DES_EN
 
#if USE_3DES_EN
#if USE_3DES_ECB_EN
//3DES-ECB buffer encryption API
unsigned int des3_ecb_encrypt(unsigned char *pout,
                              unsigned char *pdata,
                              unsigned int nlen,
                              unsigned char *pkey,
                              unsigned int klen);
unsigned int des3_ecb_decrypt(unsigned char *pout,
                              unsigned char *pdata,
                              unsigned int nlen,
                              unsigned char *pkey,
                              unsigned int klen);
#endif //#if USE_3DES_ECB_EN
 
#if USE_3DES_CBC_EN
unsigned int des3_cbc_encrypt(unsigned char *pout,
                              unsigned char *pdata,
                              unsigned int nlen,
                              unsigned char *pkey,
                              unsigned int klen,
                              unsigned char *piv);
unsigned int des3_cbc_decrypt(unsigned char *pout,
                              unsigned char *pdata,
                              unsigned int nlen,
                              unsigned char *pkey,
                              unsigned int klen,
                              unsigned char *piv);
#endif //#if USE_3DES_CBC_EN
#endif //#if USE_3DES_EN
 
 
 
 
 
 
#endif //#ifndef DES3_H
 
 

/*****************************************************************************
 * Module    : 
 * File      : typedef.h
 * Author    : Mike
 * Email     : 
 * Function  : 常用的类型定义
 *****************************************************************************/
#ifndef TYPEDEF_H
#define TYPEDEF_H
 
//typedef _Bool            bool, BOOL;
 
typedef unsigned char   uchar, u8, U8, uint8, uint8_t, UINT8, BYTE;
typedef signed char     s8, S8, int8, INT8,char_t;
 
typedef unsigned int  u16, uint16, uint16_t, UINT16, WORD;
typedef signed int    s16, S16, int16, INT16;
 
typedef unsigned long   uint, ushort,u32, U32, uint32, uint32_t, UINT32, DWORD;
typedef signed long     s32, S32, int32, INT32;
 
typedef unsigned long   uint64_t, u64, U64, uint64, UINT64;
typedef signed long     s64, S64, int64, INT64;
 
typedef unsigned short string;
 
#define TRUE            1
#define FALSE           0
#define true            1
#define false           0
//#define NULL            0
 
#endif

附上在线加密网站3DES加密

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值