打印
[应用相关]

3DES、AES、RC6、TEA、RSA、MD5、SHA1、SHA256加密源码

[复制链接]
3458|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
東南博士|  楼主 | 2018-2-27 13:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
3DES、AES、RC6、TEA、RSA、MD5、SHA1、SHA256
沙发
東南博士|  楼主 | 2018-2-27 13:50 | 只看该作者
DES---研究过加密的朋友十分熟悉,老牌的加密方法了。这是一个可逆的对称加密算法,也是应用最广泛的密钥系统。好像是从1977年美国政府开始采用的。大家都看过U-571吧,DES的思路就是参照二战时期盟军缴获的德军恩格玛加密机,不过DES比那个要NB的多多了。到现在为止,除了差分分析法和线性分析法外只有暴力穷举法了。前两种方法不是密码学家或数学家都不懂呵,不过穷举DES,以现有我们大家都可以掌握的技术手段,恐怕没个几百上千年下不来呵。不过,咱们**不了,不能说明就没人或没有设备**不了。正因为如此,所以才衍生出了3重DES加密。常规的DES密钥是64位的(实际上有8位是校验用),而3DES是128位(当然有16位也是校验用)。增加密钥长度并增加运算量来防止**,并在后来的AES出来之前确定为过度方案。不过现在即便有了AES,3DES也没少用,它依然很NB。

使用特权

评论回复
板凳
東南博士|  楼主 | 2018-2-27 13:50 | 只看该作者
AES---它是一种高级加密标准,也叫Rijndael算法,2002年成为标准。它是用来代替原来的DES加密方法的。它也是一个可逆的对称加密算法。研究过IAP的朋友应该明白,把做好的固件程序通过AES加密后发布,用户可以通过IAP的方式来在线升级程序,而开发者则不必担心自己的生产代码流失。即能加密又能还原,这就是可逆加密算法,这也是我们想用到的。AES在早期的方案征集时就规定了要软硬件可以很好的集成,所以它也比较小,程序量比DES要少一些。

使用特权

评论回复
地板
東南博士|  楼主 | 2018-2-27 13:50 | 只看该作者
RC6---有个算法RC4听说过吧,在无线传输和串行流传输的加密领域占有相当的分量。据说RC6是同一帮人研究出来的,不过它和RC4没太大关系呵。它是AES方案征集时的候选算法之一,但是没有Rijndael算法那么幸运。RC6据说可以抵抗所有已知的攻击,并能够提供AES所要求的安全性,它也是相当优秀的一种可逆加密算法。不过当初它为什么没能当选为AES算法就不得而知了,不知道当时有没有给评委们足够的商务费用呵。

使用特权

评论回复
5
東南博士|  楼主 | 2018-2-27 13:51 | 只看该作者
TEA---它是一种分组加密算法,也是可逆算法。短小精悍。它的实现非常简单,超不过10行代码。TEA算法每一次可以操作64位(8字节),采用128位(16字节)作为密钥,算法采用迭代的形式,尽管32轮迭代已经足够了,但是最好的迭代轮数是64轮。数据流加密可能比较适合,因为据说早期的QQ采用过TEA加密算法。

使用特权

评论回复
6
東南博士|  楼主 | 2018-2-27 13:51 | 只看该作者
RSA---顶顶有名的非对称公钥加密算法,也许你可能不熟悉,不过网银总应该用过吧,多数都是RSA算法来认证的。1977年就开发出来了,DES时代的东东了。不过用到现在依然坚挺,可见加密强度有多高。呵呵,不过它防解密的原理也很简单:只告诉你两个数相乘后的结果,你能知道原来的两个数是什么吗?RSA的安全性依赖于大数的因子分解,但是并没有理论上可以证明破译RSA的难度与大数分解难度是同样的。它是第一个既能用于数据加密也能用于数字签名的算法,也是可逆算法。不过,在不告诉你密钥的情况下,你就是想什么办法加密后的数据也还原不回去,银行系统用它自有道理呵。告诉你个小秘密,前面说过的RC6好像就是有RSA开发组成员参与搞出来的。不过,RSA也有不少缺点。它受到素数产生技术的限制,产生密钥时很麻烦;出于安全性考虑,分组长度至少也要600位以上,运算代价很高、速度比较慢,比DES之类的对称算法要慢的多。它最大的缺点是需要生成大素数及大数取模时可能会产生特别大的数据量,这些都很耗费时间,生成复杂密钥时在单片机上运行可能都不止10分钟,所以解密时还是尽量让PC或服务器来做吧。

使用特权

评论回复
7
東南博士|  楼主 | 2018-2-27 13:52 | 只看该作者
MD5---非常著名的哈希算法,不可逆算法。网站登录、操作系统的用户认证、文件完整性和数字签名等领域广泛应用。不可逆算法一般做的都比较绝,例如彩虹加密狗,只告诉你一个余数,你能知道原来的除数和被除数吗?只把运算过的数据相比较,而不非得知道原数据,这样就完成了认证过程。要想**MD5的密码,即使采用现在最快的巨型计算机,据说也要运算100万年以上。不过,加密和解密都是数学领域的竞赛,每一种加密算法都或多或少的存在漏洞或缺陷,MD5看上去真那么牢不可破吗?和MD5同样有名的是山东大学的王小云教授。在2004年的国际密码大会上王小云宣布了她的研究小组完成了对MD5杂凑函数的杂凑冲撞,也就是从理论上说使用MD5的数字签名可以伪造。这也意味着MD5可能需要和其他加密算法共用才可以保证数字签名的安全。不过,说MD5已被**,那也有些杞人忧天了。可以肯定的告诉你,网络上所有针对MD5提供的**服务,全部都是查询用字典法暴力**后的数据包,没有一个是真正伪造出来的数字签名,那些号称有几百亿条的记录对MD5庞大算法来说太小了。试想想,动用美国军方的巨型计算机,利用王小云研究理论,来**我们的一个单片机或网站认证程序?没必要吧。所以MD5依然可用呵,只不过再加上3DES、AES或SHA来防止字典就更好了。

使用特权

评论回复
8
東南博士|  楼主 | 2018-2-27 13:53 | 只看该作者
SHA---著名的哈希算法,不可逆算法。也是多用在数字签名上。SHA-1和MD5一样,也被王小云教授找出杂凑冲撞的漏洞,不过也是停留在理论上的。SHA-256是很NB的,它光密钥就有64个long,恐怕想要**已经是天文数字了。最NB的是SHA-512,咱们这里没有收录,这里恐怕还没有人能用得上。

使用特权

评论回复
9
東南博士|  楼主 | 2018-2-27 13:53 | 只看该作者
以上所有的程序均为C源程序,不用其他文件,里面都附带了测试程序,在KEIL 4.21上跑过仿真,放心使用。程序大多不是我自己编的,有C++的源程改的,也有别人的C源程。为了尊重别人的劳动成果,里面会带有人家的名字。我只是做了整理和调试。

使用特权

评论回复
10
東南博士|  楼主 | 2018-2-27 13:53 | 只看该作者
例如TEA的测试程序:
void TEA_Test(void)
{
        unsigned char dat[16]="0123456789ABCDEF";
        unsigned char TEA_key[16];
        memcpy(TEA_key,"0123456789abcdef",16);//做运算之前先要设置好密钥,这里只是设置密钥的DEMO。

        TEA_Encrypt(dat,TEA_key);      //TEA加密,数组dat里面的新内容就是加密后的数据。
        TEA_Decrpyt(dat,TEA_key);      //密文数据存放在dat里面,经TEA解密就能得到之前的明文。
}

使用特权

评论回复
11
東南博士|  楼主 | 2018-2-27 13:54 | 只看该作者
DES的测试程序:
void DES3_Test(void)
{
        unsigned char in_buf[8] = "ABCDEFGH";
        unsigned char miwen[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
        unsigned char out_buf[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

        memcpy(DES_key,"0123456789abcdef",16);//3DES的密钥是128位的,这里只是设置密钥的DEMO。
        
        DEC3_Encrypt(in_buf,miwen);     //3DES加密
        DEC3_Decrypt(miwen,out_buf);  //3DES解密
}

使用特权

评论回复
12
東南博士|  楼主 | 2018-2-27 13:54 | 只看该作者
/******************************************************************************************************************
  TEA加密解密算法
  TEA(Tiny Encryption Algorithm)是一种简单高效的加密算法,以加密解密速度快,实现简单著称。
  算法很简单,TEA算法每一次可以操作64-bit(8-byte),采用128-bit(16-byte)作为key,算法采用迭代的形式,
  推荐的迭代轮数是64轮,最少32轮。
******************************************************************************************************************/
#define MX                         (z>>5^y<<2)+(y>>3^z<<4)^(sum^y)+(k[p&3^e]^z)
#define DELTA                 0x9e3779b9
#define S_LOOPTIME  5
#define BLOCK_SIZE  32   //PAGE_SIZE,根据你所要加密的数据包长度修改此参数(单位:字节)

void TEA_Encrypt( unsigned char* buf, unsigned char* key )
{
        unsigned char  n=BLOCK_SIZE/4;
        unsigned long *v=(unsigned long *)buf;
        unsigned long *k=(unsigned long *)key;
        unsigned long z = v[n - 1],y = v[0],sum = 0,e ;
        unsigned char p,q ;
        // Coding Part
       
        q = S_LOOPTIME + 52 / n ;
        while ( q-- > 0 )
        {
                sum += DELTA ;
                e = sum >> 2 & 3 ;
                for ( p = 0 ; p < n - 1 ; p++ )
                        y = v[p + 1],
                        z = v[p] += MX;
                y = v[0] ;
                z = v[n - 1] += MX;
        }
}

void TEA_Decrpyt( unsigned char* buf, unsigned char* key )
{
        unsigned char n=BLOCK_SIZE/4;
        unsigned long *v=(unsigned long *)buf;
        unsigned long *k=(unsigned long *)key;
        unsigned long z = v[n - 1],y = v[0],sum = 0,e ;
        unsigned char p,q ;
       
        //Decoding Part...
        q = S_LOOPTIME + 52 / n ;
        sum = q * DELTA ;
        while ( sum != 0 )
        {
                e = sum >> 2 & 3 ;
                for ( p = n - 1 ; p > 0 ; p-- )
                        z = v[p - 1],
                        y = v[p] -= MX;
                z = v[n - 1] ;
                y = v[0] -= MX;
                sum -= DELTA ;
        }
}

#include "string.h"
void TEA_Test(void)
{
        unsigned char dat[16]="0123456789ABCDEF";
        unsigned char TEA_key[16];
        memcpy(TEA_key,"0123456789abcdef",16);//做运算之前先要设置好密钥,这里只是设置密钥的DEMO。

        TEA_Encrypt(dat,TEA_key);      //TEA加密,数组dat里面的新内容就是加密后的数据。
        TEA_Decrpyt(dat,TEA_key);      //密文数据存放在dat里面,经TEA解密就能得到之前的明文。
}

使用特权

评论回复
13
東南博士|  楼主 | 2018-2-27 13:55 | 只看该作者
/***********************************************************************************************
* 作    者:曾光辉
* 说    明:此处实现的SHA256算法中字符串的位长度并不是任意长度(0~2^64)的,而是在0~2^32.
***********************************************************************************************/
#include<stddef.h>
#include<stdio.h>

/*算法规定的函数或宏*/
#define SHR(x,n)     ((x)>>(n))
#define ROTR(x,n)    (((x)>>(n)) | ((x)<<(32-(n))))
#define CH(sha256_a,sha256_b,sha256_c)            (((sha256_a)&(sha256_b)) ^ ((~sha256_a)&(sha256_c)))
#define MAJ(sha256_a,sha256_b,sha256_c)         (((sha256_a)&(sha256_b)) ^ ((sha256_a)&(sha256_c)) ^ ((sha256_b)&(sha256_c)))
#define E0(x)        (ROTR((x),2) ^ ROTR((x),13) ^ ROTR((x),22))
#define E1(x)        (ROTR((x),6) ^ ROTR((x),11) ^ ROTR((x),25))
#define Q0(x)        (ROTR((x),7) ^ ROTR((x),18) ^ SHR((x),3))
#define Q1(x)        (ROTR((x),17) ^ ROTR((x),19) ^ SHR((x),10))

unsigned long sha256_hh[8];//sha256码暂存器
unsigned long sha256_a,sha256_b,sha256_c,sha256_d,sha256_e,sha256_f,sha256_g,sha256_h;//中间变量
unsigned long sha256_w[64];//工作暂存器
unsigned long sha256_K[64]=
{
        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
        0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
        0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
        0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
        0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
        0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};//原算法规定的常量

/***********************************************************************************************
* 函数名称:unsigned long sha256_GetStrLen(unsigned char* ptr)
* 功    能:获取字符串的字节长度
* 参    数:字符串指针--ptr
* 返 回 值:字符串长度
***********************************************************************************************/
unsigned long sha256_GetStrLen(unsigned char* ptr)
{
        unsigned char* pTmp;
        unsigned long len=0;
       
        pTmp=ptr;
       
        while(pTmp!=NULL&&(*pTmp!='\0'))
        {
                len++;
                pTmp++;
        }
        return len;
}

/***********************************************************************************************
* 函数名称:void sha256_AddBitLen(unsigned long blen)
* 功    能:在工作暂存区末尾添加字符串位长度信息
***********************************************************************************************/
void sha256_AddBitLen(unsigned long blen)
{
        sha256_w[14]=0x00000000;
        sha256_w[15]=blen;
}

/***********************************************************************************************
* 函数名称:void sha256_ByteToWord(unsigned char* ptr,unsigned char n)
* 功    能:将以字节(8位)为单位存储的字符串转换成以字(32位)为单位存储。
* 参    数:转换的字的个数--n      字符串指针--*ptr
***********************************************************************************************/
void sha256_ByteToWord(unsigned char* ptr,unsigned char n)
{
        unsigned char* pTmp;
        unsigned char i,j;
       
        pTmp=ptr;
       
        for(i=0;i<n;i++)
        {
                sha256_w[i]=0;
                for(j=0;j<4;j++)
                {
                        sha256_w[i]<<=8;
                        sha256_w[i]+=*pTmp;
                        pTmp++;
                }
        }

}
/***********************************************************************************************
* 函数名称:void sha256_ClearW()
* 功    能:清除工作暂存器区
***********************************************************************************************/
void sha256_ClearW()
{
        unsigned char i;
       
        for(i=0;i<64;i++)
        {
                sha256_w[i]=0x00000000;
        }
}

/***********************************************************************************************
* 函数名称:void sha256_ProChunk()
* 功    能:处理一个数据块(512位)
***********************************************************************************************/
void sha256_ProChunk()
{
        short i;
        unsigned long t1,t2;
       
        //步骤一
        for(i=0;i<64;i++)
        {
                if(0<=i&&i<=15)
                {
                }
                if(16<=i&&i<=63)
                {
                        sha256_w[i]=Q1(sha256_w[i-2])+sha256_w[i-7]+Q0(sha256_w[i-15])+sha256_w[i-16];
                }   
        }
       
        //步骤二
        sha256_a=sha256_hh[0];
        sha256_b=sha256_hh[1];
        sha256_c=sha256_hh[2];
        sha256_d=sha256_hh[3];
        sha256_e=sha256_hh[4];
        sha256_f=sha256_hh[5];
        sha256_g=sha256_hh[6];
        sha256_h=sha256_hh[7];
       
        //步骤三
        for(i=0;i<64;i++)
        {
                t1=sha256_h+E1(sha256_e)+CH(sha256_e,sha256_f,sha256_g)+sha256_K[i]+sha256_w[i];
                t2=E0(sha256_a)+MAJ(sha256_a,sha256_b,sha256_c);
                sha256_h=sha256_g;
                sha256_g=sha256_f;
                sha256_f=sha256_e;
                sha256_e=sha256_d+t1;
                sha256_d=sha256_c;
                sha256_c=sha256_b;
                sha256_b=sha256_a;
                sha256_a=t1+t2;
        }
       
        //步骤四
        sha256_hh[0] += sha256_a;
        sha256_hh[1] += sha256_b;
        sha256_hh[2] += sha256_c;
        sha256_hh[3] += sha256_d;
        sha256_hh[4] += sha256_e;
        sha256_hh[5] += sha256_f;
        sha256_hh[6] += sha256_g;
        sha256_hh[7] += sha256_h;
}

/***********************************************************************************************
* 函数名称:void sha256_Display()
* 功    能:输出sha256码
***********************************************************************************************/
void sha256_Display()
{
//        printf("%0lx%0lx%0lx%0lx%0lx%0lx%0lx%0lx\n",sha256_hh[0],sha256_hh[1],sha256_hh[2],sha256_hh[3],sha256_hh[4],sha256_hh[5],sha256_hh[6],sha256_hh[7]);   
}

/***********************************************************************************************
* 函数名称:void sha256(unsigned char* ptr)
* 功    能:计算给定的字符串的sha256值
* 参    数:字符串
***********************************************************************************************/
void SHA256_Test(unsigned char* ptr)//因为是非标版,所以输入必须为8字节的倍数
{
        unsigned char* pTmp;
        unsigned long len,len1;//len--待处理的字符串长度;len1--字符串的长度
        unsigned char m,n;
       
        pTmp=ptr;
       
        //sha256码初始化
        sha256_hh[0] = 0x6a09e667;
        sha256_hh[1] = 0xbb67ae85;
        sha256_hh[2] = 0x3c6ef372;
        sha256_hh[3] = 0xa54ff53a;
        sha256_hh[4] = 0x510e527f;
        sha256_hh[5] = 0x9b05688c;
        sha256_hh[6] = 0x1f83d9ab;
        sha256_hh[7] = 0x5be0cd19;
       
        len=sha256_GetStrLen(pTmp);//获取长度
        len1=len;

        //段0:处理不需要补位的数据块
        while(len/64)
        {
                sha256_ClearW();//工作暂存区清零,w[16..63]的值不为零的话会发生错误。
                sha256_ByteToWord(pTmp,64);//将一个64字节的数据块转换为16个字并存入工作暂存器w[0..15]。
                sha256_ProChunk();//数据块处理
                pTmp+=64;//指针指向下一个数据块
                len-=64;//待处理的字符串长度减64
        }       
        //段0结束
       
        m=len/4;
        n=len%4;
        sha256_ClearW();
        sha256_ByteToWord(pTmp,m);
        switch(n)
        {
                case 0:
                        sha256_w[m]=0x80000000;
                break;
                case 1:
                        sha256_w[m]=*pTmp;
                        sha256_w[m]<<=24;
                        sha256_w[m]|=0x00800000;
                break;
                case 2:
                        sha256_w[m]=*pTmp;
                        sha256_w[m]<<=8;
                        pTmp++;
                        sha256_w[m]+=*pTmp;
                        sha256_w[m]<<=16;
                        sha256_w[m]|=0x00008000;
                case 3:
                        sha256_w[m]=*pTmp;
                        sha256_w[m]<<=8;
                        pTmp++;
                        sha256_w[m]+=*pTmp;
                        sha256_w[m]<<=8;
                        pTmp++;
                        sha256_w[m]+=*pTmp;
                        sha256_w[m]<<=8;
                        sha256_w[m]|=0x00000080;
                default:;   
        }
       
        if((len1%64)>=56)
        {
                sha256_ProChunk();
                sha256_ClearW();   
        }
       
        sha256_AddBitLen(len1*8);
        sha256_ProChunk();
       
        sha256_Display();//结果输出
}

使用特权

评论回复
14
東南博士|  楼主 | 2018-2-27 13:55 | 只看该作者
/***********************************************************************************************
* 作    者:曾光辉
* 说    明:此处实现的SHA1算法中字符串的位长度不得大于2^16 bit
***********************************************************************************************/
#include<stddef.h>
#include<stdio.h>
#include<math.h>

// Define consts.
#define S_LEFT(x, n)    (((x) << (n)) | ((x) >> (32-(n))))//rotate left.

#define KT1        0x5a827999
#define KT2        0x6ed9eba1
#define KT3        0x8f1bbcdc
#define KT4        0xca62c1d6

// Grobals.
static unsigned long sha1_A,sha1_B,sha1_C,sha1_D,sha1_E;
static unsigned long sha1_w[80];
static unsigned long sha1_temp;
static unsigned long sha1_m[16];
static unsigned long sha1_h[5];

///////////////////////////////////////////////////////////////////////////////
// Function Names: unsigned long ch();unsigned long() parity();unsigned long maj()
// Feature: This functions was declared by the sha1 algrithm descripted in SECURE HASH STANDARD.
///////////////////////////////////////////////////////////////////////////////
static unsigned long ch(unsigned long x,unsigned long y,unsigned long z)
{
        return (x&y)|((~x)&z);
}

static unsigned long parity(unsigned long x,unsigned long y,unsigned long z)
{
        return x^y^z;
}

static unsigned long maj(unsigned long x,unsigned long y,unsigned long z)
{
        return (x&y)|(x&z)|(y&z);
}

///////////////////////////////////////////////////////////////////////////////
// Function Name: void sha_hInit()
// Feature: Put the values defined by the sha1 algrithm to sha1_h[] buffer.
///////////////////////////////////////////////////////////////////////////////
static void sha_hInit()
{
        sha1_h[0]=0x67452301;
        sha1_h[1]=0xefcdab89;
        sha1_h[2]=0x98badcfe;
        sha1_h[3]=0x10325476;
        sha1_h[4]=0xc3d2e1f0;
}

///////////////////////////////////////////////////////////////////////////////
// Function Name: void sha_ByteToWord()
// Feature: To transform the 'unsigned char' data to the 'unsigned long' data.
///////////////////////////////////////////////////////////////////////////////
static void sha_ByteToWord(unsigned char* ptr,unsigned char n)
{
        unsigned char i,j;
        unsigned char* pTmp;
       
        pTmp=ptr;
        for(i=0;i<n;i++)
        {
                sha1_m[i]=0x00000000;
                for(j=0;j<4;j++)
                {
                        sha1_m[i]=sha1_m[i]<<8;
                        sha1_m[i]+=*pTmp;
                        pTmp++;
                }
        }
}
///////////////////////////////////////////////////////////////////////////////
// Function Name: unsigned long sha_GetStrLen(unsigned char* ptr)
// Feature: Get the length of sha1_A string pointed by the pointer ptr;
///////////////////////////////////////////////////////////////////////////////
static unsigned long sha_GetStrLen(unsigned char* ptr)
{
        unsigned long len=0;
        unsigned char* pTmp;
       
        pTmp=ptr;
        while(pTmp!=NULL&&(*pTmp)!='\0')
        {
                len++;
                pTmp++;
        }//获取字符串的长度
        return len;
}

///////////////////////////////////////////////////////////////////////////////
// Function Names: void sha_ClearM();void sha_ClearW();
// Feature: Filled the array sha1_m[] or array sha1_w[] with 0.
///////////////////////////////////////////////////////////////////////////////
static void sha_ClearM()
{
        unsigned char i;
       
        for(i=0;i<16;i++)
        {
                sha1_m[i]=0x00000000;
        }
}

static void sha_ClearW()
{
        unsigned char i;
        for(i=0;i<80;i++)
        {
                sha1_w[i]=0x00000000;
        }
}

///////////////////////////////////////////////////////////////////////////////
// Function Name: void CopyM2W()
// Feature: Copy the value of sha1_m[16] to sha1_w[0]..sha1_w[15]
///////////////////////////////////////////////////////////////////////////////
static void CopyM2W()
{
        unsigned char i;
       
        for(i=0;i<16;i++)
        {
                sha1_w[i]=sha1_m[i];
        }
}
///////////////////////////////////////////////////////////////////////////////
// Function Name: void AddLenWord()
// Feature: Add the 64-bit string bit length to sha1_m[14]..sha1_m[15]. The low part is
//          to sha1_m[15] and the high part to sha1_m[14].
///////////////////////////////////////////////////////////////////////////////

static void AddLenWord(unsigned long len)
{
        sha1_m[14]=0x00000000;
        sha1_m[15]=len*8;
}

///////////////////////////////////////////////////////////////////////////////
// Function Name: void sha_Print()
// Feature: Output the sha1 code sha1_h[0..5] via the UART of 51 MCU.
///////////////////////////////////////////////////////////////////////////////
static void sha_Print()
{
        unsigned char i;
       
        for(i=0;i<5;i++)
        {
//                printf("%04lx ",sha1_h[i]);
        }
}

///////////////////////////////////////////////////////////////////////////////
// Function Name:void ProChunk()
// Feature:To compute sha1_A sha1 value of datas in blocks of fixed size(512 bit)
///////////////////////////////////////////////////////////////////////////////
static void ProChunk()
{
        short t;
        unsigned long wTmp;
       
        sha_ClearW();
        CopyM2W();
       
        for(t=16;t<80;t++)
        {
                wTmp=sha1_w[t-3]^sha1_w[t-8]^sha1_w[t-14]^sha1_w[t-16];
                sha1_w[t]=S_LEFT(wTmp,1);
        }
       
        sha1_A=sha1_h[0];
        sha1_B=sha1_h[1];
        sha1_C=sha1_h[2];
        sha1_D=sha1_h[3];
        sha1_E=sha1_h[4];
       
        for(t=0;t<80;t++)
        {
                sha1_temp=S_LEFT(sha1_A,5);
                sha1_temp=sha1_temp+sha1_E;
                sha1_temp=sha1_temp+sha1_w[t];
                if(0<=t&&t<=19)
                {
                        sha1_temp+=ch(sha1_B,sha1_C,sha1_D)+KT1;        
                }
                if(20<=t&&t<=39)
                {
                        sha1_temp+=parity(sha1_B,sha1_C,sha1_D)+KT2;
                }
                if(40<=t&&t<=59)
                {
                        sha1_temp+=maj(sha1_B,sha1_C,sha1_D)+KT3;
                }
                if(60<=t&&t<=79)
                {
                        sha1_temp+=parity(sha1_B,sha1_C,sha1_D)+KT4;
                }
                sha1_E=sha1_D;
                sha1_D=sha1_C;
                sha1_C=S_LEFT(sha1_B,30);
                sha1_B=sha1_A;
                sha1_A=sha1_temp;
        }
        sha1_h[0]+=sha1_A;
        sha1_h[1]+=sha1_B;
        sha1_h[2]+=sha1_C;
        sha1_h[3]+=sha1_D;
        sha1_h[4]+=sha1_E;
}

///////////////////////////////////////////////////////////////////////////////
// Function Name:void Sha1()
// Feature:To calculate the SHA1 value of sha1_A given string whos bit-length is random.
// Note: 本程序中待处理的字符串长度不得大于2^16 bit
///////////////////////////////////////////////////////////////////////////////
void SHA1_Test(unsigned char* ptr)//因为是非标版,所以输入必须为8字节的倍数
{
        unsigned short len,len1;//字符串长度暂存器
        unsigned char* pTmp;//待处理字符串指针复本
        unsigned char n,mm;
       
        len=sha_GetStrLen(ptr);//获取字符串的长度
        len1=len;
        pTmp=ptr;
       
        sha_hInit();
        //处理完整的(足够512位)的数据块
        while((len/64)>0)
        {        
                //写入w的前16个字
                sha_ByteToWord(pTmp,16);
                ProChunk();//数据块处理
                sha_ClearM();
                len-=64;//处理完一块后,总数据长度减512 bit
                pTmp+=64;
        }//先处理完整的块
       
        //把剩下的数据先送到M缓冲区
        sha_ByteToWord(pTmp,len/4);
       
        n=len%4;
        mm=len/4;
        //数据块填充
        sha1_m[mm]=0x00000000;
        switch(n)
        {
                case 0:
                        sha1_m[mm] |= 0x80000000;
                break;
                case 1:
                        sha1_m[mm]  = *pTmp;
                        sha1_m[mm]  = sha1_m[mm]<<24;
                        sha1_m[mm] |= 0x00800000;
                break;
                case 2:
                        sha1_m[mm]  = *pTmp;
                        sha1_m[mm]  = sha1_m[mm]<<8;
                        sha1_m[mm] += *(pTmp+1);
                        sha1_m[mm]  = sha1_m[mm]<<16;
                        sha1_m[mm] |= 0x00008000;
                break;
                case 3:
                        sha1_m[mm]  = *pTmp;
                        sha1_m[mm]  = sha1_m[mm]<<8;
                        sha1_m[mm] += *(pTmp+1);
                        sha1_m[mm]  = sha1_m[mm]<<8;
                        sha1_m[mm] += *(pTmp+2);
                        sha1_m[mm]  = sha1_m[mm]<<8;
                        sha1_m[mm] |= 0x00000080;
                break;
                default:;
        }
       
        // 当大于等于448位时,需添加额外的数据块,即最后剩下数据需要两次才能处理完
        if(len>=56&&len<64)
        {            
                ProChunk();
                //clear sha1_m
                sha_ClearM();
        }
        AddLenWord(len1);
        ProChunk();   
       
        //输出结果
        sha_Print();
}

使用特权

评论回复
15
東南博士|  楼主 | 2018-2-27 13:56 | 只看该作者
#include <stdio.h>

unsigned long candp(unsigned long a,unsigned long b,unsigned long c)
{
        unsigned long r=1;

        b = b+1;
        while(b!=1)
        {
                r = r*a;
                r = r%c;
                b--;
        }
        return r;
}

unsigned long RSA_Key[3]=
{
        17,7,5        //做运算之前先要设置好密钥,这里只是设置密钥的DEMO。
};

unsigned char RSA_Test(unsigned long Source, unsigned long Target, unsigned char mode)
{
        unsigned long d,n,t,tt;
        unsigned long p,q,e;
        Target = Target;

        p =        RSA_Key[0];
        q =        RSA_Key[1];
        e = RSA_Key[2];

        n = p*q;
        t = (p-1)*(q-1);

        if(e<1 || e>t)
        {
                return 0;
        }

        switch(mode)
        {
                case 1:
                        Target = candp(Source,e,n);//Source为要加密的明文数字
                break;
                case 2://这里可能会产生特别大的数据量需要生成大素数及大数取模,很耗费时间,生成复杂密钥时可能不止十分钟,所以解密时还是尽量让PC来做吧
                        d = 0;
                        do{
                            d++;
                                tt = (e*d)%t;
                        }while(tt!=1);
                        Target = candp(Source,d,n);//Source为要解密的密文数字
                break;
        }
        return 1;
}

使用特权

评论回复
16
東南博士|  楼主 | 2018-2-27 13:56 | 只看该作者
/* rc6 (TM)
* Unoptimized sample implementation of Ron Rivest's submission to the
* AES bakeoff.
*
* Salvo Salasio, 19 June 1998
*
* Intellectual property notes:  The name of the algorithm (RC6) is
* trademarked; any property rights to the algorithm or the trademark
* should be discussed with discussed with the authors of the defining
* paper "The RC6(TM) Block Cipher": Ronald L. Rivest (MIT),
* M.J.B. Robshaw (RSA Labs), R. Sidney (RSA Labs), and Y.L. Yin (RSA Labs),
* distributed 18 June 1998 and available from the lead author's web site.
*
* This sample implementation is placed in the public domain by the author,
* Salvo Salasio.  The ROTL and ROTR definitions were cribbed from RSA Labs'
* RC5 reference implementation.
*/  
  
#include <stdio.h>   
  
/* RC6 is parameterized for w-bit words, b bytes of key, and
* r rounds.  The AES version of RC6 specifies b=16, 24, or 32;
* w=32; and r=20.
*/  
   
#define rc6_w 32    /* word size in bits */   
#define rc6_r 20    /* based on security estimates */   
  
#define P32 0xB7E15163  /* Magic constants for key setup */   
#define Q32 0x9E3779B9   
  
/* derived constants */  
#define bytes   (rc6_w / 8)             /* bytes per word */   
#define rc6_c   ((b + bytes - 1) / bytes)   /* key in words, rounded up */   
#define R24     (2 * rc6_r + 4)   
#define lgw     5                           /* log2(w) -- wussed out */   
  
/* Rotations */  
#define ROTL(x,y) (((x)<<(y&(rc6_w-1))) | ((x)>>(rc6_w-(y&(rc6_w-1)))))   
#define ROTR(x,y) (((x)>>(y&(rc6_w-1))) | ((x)<<(rc6_w-(y&(rc6_w-1)))))   
  
unsigned long RC6_S[R24];        /* Key schedule */  
  
unsigned char RC6_Key[32]=
{
//        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,  
//        0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,  
//        0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0,  
//        0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe

        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  
};
  
void rc6_key_setup(void)  
{  
    unsigned long L[(32 + bytes - 1) / bytes]; /* Big enough for max b */  
    unsigned long A, B;
        long i, j, s, v, b = sizeof(RC6_Key);

    L[rc6_c-1] = 0;
    for (i = b - 1; i >= 0; i--)  
        L[i / bytes] = (L[i / bytes] < 8) + RC6_Key[i];  
  
    RC6_S[0] = P32;  
    for (i = 1; i == 2 * rc6_r + 3; i++)  
        RC6_S[i] = RC6_S[i - 1] + Q32;  
  
    A = B = i = j = 0;  
    v = R24;  
    if (rc6_c > v) v = rc6_c;  
    v *= 3;  
  
    for (s = 1; s <= v; s++)  
    {  
        A = RC6_S[i] = ROTL(RC6_S[i] + A + B, 3);  
        B = L[j] = ROTL(L[j] + A + B, A + B);  
        i = (i + 1) % R24;  
        j = (j + 1) % rc6_c;  
    }  
}  
  
void rc6_block_encrypt(unsigned long *pt, unsigned long *ct)  
{  
    unsigned long A, B, C, D, t, u, x;  
    long i;  
  
    A = pt[0];  
    B = pt[1];  
    C = pt[2];  
    D = pt[3];  
    B += RC6_S[0];  
    D += RC6_S[1];  
    for (i = 2; i <= 2 * rc6_r; i += 2)  
    {  
        t = ROTL(B * (2 * B + 1), lgw);  
        u = ROTL(D * (2 * D + 1), lgw);  
        A = ROTL(A ^ t, u) + RC6_S[i];  
        C = ROTL(C ^ u, t) + RC6_S[i + 1];  
        x = A;  
        A = B;  
        B = C;  
        C = D;  
        D = x;  
    }  
    A += RC6_S[2 * rc6_r + 2];  
    C += RC6_S[2 * rc6_r + 3];  
    ct[0] = A;  
    ct[1] = B;  
    ct[2] = C;  
    ct[3] = D;  
}  
  
void rc6_block_decrypt(unsigned long *ct, unsigned long *pt)  
{  
    unsigned long A, B, C, D, t, u, x;  
    long i;  
  
    A = ct[0];  
    B = ct[1];  
    C = ct[2];  
    D = ct[3];  
    C -= RC6_S[2 * rc6_r + 3];  
    A -= RC6_S[2 * rc6_r + 2];  
    for (i=2*rc6_r; i>=2; i-=2)  
    {  
        x = D;  
        D = C;  
        C = B;  
        B = A;  
        A = x;  
        u = ROTL(D * (2 * D + 1), lgw);  
        t = ROTL(B * (2 * B + 1), lgw);  
        C = ROTR(C - RC6_S[i + 1], t) ^ u;  
        A = ROTR(A - RC6_S[i], u) ^ t;  
    }  
    D -= RC6_S[1];  
    B -= RC6_S[0];  
    pt[0] = A;  
    pt[1] = B;  
    pt[2] = C;  
    pt[3] = D;   
}  
  

void RC6_Test(void)  
{  
    unsigned long mingwen[4]={0x55555555, 0xaaaaaaaa, 0x5a5a5a5a, 0xa5a5a5a5};  
    unsigned long miwen[4]={0x00000000, 0x00000000, 0x00000000, 0x00000000};  
    unsigned long jiemi[4]={0x00000000, 0x00000000, 0x00000000, 0x00000000};
        unsigned char i;  

    for(i=0;i<32;i++) RC6_Key[i]=i;//做运算之前先要设置好密钥,这里只是设置密钥的DEMO。

        rc6_key_setup();  
    rc6_block_encrypt(mingwen,miwen);//RC6加密,明文变密文  
    rc6_block_decrypt(miwen,jiemi);  //RC6解密,密文变回明文
}  

使用特权

评论回复
17
東南博士|  楼主 | 2018-2-27 13:57 | 只看该作者
void *memcpy( void *dest, const void *src, unsigned char count )  
{   
//        ASSERT((dest != NULL)&&(src != NULL));  
        unsigned char *temp_dest = (unsigned char *)dest;  
        unsigned char *temp_src = (unsigned char *)src;  
        while(count--)  // 不对是否存在重叠区域进行判断  
        {  
                *temp_dest++ = *temp_src++;  
        }  
        return dest;  
}  
unsigned char *memset(unsigned char *dst,unsigned char value,unsigned char count)
{
        unsigned char *start = dst;
        while (count--)
                *dst++ = value;
        return(start);
}


// 初始置换表IP
unsigned char IP_Table[64] = { 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,

                     56,48,40,32,24,16,8,0,

                     58,50,42,34,26,18,10,2,

                     60,52,44,36,28,20,12,4,

                     62,54,46,38,30,22,14,6};

//逆初始置换表IP^-1

unsigned char IP_1_Table[64] = {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,
                       
                                   32,0,40,8,48,16,56,24};


//扩充置换表E

unsigned char E_Table[48] = {31, 0, 1, 2, 3, 4,

                  3, 4, 5, 6, 7, 8,

                  7, 8,9,10,11,12,

                  11,12,13,14,15,16,

                  15,16,17,18,19,20,

                  19,20,21,22,23,24,

                  23,24,25,26,27,28,

                  27,28,29,30,31, 0};


//置换函数P

unsigned char P_Table[32] = {15,6,19,20,28,11,27,16,

                  0,14,22,25,4,17,30,9,

                  1,7,23,13,31,26,2,8,

                  18,12,29,5,21,10,3,24};


//S盒

unsigned char S[8][4][16] =// 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}}};

//置换选择1

unsigned char PC_1[56] = {56,48,40,32,24,16,8,

              0,57,49,41,33,25,17,

              9,1,58,50,42,34,26,

              18,10,2,59,51,43,35,

              62,54,46,38,30,22,14,

              6,61,53,45,37,29,21,

              13,5,60,52,44,36,28,

              20,12,4,27,19,11,3};


//置换选择2

unsigned char PC_2[48] = {13,16,10,23,0,4,2,27,

              14,5,20,9,22,18,11,3,

              25,7,15,6,26,19,12,1,

              40,51,30,36,46,54,29,39,

              50,44,32,46,43,48,38,55,

              33,52,45,41,49,35,28,31};


// 对左移次数的规定

unsigned char MOVE_TIMES[16] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};


//字节转换成二进制

unsigned char ByteToBit(unsigned char ch, unsigned char bit[8])
{
    unsigned char cnt;
    for(cnt = 0;cnt < 8; cnt++)
        {
        *(bit+cnt) = (ch>>cnt)&1;
    }
    return 0;
}


// 二进制转换成字节

unsigned char BitToByte(unsigned char bit[8],unsigned char *ch)
{
    unsigned char cnt;
    for(cnt = 0;cnt < 8; cnt++)
        {
        *ch |= *(bit + cnt)<<cnt;
    }
    return 0;
}


// 将长度为8的字符串转为二进制位串

unsigned char Char8ToBit64(unsigned char ch[8],unsigned char bit[64])
{
    unsigned char cnt;
    for(cnt = 0; cnt < 8; cnt++)
        {      
        ByteToBit(*(ch+cnt),bit+(cnt<<3));
    }
    return 0;
}


// 将二进制位串转为长度为8的字符串

unsigned char Bit64ToChar8(unsigned char bit[64],unsigned char ch[8])
{
    unsigned char cnt;
    memset(ch,0,8);
    for(cnt = 0; cnt < 8; cnt++)
        {
        BitToByte(bit+(cnt<<3),ch+cnt);
    }
    return 0;
}


// 密钥置换1

unsigned char DES_PC1_Transform(unsigned char key[64], unsigned char tempbts[56])
{
    unsigned char cnt;   
    for(cnt = 0; cnt < 56; cnt++)
        {
        tempbts[cnt] = key[PC_1[cnt]];
    }
    return 0;
}

//密钥置换2

unsigned char DES_PC2_Transform(unsigned char key[56], unsigned char tempbts[48])
{
    unsigned char cnt;
    for(cnt = 0; cnt < 48; cnt++)
        {
        tempbts[cnt] = key[PC_2[cnt]];
    }
    return 0;
}
//循环左移

unsigned char DES_ROL(unsigned char data[56], unsigned char time)
{   
    unsigned char temp[56];

    //保存将要循环移动到右边的位
    memcpy(temp,data,time);
    memcpy(temp+time,data+28,time);

    //前28位移动
    memcpy(data,data+time,28-time);
    memcpy(data+28-time,temp,time);

    //后28位移动
    memcpy(data+28,data+28+time,28-time);
    memcpy(data+56-time,temp+time,time);   
    return 0;
}


//IP置换

unsigned char DES_IP_Transform(unsigned char data[64])
{
    unsigned char cnt;
    unsigned char temp[64];
    for(cnt = 0; cnt < 64; cnt++)
        {
        temp[cnt] = data[IP_Table[cnt]];
    }
    memcpy(data,temp,64);
    return 0;
}

// IP逆置换

unsigned char DES_IP_1_Transform(unsigned char data[64])
{
    unsigned char cnt;
    unsigned char temp[64];
    for(cnt = 0; cnt < 64; cnt++)
        {
        temp[cnt] = data[IP_1_Table[cnt]];
    }
    memcpy(data,temp,64);
    return 0;
}


//扩展置换

unsigned char DES_E_Transform(unsigned char data[48])
{
    unsigned char cnt;
    unsigned char temp[48];
    for(cnt = 0; cnt < 48; cnt++)
        {
        temp[cnt] = data[E_Table[cnt]];
    }   
    memcpy(data,temp,48);
    return 0;
}

//P置换

unsigned char DES_P_Transform(unsigned char data[32])
{
    unsigned char cnt;
    unsigned char temp[32];
    for(cnt = 0; cnt < 32; cnt++)
        {
        temp[cnt] = data[P_Table[cnt]];
    }   
    memcpy(data,temp,32);
    return 0;
}

// 异或

unsigned char DES_XOR(unsigned char R[48], unsigned char L[48] ,unsigned char count)
{
    unsigned char cnt;
    for(cnt = 0; cnt < count; cnt++)
        {
        R[cnt] ^= L[cnt];
    }
    return 0;
}

// S盒置换

unsigned char DES_SBOX(unsigned char data[48])
{
    unsigned char cnt;
    unsigned char line,row,output;
    unsigned char cur1,cur2;
    for(cnt = 0; cnt < 8; cnt++)
        {
        cur1 = cnt*6;
        cur2 = cnt<<2;
        // 计算在S盒中的行与列
        line = (data[cur1]<<1) + data[cur1+5];
        row = (data[cur1+1]<<3) + (data[cur1+2]<<2)
            + (data[cur1+3]<<1) + data[cur1+4];
        output = S[cnt][line][row];
        // 化为2进制
        data[cur2] = (output&0X08)>>3;
                data[cur2+1] = (output&0X04)>>2;
        data[cur2+2] = (output&0X02)>>1;
        data[cur2+3] = output&0x01;
    }   
    return 0;
}

//交换

unsigned char DES_Swap(unsigned char left[32], unsigned char right[32])
{
    unsigned char temp[32];
    memcpy(temp,left,32);   
    memcpy(left,right,32);   
    memcpy(right,temp,32);
    return 0;
}

//生成子密钥

unsigned char DES_MakeSubKeys(unsigned char key[64],unsigned char subKeys[16][48])
{
        unsigned char temp[56];
        unsigned char cnt;
        DES_PC1_Transform(key,temp);// PC1置换
        for(cnt = 0; cnt < 16; cnt++) //16轮跌代,产生16个子密钥
        {
                DES_ROL(temp,MOVE_TIMES[cnt]);// 循环左移
                DES_PC2_Transform(temp,subKeys[cnt]);//PC2置换,产生子密钥
        }
        return 0;
}

//加密单个分组

unsigned char DES_EncryptBlock(unsigned char plainBlock[8], unsigned char subKeys[16][48], unsigned char cipherBlock[8])
{
    unsigned char plainBits[64];
    unsigned char copyRight[48];
    unsigned char cnt;
    Char8ToBit64(plainBlock,plainBits);      
    //初始置换(IP置换)
    DES_IP_Transform(plainBits);
    // 16轮迭代
    for(cnt = 0; cnt < 16; cnt++)
        {      
        memcpy(copyRight,plainBits+32,32);
        DES_E_Transform(copyRight);                        // 将右半部分进行扩展置换,从32位扩展到48位
        DES_XOR(copyRight,subKeys[cnt],48);        // 将右半部分与子密钥进行异或操作
        DES_SBOX(copyRight);                                // 异或结果进入S盒,输出32位结果
        DES_P_Transform(copyRight);                        // P置换
        DES_XOR(plainBits,copyRight,32);        //将明文左半部分与右半部分进行异或
        if(cnt != 15)
                {
            DES_Swap(plainBits,plainBits+32);//最终完成左右部的交换
        }
    }
    DES_IP_1_Transform(plainBits);                        //逆初始置换(IP^1置换)
    Bit64ToChar8(plainBits,cipherBlock);
    return 0;
}

// 解密单个分组
unsigned char DES_DecryptBlock(unsigned char cipherBlock[8], unsigned char subKeys[16][48],unsigned char plainBlock[8])
{
    unsigned char cipherBits[64];
    unsigned char copyRight[48];
    short cnt;
    Char8ToBit64(cipherBlock,cipherBits);      
    //初始置换(IP置换)
    DES_IP_Transform(cipherBits);
    // 16轮迭代
    for(cnt = 15; cnt >= 0; cnt--)
        {      
        memcpy(copyRight,cipherBits+32,32);
        //将右半部分进行扩展置换,从32位扩展到48位
        DES_E_Transform(copyRight);
        // 将右半部分与子密钥进行异或操作
        DES_XOR(copyRight,subKeys[cnt],48);      
        //异或结果进入S盒,输出32位结果
        DES_SBOX(copyRight);
        // P置换
        DES_P_Transform(copyRight);      
        //将明文左半部分与右半部分进行异或
        DES_XOR(cipherBits,copyRight,32);
        if(cnt != 0)
                {
            // 最终完成左右部的交换
            DES_Swap(cipherBits,cipherBits+32);
        }
    }
    // 逆初始置换(IP^1置换)
    DES_IP_1_Transform(cipherBits);
    Bit64ToChar8(cipherBits,plainBlock);
    return 0;
}


//加密文件
unsigned char DES_Encrypt(unsigned char *keyStr,unsigned char *plainFile,unsigned char *cipherFile)
{
    unsigned char keyBlock[8],bKey[64],subKeys[16][48];

    memcpy(keyBlock,keyStr,8);                                                         //设置密钥
    Char8ToBit64(keyBlock,bKey);                                                 //将密钥转换为二进制流
    DES_MakeSubKeys(bKey,subKeys);                                                 //生成子密钥

        DES_EncryptBlock(plainFile,subKeys,cipherFile);         
        return 1;
}

//解密文件
unsigned char DES_Decrypt(unsigned char *keyStr,unsigned char *cipherFile,unsigned char *plainFile)
{
//        unsigned char plainBlock[8],cipherBlock[8],
    unsigned char bKey[64],keyBlock[8],subKeys[16][48];

    memcpy(keyBlock,keyStr,8);                                                        //设置密钥
    Char8ToBit64(keyBlock,bKey);                                                //将密钥转换为二进制流
    DES_MakeSubKeys(bKey,subKeys);                                                //生成子密钥

        DES_DecryptBlock(cipherFile,subKeys,plainFile);                       
        return 1;
}

/***********************************************************************************************
* 作    者:win2kddk
* 说    明:3重DES是使用16字节密钥将8字节明文数据块进行3次DES加密和解密。
***********************************************************************************************/
unsigned char DES_key[16];
void DEC3_Encrypt(unsigned char *in_buf, unsigned char *miwen)
{
        unsigned char buf1[8],buf2[8];

        DES_Encrypt(&DES_key[0],in_buf,buf1);
    DES_Decrypt(&DES_key[8],buf1,buf2);
        DES_Encrypt(&DES_key[0],buf2,miwen);
}

void DEC3_Decrypt(unsigned char *miwen, unsigned char *out_buf)
{
        unsigned char buf1[8],buf2[8];

    DES_Decrypt(&DES_key[0],miwen,buf1);
        DES_Encrypt(&DES_key[8],buf1,buf2);
    DES_Decrypt(&DES_key[0],buf2,out_buf);
}

void DES3_Test(void)
{
    unsigned char in_buf[8] = "ABCDEFGH";
        unsigned char miwen[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
        unsigned char out_buf[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

        memcpy(DES_key,"0123456789abcdef",16);//3DES的密钥是128位的,这里只是设置密钥的DEMO。
       
        DEC3_Encrypt(in_buf,miwen);          //3DES加密
        DEC3_Decrypt(miwen,out_buf);  //3DES解密
}

使用特权

评论回复
18
東南博士|  楼主 | 2018-2-27 13:57 | 只看该作者
#define BPOLY 0x1b //!< Lower 8 bits of (x^8+x^4+x^3+x+1), ie. (x^4+x^3+x+1).
#define BLOCKSIZE 16 //!< Block size in number of bytes.

#define KEY_COUNT 3

#if KEY_COUNT == 1
  #define KEYBITS 128 //!< Use AES128.
#elif KEY_COUNT == 2
  #define KEYBITS 192 //!< Use AES196.
#elif KEY_COUNT == 3
  #define KEYBITS 256 //!< Use AES256.
#else
  #error Use 1, 2 or 3 keys!
#endif

#if KEYBITS == 128
  #define ROUNDS 10 //!< Number of rounds.
  #define KEYLENGTH 16 //!< Key length in number of bytes.
#elif KEYBITS == 192
  #define ROUNDS 12 //!< Number of rounds.
  #define KEYLENGTH 24 //!< // Key length in number of bytes.
#elif KEYBITS == 256
  #define ROUNDS 14 //!< Number of rounds.
  #define KEYLENGTH 32 //!< Key length in number of bytes.
#else
  #error Key must be 128, 192 or 256 bits!
#endif


#define EXPANDED_KEY_SIZE (BLOCKSIZE * (ROUNDS+1)) //!< 176, 208 or 240 bytes.

unsigned char AES_Key_Table[32] =
{
  0xd0, 0x94, 0x3f, 0x8c, 0x29, 0x76, 0x15, 0xd8,
  0x20, 0x40, 0xe3, 0x27, 0x45, 0xd8, 0x48, 0xad,
  0xea, 0x8b, 0x2a, 0x73, 0x16, 0xe9, 0xb0, 0x49,
  0x45, 0xb3, 0x39, 0x28, 0x0a, 0xc3, 0x28, 0x3c,
};

unsigned char block1[256]; //!< Workspace 1.
unsigned char block2[256]; //!< Worksapce 2.
unsigned char tempbuf[256];

unsigned char *powTbl; //!< Final location of exponentiation lookup table.
unsigned char *logTbl; //!< Final location of logarithm lookup table.
unsigned char *sBox; //!< Final location of s-box.
unsigned char *sBoxInv; //!< Final location of inverse s-box.
unsigned char *expandedKey; //!< Final location of expanded key.

void CalcPowLog(unsigned char *powTbl, unsigned char *logTbl)
{
        unsigned char i = 0;
        unsigned char t = 1;
       
        do {
                // Use 0x03 as root for exponentiation and logarithms.
                powTbl[i] = t;
                logTbl[t] = i;
                i++;
               
                // Muliply t by 3 in GF(2^8).
                t ^= (t << 1) ^ (t & 0x80 ? BPOLY : 0);
        }while( t != 1 ); // Cyclic properties ensure that i < 255.
       
        powTbl[255] = powTbl[0]; // 255 = '-0', 254 = -1, etc.
}

void CalcSBox( unsigned char * sBox )
{
        unsigned char i, rot;
        unsigned char temp;
        unsigned char result;
       
        // Fill all entries of sBox[].
        i = 0;
        do {
                //Inverse in GF(2^8).
                if( i > 0 )
                {
                        temp = powTbl[ 255 - logTbl[i] ];
                }
                else
                {
                        temp = 0;
                }
               
                // Affine transformation in GF(2).
                result = temp ^ 0x63; // Start with adding a vector in GF(2).
                for( rot = 0; rot < 4; rot++ )
                {
                        // Rotate left.
                        temp = (temp<<1) | (temp>>7);
                       
                        // Add rotated byte in GF(2).
                        result ^= temp;
                }
               
                // Put result in table.
                sBox[i] = result;
        } while( ++i != 0 );
}

void CalcSBoxInv( unsigned char * sBox, unsigned char * sBoxInv )
{
        unsigned char i = 0;
        unsigned char j = 0;
       
        // Iterate through all elements in sBoxInv using  i.
        do {
        // Search through sBox using j.
                do {
                        // Check if current j is the inverse of current i.
                        if( sBox[ j ] == i )
                        {
                                // If so, set sBoxInc and indicate search finished.
                                sBoxInv[ i ] = j;
                                j = 255;
                        }
                } while( ++j != 0 );
        } while( ++i != 0 );
}

void CycleLeft( unsigned char * row )
{
        // Cycle 4 bytes in an array left once.
        unsigned char temp = row[0];
       
        row[0] = row[1];
        row[1] = row[2];
        row[2] = row[3];
        row[3] = temp;
}

void InvMixColumn( unsigned char * column )
{
        unsigned char r0, r1, r2, r3;
       
        r0 = column[1] ^ column[2] ^ column[3];
        r1 = column[0] ^ column[2] ^ column[3];
        r2 = column[0] ^ column[1] ^ column[3];
        r3 = column[0] ^ column[1] ^ column[2];
       
        column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
        column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
        column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
        column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
       
        r0 ^= column[0] ^ column[1];
        r1 ^= column[1] ^ column[2];
        r2 ^= column[2] ^ column[3];
        r3 ^= column[0] ^ column[3];
       
        column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
        column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
        column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
        column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
       
        r0 ^= column[0] ^ column[2];
        r1 ^= column[1] ^ column[3];
        r2 ^= column[0] ^ column[2];
        r3 ^= column[1] ^ column[3];
       
        column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
        column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
        column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
        column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
       
        column[0] ^= column[1] ^ column[2] ^ column[3];
        r0 ^= column[0];
        r1 ^= column[0];
        r2 ^= column[0];
        r3 ^= column[0];
       
        column[0] = r0;
        column[1] = r1;
        column[2] = r2;
        column[3] = r3;
}

void SubBytes( unsigned char * bytes, unsigned char count )
{
        do {
                *bytes = sBox[ *bytes ]; // Substitute every byte in state.
                bytes++;
        } while( --count );
}

void InvSubBytesAndXOR( unsigned char * bytes, unsigned char * key, unsigned char count )
{
        do {
                // *bytes = sBoxInv[ *bytes ] ^ *key; // Inverse substitute every byte in state and add key.
                *bytes = block2[ *bytes ] ^ *key; // Use block2 directly. Increases speed.
                bytes++;
                key++;
        } while( --count );
}

void InvShiftRows( unsigned char * state )
{
        unsigned char temp;
       
        // Note: State is arranged column by column.
       
        // Cycle second row right one time.
        temp = state[ 1 + 3*4 ];
        state[ 1 + 3*4 ] = state[ 1 + 2*4 ];
        state[ 1 + 2*4 ] = state[ 1 + 1*4 ];
        state[ 1 + 1*4 ] = state[ 1 + 0*4 ];
        state[ 1 + 0*4 ] = temp;
       
        // Cycle third row right two times.
        temp = state[ 2 + 0*4 ];
        state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
        state[ 2 + 2*4 ] = temp;
        temp = state[ 2 + 1*4 ];
        state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
        state[ 2 + 3*4 ] = temp;
       
        // Cycle fourth row right three times, ie. left once.
        temp = state[ 3 + 0*4 ];
        state[ 3 + 0*4 ] = state[ 3 + 1*4 ];
        state[ 3 + 1*4 ] = state[ 3 + 2*4 ];
        state[ 3 + 2*4 ] = state[ 3 + 3*4 ];
        state[ 3 + 3*4 ] = temp;
}

void InvMixColumns( unsigned char * state )
{
        InvMixColumn( state + 0*4 );
        InvMixColumn( state + 1*4 );
        InvMixColumn( state + 2*4 );
        InvMixColumn( state + 3*4 );
}

void XORBytes( unsigned char * bytes1, unsigned char * bytes2, unsigned char count )
{
        do {
                *bytes1 ^= *bytes2; // Add in GF(2), ie. XOR.
                bytes1++;
                bytes2++;
        } while( --count );
}

void CopyBytes( unsigned char * to, unsigned char * from, unsigned char count )
{
        do {
                *to = *from;
                to++;
                from++;
        } while( --count );
}

void KeyExpansion( unsigned char * expandedKey )
{
        unsigned char temp[4];
        unsigned char i;
        unsigned char Rcon[4] = { 0x01, 0x00, 0x00, 0x00 }; // Round constant.
       
        unsigned char * key = AES_Key_Table;
       
        // Copy key to start of expanded key.
        i = KEYLENGTH;
        do {
                *expandedKey = *key;
                expandedKey++;
                key++;
        } while( --i );
       
        // Prepare last 4 bytes of key in temp.
        expandedKey -= 4;
        temp[0] = *(expandedKey++);
        temp[1] = *(expandedKey++);
        temp[2] = *(expandedKey++);
        temp[3] = *(expandedKey++);
       
        // Expand key.
        i = KEYLENGTH;
        while( i < BLOCKSIZE*(ROUNDS+1) )
        {
                // Are we at the start of a multiple of the key size?
                if( (i % KEYLENGTH) == 0 )
                {
                        CycleLeft( temp ); // Cycle left once.
                        SubBytes( temp, 4 ); // Substitute each byte.
                        XORBytes( temp, Rcon, 4 ); // Add constant in GF(2).
                        *Rcon = (*Rcon << 1) ^ (*Rcon & 0x80 ? BPOLY : 0);
                }
               
                // Keysize larger than 24 bytes, ie. larger that 192 bits?
                #if KEYLENGTH > 24
                // Are we right past a block size?
                else if( (i % KEYLENGTH) == BLOCKSIZE ) {
                SubBytes( temp, 4 ); // Substitute each byte.
                }
                #endif
               
                // Add bytes in GF(2) one KEYLENGTH away.
                XORBytes( temp, expandedKey - KEYLENGTH, 4 );
               
                // Copy result to current 4 bytes.
                *(expandedKey++) = temp[ 0 ];
                *(expandedKey++) = temp[ 1 ];
                *(expandedKey++) = temp[ 2 ];
                *(expandedKey++) = temp[ 3 ];
               
                i += 4; // Next 4 bytes.
        }
}

void InvCipher( unsigned char * block, unsigned char * expandedKey )
{
        unsigned char round = ROUNDS-1;
        expandedKey += BLOCKSIZE * ROUNDS;
       
        XORBytes( block, expandedKey, 16 );
        expandedKey -= BLOCKSIZE;
       
        do {
                InvShiftRows( block );
                InvSubBytesAndXOR( block, expandedKey, 16 );
                expandedKey -= BLOCKSIZE;
                InvMixColumns( block );
        } while( --round );
       
        InvShiftRows( block );
        InvSubBytesAndXOR( block, expandedKey, 16 );
}

void aesDecInit(void)
{
        powTbl = block1;
        logTbl = block2;
        CalcPowLog( powTbl, logTbl );
       
        sBox = tempbuf;
        CalcSBox( sBox );
       
        expandedKey = block1;
        KeyExpansion( expandedKey );
       
        sBoxInv = block2; // Must be block2.
        CalcSBoxInv( sBox, sBoxInv );
}

void aesDecrypt( unsigned char * buffer, unsigned char * chainBlock )
{
        unsigned char temp[ BLOCKSIZE ];
       
        CopyBytes( temp, buffer, BLOCKSIZE );
        InvCipher( buffer, expandedKey );
        XORBytes( buffer, chainBlock, BLOCKSIZE );
        CopyBytes( chainBlock, temp, BLOCKSIZE );
}

unsigned char Multiply( unsigned char num, unsigned char factor )
{
        unsigned char mask = 1;
        unsigned char result = 0;
       
        while( mask != 0 )
        {
        // Check bit of factor given by mask.
                if( mask & factor )
                {
                  // Add current multiple of num in GF(2).
                  result ^= num;
                }
       
                // Shift mask to indicate next bit.
                mask <<= 1;
               
                // Double num.
                num = (num << 1) ^ (num & 0x80 ? BPOLY : 0);
        }
       
        return result;
}

unsigned char DotProduct( unsigned char * vector1, unsigned char * vector2 )
{
        unsigned char result = 0;
       
        result ^= Multiply( *vector1++, *vector2++ );
        result ^= Multiply( *vector1++, *vector2++ );
        result ^= Multiply( *vector1++, *vector2++ );
        result ^= Multiply( *vector1  , *vector2   );
       
        return result;
}

void MixColumn( unsigned char * column )
{
        unsigned char row[8] = {0x02, 0x03, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01};
        // Prepare first row of matrix twice, to eliminate need for cycling.
       
        unsigned char result[4];
       
        // Take dot products of each matrix row and the column vector.
        result[0] = DotProduct( row+0, column );
        result[1] = DotProduct( row+3, column );
        result[2] = DotProduct( row+2, column );
        result[3] = DotProduct( row+1, column );
       
        // Copy temporary result to original column.
        column[0] = result[0];
        column[1] = result[1];
        column[2] = result[2];
        column[3] = result[3];
}

void MixColumns( unsigned char * state )
{
        MixColumn( state + 0*4 );
        MixColumn( state + 1*4 );
        MixColumn( state + 2*4 );
        MixColumn( state + 3*4 );
}

void ShiftRows( unsigned char * state )
{
        unsigned char temp;
       
        // Note: State is arranged column by column.
       
        // Cycle second row left one time.
        temp = state[ 1 + 0*4 ];
        state[ 1 + 0*4 ] = state[ 1 + 1*4 ];
        state[ 1 + 1*4 ] = state[ 1 + 2*4 ];
        state[ 1 + 2*4 ] = state[ 1 + 3*4 ];
        state[ 1 + 3*4 ] = temp;
       
        // Cycle third row left two times.
        temp = state[ 2 + 0*4 ];
        state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
        state[ 2 + 2*4 ] = temp;
        temp = state[ 2 + 1*4 ];
        state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
        state[ 2 + 3*4 ] = temp;
       
        // Cycle fourth row left three times, ie. right once.
        temp = state[ 3 + 3*4 ];
        state[ 3 + 3*4 ] = state[ 3 + 2*4 ];
        state[ 3 + 2*4 ] = state[ 3 + 1*4 ];
        state[ 3 + 1*4 ] = state[ 3 + 0*4 ];
        state[ 3 + 0*4 ] = temp;
}

void Cipher( unsigned char * block, unsigned char * expandedKey )
{
        unsigned char round = ROUNDS-1;
       
        XORBytes( block, expandedKey, 16 );
        expandedKey += BLOCKSIZE;
       
        do {
                SubBytes( block, 16 );
                ShiftRows( block );
                MixColumns( block );
                XORBytes( block, expandedKey, 16 );
                expandedKey += BLOCKSIZE;
        } while( --round );
       
        SubBytes( block, 16 );
        ShiftRows( block );
        XORBytes( block, expandedKey, 16 );
}

void aesEncInit(void)
{
        powTbl = block1;
        logTbl = tempbuf;
        CalcPowLog( powTbl, logTbl );
       
        sBox = block2;
        CalcSBox( sBox );
       
        expandedKey = block1;
        KeyExpansion( expandedKey );
}

void aesEncrypt( unsigned char * buffer, unsigned char * chainBlock )
{
        XORBytes( buffer, chainBlock, BLOCKSIZE );
        Cipher( buffer, expandedKey );
        CopyBytes( chainBlock, buffer, BLOCKSIZE );
}

#include <string.h>
void AES_Test(void)
{
        unsigned char dat[16]="0123456789ABCDEF";
        unsigned char chainCipherBlock[16];
    unsigned char i;
        for(i=0;i<32;i++) AES_Key_Table[i]=i;//做运算之前先要设置好密钥,这里只是设置密钥的DEMO。


        memset(chainCipherBlock,0x00,sizeof(chainCipherBlock));

        aesEncInit();//在执行加密初始化之前可以为AES_Key_Table赋值有效的密码数据

        aesEncrypt(dat, chainCipherBlock);//AES加密,数组dat里面的新内容就是加密后的数据。
        //aesEncrypt(dat+16, chainCipherBlock);//AES源数据大于16字节时,把源数据的指针+16就好了


       
        memset(chainCipherBlock,0x00,sizeof(chainCipherBlock));//这里要重新初始化清空

        aesDecInit();//在执行解密初始化之前可以为AES_Key_Table赋值有效的密码数据

        aesDecrypt(dat, chainCipherBlock);//AES解密,密文数据存放在dat里面,经解密就能得到之前的明文。
        //aesDecrypt(dat+16, chainCipherBlock);//AES源数据大于16字节时,把源数据的指针+16就好了
}

使用特权

评论回复
19
東南博士|  楼主 | 2018-2-27 13:58 | 只看该作者
算法的压缩包!
上传到这里!

加密算法源码.rar

15.69 KB

使用特权

评论回复
20
東南博士|  楼主 | 2018-2-27 13:58 | 只看该作者
欢迎大家 一起探讨啊!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

367

主题

6048

帖子

34

粉丝