打印

哪位兄弟有在单片机上跑的DES,3DES算法?

[复制链接]
8199|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
涛行九天|  楼主 | 2010-12-12 16:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
涛行九天|  楼主 | 2010-12-14 02:55 | 只看该作者
出差一天,帖子就不见了,晕倒啊

哪位兄弟有,c语言的也行啊,多谢了!

使用特权

评论回复
板凳
airwill| | 2010-12-14 06:51 | 只看该作者
这是本人网上摘录到的单片机汇编语言实现DES加密算法
http://www.c51.cn/mcu/mcs51yy/200709/mcu_20070903210544_6703.html

2008-06-10 13:50:46 来源:网络 作者:未知 【大 中 小】 点击:242 次
目前在金融界及非金融界的保密通信中,越来越多地用到了DES算法。DES(Data Encryption Standard)即数据加密算法,是IBM公司于 1977年研究成功并公开发表的。随着我国三金工程尤其是金卡工程的启动,DES算法在POS、ATM、磁卡及智能卡(IC卡)中被广泛应用,以此来实现关键数据的保密。如信用*持卡人的PIN的加密传输、IC卡与POS间的双向认证、金融交易中的密码键盘等,均用到DES算法。由于密码键盘不可能使用高级语言,所以用汇编语言实现DES就非常实用。
1 DES算法的简单原理

  DES是一种分组密码。假定明文m是由0和1组成的长度为64位的符号串,密钥k也是64位的0、1符号串。

   设:M=m1m2m3…m64

   K=k1k2k3…k64

    加密过程可表达如下:

    DES(m)=IP-1·T16·T15…T2·T1·IP(m)

    其中:IP(m)是初始置换,IP-1是逆置换,T16~T1是16次迭代。

    (1)初始置换IP

  功能是把输入的明文m按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则如下:

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

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

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

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

57,49,41,33,25,17,9 ,1,

59,51,43,35,27,19,11,3,

61,53,45,37,29,21,13,5,

63,55,47,39,31,23,15,7

    (2)逆置换IP-1

  经过16次迭代运算后,得到L16、R16,将此作为输入,进行逆置换。逆置换满足:

    IP·IP-1=IP-1·IP=I

    逆置换正好是初始置换的逆运算。

    (3)T16~T1的迭代计算

  DES的迭代算法采用模2加法。

  在通信网络的两端,双方约定了一致的密钥。在通信的源点用密钥对核心数据进行加密并形成密文,然后,以密文的形式在公共通信网中传输到通信网络的终点。数据到达终点后,用同样的密钥对密文数据进行解密,便再现了明文形式的核心数据。这样,便保证了核心数据(如PIN、MAC等)在公共通信网中传输的安全性和可靠性。

2 汇编语言的实现

  用汇编语言实现DES算法有它的优势也有它的难点。优势是51汇编的位操作可以方便地实现置换功能。但用汇编语言实现算法的迭代运算及循环功能比较烦琐。在用51汇编实现DES的过程中,我编写了几个子程序,组合起来可实现DES算法加密。在这里写出一些思路,有需要的同行可与我联系(E-mail:zhoubin@jlu.edu.cn)。

  8031有16个可以位寻址的寄存器,可放置128位的数据,利用它可实现DES的转置功能。将明文m放入寄存器27H~20H中,即位地址00H对应m64 ,3FH对应m1。利用标志寄存器C可实现置换与逆置换程序。在DES的16次迭代过程中,要实现公式:

    Li=Ri-1;Ri=Li-1f(Ri-1,ki)

    的运算过程,其关键在于f(Ri-1,ki)的功能。f是将32位的输入转化为32位的输出。其中含3项技术:

  ① 将32位膨胀为48位的E功能。该项功能可用类似于置换功能的子程序编写。

  ② 48位子密钥的生成。为了便于51汇编生成子密钥,可以使用主机用串口下传的方式,由主机将16个子密钥传给89C52为核心的单片机,然后存入80H~FFH中。如果密钥是固定的,则可直接将子密钥固化在89C52的Flash中。

  ③ S盒的功能是将48位的输入再次缩为32位。具体实现是将S盒表存入89C52的Flash中,每次通过查表求得S输出的结果。

    下面列举其中的几个子程序。

(1)IP置换子程序

;入口寄存器:(MSB)2726252423222120(LSB),出口寄存器:(MSB)2F2E2D2C2B2A2928(LSB)

;功能:将入口寄存器的数据按置换表换位。

IP: MOV C,06H ;将m58送到进位标志中

MOV 7FH,C ;将进位标志送m1中

MOV C,0EH ;将m50送到进位标志中

MOV 7EH,C ;将进位标志送m2中

;重复,按表编写

……

MOV C,31H ;将m15送到进位标志中

MOV 41H,C ;将进位标志送m63中

MOV C,39H ;将m7送到进位标志中

MOV 40H,C ;将进位标志送m64中

RET

(2)逆置换子程序

;入口寄存器:(MSB)2726252423222120(LSB),出口寄存器:(MSB)2F2E2D2C2B2A2928(LSB)

;功能:将入口寄存器的数据按逆置换表换位。

IPRVS:MOV C,18H ;将m40送到进位标志中

MOV 7FH,C ;将进位标志送m1中

MOV C,38H

……

RET

(3)异或子程序

;入口寄存器:272625243F3E3D3C,出口寄存器:2B2A2928

;功能:将寄存器27262524的内容和寄存器3F3E3D3C的内容异或。结果保存在2B2A2928寄存器中。

XORLF: MOV A,3FH ;将高8位异或

XRL A,27H

MOV 2BH,A ;放入出口处

MOV A,3EH

XRL A,26H

MOV 2AH,A

MOV A,3DH

XRL A,25H

MOV 29H,A

MOV A,3CH

XRL A,24H

MOV 28H,A

RET

(4)S盒子程序

;入口寄存器:(MSB)2F2E2D2C2B2A2928,出口寄存器:(MSB)27262524

;功能:48位→32位

S6TO4: MOV 20h,2FH ;取出高位数据

LCALL S162345 ;调用实现Si(b1b6,b2b3b4b5)

;的功能子程序

MOV DPTR,#S1TAB;S盒表的首址

MOV A,21H ;取出第几个S盒

LCALL DPTRADD

CLR A

MOVC A,@A+DPTR;求出S盒的表地址及S 结果

SWAP A

MOV 27H,A ;保存高位结果

MOV 20H,2EH

LCALL S162345

;重复

RET

利用这些子程序,我们成功地开发了以89C52为核心单片机的密钥键盘,可用于金融系统的用户远程密码修改,也可用于其它商用密文的传输。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
老鱼探戈 + 1
地板
ejack| | 2010-12-14 08:06 | 只看该作者
Woah!学习中……

使用特权

评论回复
5
mtwumtwu| | 2010-12-14 08:40 | 只看该作者
good leraning material

使用特权

评论回复
6
涛行九天|  楼主 | 2010-12-14 13:26 | 只看该作者
原理清楚,上学的时候学过一门课《计算机加解密技术》

使用特权

评论回复
7
hotpower| | 2010-12-14 15:55 | 只看该作者
可惜hotwc3没资质…

使用特权

评论回复
8
yewuyi| | 2010-12-14 16:38 | 只看该作者
哈哈,不懂不懂。。。

热电源抓紧和九天排忧解难。。。

使用特权

评论回复
9
dragon20100708| | 2010-12-14 16:47 | 只看该作者
leraning

使用特权

评论回复
10
wendongwei| | 2010-12-14 17:22 | 只看该作者
我有C语言实现的3DES加密算法,可我没用位寄存器,因为位寄存器较少,与其来回交换,不如用一个字节代表一位,这样更通用,速度更快一些,况且也不缺这几百字节。因此在函数的开始要将64位8字节的明文转换为64字节的明文,每个字节代表一位,存放在xdata中,以下是主要函数(新手,写的可能不够好,让大家见笑了):
typedef unsigned char uint8;
typedef unsigned long uint32;
uint8 xdata DES_IP[64]={
                58,50,42,34,26,18,10, 2,
                60,52,44,36,28,20,12, 4,
                62,54,46,38,30,22,14, 6,
                64,56,48,40,32,24,16, 8,
               
                57,49,41,33,25,17, 9, 1,
                59,51,43,35,27,19,11, 3,
                61,53,45,37,29,21,13, 5,
                63,55,47,39,31,23, 15,7};
               
uint8 xdata DES_IP_1[64]={
                40, 8,48,16,56,24,64,32,
                39, 7,47,15,55,23,63,31,
                38, 6,46,14,54,22,62,30,
                37, 5,45,13,53,21,61,29,
               
                36, 4,44,12,52,20,60,28,
                35, 3,43,11,51,19,59,27,
                34, 2,42,10,50,18,58,26,
                33, 1,41, 9,49,17,57,25};
               
uint8 xdata DES_PC_1[56]={
                57,49,41,33,25,17, 9,
                 1,58,50,42,34,26,18,
                10, 2,59,51,43,35,27,
                19,11, 3,60,52,44,36,
               
                63,55,47,39,31,23,15,
                 7,62,54,46,38,30,22,
                14, 6,61,53,45,37,29,
                21,13, 5,28,20,12, 4};
               
uint8 xdata DES_PC_2[48]={
                14,17,11,24, 1, 5,
                 3,28,15, 6,21,10,
                23,19,12, 4,26, 3,
                16, 7,27,20,13, 2,
               
                41,52,31,37,47,55,
                30,40,51,45,33,48,
                44,49,39,56,34,53,
                46,42,50,36,29,32};
               
uint8 xdata shift[16]={1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
               
uint8 xdata DES_E[48]={
                32, 1, 2, 3, 4, 5,
                 4, 5, 6, 7, 8, 9,
                 8, 9,10,11,12,13,
                12,13,14,15,16,17,
               
                16,17,18,19,20,21,
                20,21,22,23,24,25,
                24,25,26,27,28,29,
                28,29,30,31,32, 1};
               
uint8 xdata DES_S[8][4][16]={
                {{14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7},
                 { 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8},
                 { 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0},
                 {15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13}},
                 
                {{15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10},  
                   { 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5},  
                   { 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15},  
                   {13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9}},
                 
                {{10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8},  
                   {13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1},  
                   {13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7},  
                   { 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12}},
                 
                {{ 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15},  
                    {13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9},  
                   {10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4},  
                   { 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14}},
                 
                {{ 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9},  
                   {14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6},  
                   { 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14},  
                   {11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3}},
                  
                {{12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11},  
                   {10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8},  
                   { 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6},  
                   { 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13}},  
         
                {{ 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1},  
                   {13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6},  
                   { 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2},  
                   { 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12}},  
         
                  {{13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7},  
                  { 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2},  
                   { 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8},  
                   { 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11}}};
       
uint8 xdata DES_P[32]={
                16, 7,20,21,
                29,12,28,17,
                 1,15,23,26,
                 5,18,31,10,
                 2, 8,24,14,
                32,27, 2, 9,
                19,13,30, 6,
                22,11, 4,25};       
       
uint8 xdata M[64]="";       
uint8 xdata M2[64]="";       
uint8 xdata RSK[48]="";
uint8 xdata RSK2[32]="";
uint8 xdata temp[32]="";
       
uint8 xdata key[192]="";
uint8 xdata key3[24]="";       
uint8 xdata key2[168]="";
uint8 xdata subkey[48][48]="";

void TripleDES(uint8* DATA,uint8* KEY,uint32 readln,uint8 mode)
{
        bit a;
       
        uint8 i=0,j=0,k=0,l=0;
        uint8 temp1,temp2,temp3,temp4;
        uint8 x=0,y=0,z=0;
        ///校验密钥
        ///
        for(i=0;i<24;i++)                //密钥每位扩大为一个字节
        {
                key3[i]=KEY[i];
                for(j=7;j>0;j--)
                {
                        key[(i<<3)+j]=key3[i]%2;
                        key3[i]>>=1;
                }
                key[i<<3]=key3[i]%2;
        }                                       
        for(i=0;i<56;i++)                        //生成168位密钥
        {
                key2[i]=key[DES_PC_1[i]-1];       
                key2[i+56]=key[DES_PC_1[i]+55];               
                key2[i+112]=key[DES_PC_1[i]+111];
        }
        for(i=0;i<16;i++)                        //生成48组48位的子密钥
        {
                if(shift[i]==1)                        //循环左移一位
                {
                        for(k=0;k<3;k++)
                        {
                                temp1=key2[k*56];
                                temp2=key2[28+k*56];
                                for(j=k*56;j<27+k*56;j++)
                                {
                                        key2[j]=key2[j+1];
                                        key2[j+28]=key2[j+29];
                                }
                                key2[27+k*56]=temp1;
                                key2[55+k*56]=temp2;
                        }
                }
                else if(shift[i]==2)                //循环左移两位
                {
                        for(k=0;k<3;k++)
                        {
                                temp1=key2[k*56];
                                temp2=key2[1+k*56];
                                temp3=key2[28+k*56];
                                temp4=key2[29+k*56];
                                for(j=k*56;j<26+k*56;j++)
                                {
                                        key2[j]=key2[j+2];
                                        key2[j+28]=key2[j+30];
                                }
                                key2[26+k*56]=temp1;
                                key2[27+k*56]=temp2;
                                key2[54+k*56]=temp3;
                                key2[55+k*56]=temp4;
                        }
                }
                for(j=0;j<48;j++)
                {
                        subkey[i][j]=key2[DES_PC_2[j]-1];
                        subkey[i+16][j]=key2[DES_PC_2[j]+55];
                        subkey[i+32][j]=key2[DES_PC_2[j]+111];
                }
        }
        if(readln%8!=0) readln=(readln>>3)+1;
        else readln>>=3;
        for(k=0;k<readln;k++)
        {
                for(i=0;i<8;i++)                //明文每位扩大为一个字节
                {
                        for(j=7;j>0;j--)
                        {
                                M[(i<<3)+j]=DATA[(k<<3)+i]%2;
                                DATA[(k<<3)+i]>>=1;
                        }
                        M[(i<<3)]=DATA[(k<<3)+i]%2;
                }                       
                for(l=0;l<3;l++)
                {
                        if(l>0) mode=(1==mode)?0:1;
                        for(i=0;i<64;i++)                        //生成初始转换表
                                M2[i]=M[DES_IP[i]-1];
                        for(i=0;i<16;i++)                        //16次迭代
                        {
                                for(j=0;j<48;j++)
                                {
                                        if(0==mode) RSK[j]=((M2[DES_E[j]+31]==subkey[i+l*16][j])?0:1);//加密
                                        else RSK[j]=((M2[DES_E[j]+31]==subkey[47-i-l*16][j])?0:1);//解密
                                }
                                for(j=0;j<8;j++)
                                {
                                        x=(RSK[j*6]<<1)+RSK[j*6+5];
                                        y=(RSK[j*6+1]<<3)+(RSK[j*6+2]<<2)+(RSK[j*6+3]<<1)+RSK[j*6+4];
                                        z=DES_S[j][x][y];
                                        RSK2[(j<<2)+3]=z%2;
                                        z=z>>1;
                                        RSK2[(j<<2)+2]=z%2;
                                        z=z>>1;
                                        RSK2[(j<<2)+1]=z%2;
                                        z=z>>1;
                                        RSK2[(j<<2)]=z%2;
                                }
                                for(j=0;j<32;j++)                //P盒转换
                                        temp[j]=((RSK2[DES_P[j]-1]==M2[j])?0:1);
                                if(i<15)
                                {
                                        for(j=0;j<32;j++)                //交换
                                        {
                                                M2[j]=M2[j+32];       
                                                M2[j+32]=temp[j];
                                        }
                                }
                                else
                                {
                                        for(j=0;j<32;j++)                //不交换
                                        {
                                                M2[j]=temp[j];
                                        }       
                                }
                        }
                        for(i=0;i<64;i++)                        //逆置换
                                M[i]=M2[DES_IP_1[i]-1];
                }
                for(i=0;i<8;i++)
                {
                        DATA[(k<<3)+i]=(M[i<<3]<<7)+(M[(i<<3)+1]<<6)+(M[(i<<3)+2]<<5)+(M[(i<<3)+3]<<4)
                                +(M[(i<<3)+4]<<3)+(M[(i<<3)+5]<<2)+(M[(i<<3)+6]<<1)+M[(i<<3)+7];
                }
        }
}

使用特权

评论回复
11
wendongwei| | 2010-12-14 17:26 | 只看该作者
以下是调用示例:
//code by 南京理工大学 温冬伟
//注意:明文长度一定要为8的倍数
uint8 xdata key[24]={0xab,0x36,0x95,0xa1,0x3f,0x55,0xb0,0x12,
                        0xac,0x01,0x95,0x22,0x3f,0x55,0x18,0xa9,
                        0xce,0x30,0x24,0xbb,0x3f,0x44,0x12,0x39};
                       
uint8 xdata text[24]="0123456789abcdef";        //明文
void TripleDES(unsigned char* DATA,unsigned char* KEY,unsigned long readln,unsigned char mode);       
void main()
{
        uint8 i=0;
        Init_iMCU();
       
        putstring("请输入字符\'s\'开始加密程序:\r\n");
        while(GetByte()!='s');
        putstring("加密前明文:\r\n");
        putstring(text);
        putstring("\r\n");
        wait_10ms(50);
       
        TripleDES(text,key,24,0);
       
        putstring("\r\n加密后密文:\r\n");
        putstring(text);
        putstring("\r\n");
        wait_10ms(50);

        TripleDES(text,key,24,1);
       
        putstring("\r\n解密后明文:\r\n");
        putstring(text);
        putstring("\r\n");
        while(1);
}

使用特权

评论回复
12
wendongwei| | 2010-12-14 17:28 | 只看该作者
以上代码,如有批评更正,可以联系wendongwei1987@163.com
或直接贴出来

使用特权

评论回复
13
wendongwei| | 2010-12-14 17:29 | 只看该作者
头文件:
//code by 南京理工大学 温冬伟
//注意:明文长度一定要为8的倍数
#ifndef _DES_H_
#define _DES_H_

void TripleDES(unsigned char* DATA,unsigned char* KEY,unsigned long readln,unsigned char mode);
//密钥:uint8 xdata KEY[24]={0xab,0x36,0x95,0xa1,0x3f,0x55,0xb0,0x12,
//                                0xac,0x01,0x95,0x22,0x3f,0x55,0xb8,0xa9,
//                                0xce,0x30,0x24,0xa1,0x3f,0x44,0x12,0x39};
//明文:uint8 xdata DATA[128]="";
//readln 为加密明文的长度
//mode为运行模式: mode=0 执行加密 mode=1 执行解密

#endif                /* _DES_H_ */

使用特权

评论回复
14
wendongwei| | 2010-12-14 17:31 | 只看该作者
需要此Keil C51的工程文件的可联系我的邮箱,欢迎批评指正

使用特权

评论回复
15
wendongwei| | 2010-12-15 11:31 | 只看该作者
可能是你使用的单片机ram较小,现在64KB的ram也比较常见,价格也不贵,这个3DES总共用3K多xdata

使用特权

评论回复
16
wendongwei| | 2010-12-15 11:33 | 只看该作者
改存在code区,也未尝不可

使用特权

评论回复
17
huangqi412| | 2010-12-15 12:13 | 只看该作者
MARK

使用特权

评论回复
18
catzl7| | 2010-12-16 13:48 | 只看该作者
关注!

使用特权

评论回复
19
gaojing0631| | 2010-12-16 14:13 | 只看该作者
我来学习

使用特权

评论回复
20
涛行九天|  楼主 | 2010-12-17 13:56 | 只看该作者
楼顶位说了,stc那个芯片ram是1280字节

使用特权

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

本版积分规则

个人签名:油站大管家--互联网+油站综合管理平台 银行押运,会员积分,稽查管理,自行车租赁,城市一卡通,电力抄表,电力巡检。。。 [u

4249

主题

8686

帖子

239

粉丝