信息安全技术 实验四

 

 

 

《信息安全技术》实验报告

 

 

实验四 简单RSA加密算法实验

 

1、实验目的

  掌握消息RSA密钥生成和加密算法的原理。

 

2、实验环境

  硬件:ZXBee CC2530 节点板 2 块、USB  接口的 CC2530 仿真器,PC 机;

  软件:Windows 7/Windows XP、IAR 集成开发环境、串口监控程序。

 

3、实验原理

       RSA算法的关键是生成公钥私钥对。本实验采用了一个简化的算法,通过一个给定的seed(实验组号)搜索两个不同的素数(100以内),并计算出公钥PubliceKey(e,n)和私钥PrivateKey(d,n)。

       RSA加/解密公式为C=Pe mod n和P=Cd mod n,其中的幂指数运算速度慢,可采用下面的公式进行转换:

C=Pe mod n=((...((P*P mod n)*P mod n)*P mod n)... ...)*P mod n

       此外,RSA算法的明文和密文均为0到n-1之间的整数,而一般传送消息的长度单位为字节(8 bits),n的大小与消息长度难以匹配。因此,本实验采用如下的特殊处理方法:

       (1)令选定公钥/私钥的n值小于65536,即n值小于16bits的二进制。

       (2)将消息的每个字节(8bits)作为一个明文块。

       (3)每个明文块进行RSA加密后,得到的密文块为16bits,用2个字节存放。即密文的长度为明文的2倍。

       (4)接收方收到的密文,按2个字节为一个密文块进行RSA解密,解密后的结果只保留低8bits。

 

4、实验步骤

       1)本实验程序可在《指导书》4.4节程序上进行修改,可节约时间。信道编号不用更改。

       2)增加下列有关公钥和私钥的定义(全局定义)。

typedef struct

{

       unsigned int e;

       unsigned int n;

}RSA_PUBLICKEY;

 

typedef struct

{

       unsigned int d;

       unsigned int n;

}RSA_PRIVATEKEY;

 

typedef struct

{

       RSA_PUBLICKEY Pu;

       RSA_PRIVATEKEY Pr;

}RSA_KEY;

       3)增加一个RSA公钥/私钥产生函数。

RSA_KEY CreateRSAKey(unsigned int seed)

{

       RSA_KEY RSAKey;

       unsigned int i,j;

       unsigned int a,b,temp;

       unsigned int p=0,q=0,fi=0;

 

       i=(seed*71-17)%29+11;             //产生第一个素数搜索的初始值,只搜索11~39

 

       //搜索素数p

       while(p==0){

              for(j=2;j<=i/2-1;j++)

                     if(i%j==0) break;

              if(j>(i/2-1) && p==0)

                     p=i;

              i=(i-10)%29+11;

       }

 

       i=(seed*171-51)%29+11;     //产生第二个素数搜索的初始值,只搜索11~39

 

       //搜索素数q

       while(q==0){

              for(j=2;j<=i/2-1;j++)

                     if(i%j==0) break;

              if(j>(i/2-1) && i!=p && q==0)

                     q=i;

              i=(i-10)%29+11;

       }

 

       RSAKey.Pu.n=p*q;

       RSAKey.Pr.n=p*q;

       fi=(p-1)*(q-1);

 

       //找出一个小于fi且与fi互素的e

       for(i=3;i<fi;i++){

              a=fi;

              b=i;

              while(b!=0) {         //使用辗转相除法,判断是否互素

                     temp=b;

                     b=a%b;

                     a=temp;

              }

              if(a==1){

                     RSAKey.Pu.e=i;

                     break;

              }

       }

 

    //计算d

       j=1;

       while((fi*j+1)%RSAKey.Pu.e!=0) j++;

       RSAKey.Pr.d=(fi*j+1)/RSAKey.Pu.e;

 

       //printf("p=%d,q=%d,", p, q);

       //printf("e=%d,d=%d,n=%d\n", RSAKey.Pu.e, RSAKey.Pr.d, RSAKey.Pu.n);

       return RSAKey;

}

 

 

 

       4)增加一个RSA加密函数。

//RSA加密函数,PlainText为8bit数组,CipherText为16bits数组,Len为PlainText长度

void RSA_Encrypt( RSA_PUBLICKEY PuKey, uint8 *PlainText, uint16 *CipherText, int Len )

{

       int i=0, j=0;

       uint16 temInt = 0;

 

       for( i=0; i<Len; i++ ){

              temInt = PlainText[i];

 

              for( j=1; j<PuKey.e; j++ )

                     temInt = ( temInt * PlainText[i] ) % PuKey.n;

 

              CipherText[i] = temInt;

       }

}

 

       5)增加一个发送数据函数rfSendData()。发送节点每隔 1s发送一次数据。发送数据的格式为:

字段名称

接收方编号

明文长度

密文

长度(字节)

1

1

2~256

代码:

/*发送数据函数 */

void rfSendData(void)

{

       uint8 PlainText[]={'G','D','U','T', '2', '5'};        //明文,请将'2', '5'更改为各个小组的组号

       uint16 CipherText[sizeof PlainText];        //密文

       uint8 pTxData[128];      //存放发送数据

       RSA_KEY Key=CreateRSAKey(25);      //请将25更改为各个小组的组号

 

RSA_Encrypt( Key.Pu, PlainText, CipherText, sizeof PlainText );  //产生密文

pTxData[0]=25;     //请将25更改为各个小组的组号

pTxData[1]=sizeof PlainText

memcpy(pTxData+2, CipherText, sizeof CipherText);

 

       while(TRUE){

              basicRfSendPacket(RECV_ADDR, pTxData, (sizeof CipherText)+2);     //发送数据

              halMcuWaitMs(1000);

       }

}

       注意,上面代码有三个地方需要改为各实验小组的组号。

 

       6)修改接收数据函数rfRecvData()。接收节点不断接收各个发送节点发送的信息,先判断数据的第一个字节是不是本站点,如果是再进行解密。通过串口显示结果。

/*  接收数据函数  */

void rfRecvData(void)

{

       uint8 pRxData[128];      //用来存放接收到的数据

       int i,rlen;

       basicRfReceiveOn();      //打开接收器

uint8 PlainText[64];

 

       while (TRUE) {

              while(!basicRfPacketIsReady());    //等待直到数据准备好

              rlen = basicRfReceive(pRxData, sizeof pRxData, NULL);    //接收数据

              if(rlen > 0 && pRxData[0]==25) {  //接收到数据且为发送给本站点的。请修改本小组的组号

                     for(i=0;i<pRxData[1];i++)

                            printf("0x%02x%02x ", pRxData[i*2+3], pRxData[i*2+2]);

                     printf("\n");

              }

       }

}

       注意,这个时候串口输出的应该是密文,且为16进制显示。

 

       7)编写一个RSA解密函数RSA_Decrypt ( )。其中省略号部分自己填充完成。

/*  RSA解密函数  */

void RSA_Decrypt( RSA_PRIVATEKEY PrKey, uint16 *CipherText, uint8 *PlainText, int Len )

{

       int i=0, j=0;

       uint16 temInt = 0;

 

       for( i=0; i<Len; i++ )

       {

              ……

       }

}

 

       8)修改接收数据函数rfRecvData()红色部分,对接收到的密文进行解密,并通过串口显示结果。

              if(rlen > 0 && pRxData[0]==25) {    //接收到数据,且为发送给本站点的

                     RSA_Decrypt(Key.Pr, pRxData+2, PlainText, pRxData[1]);

                     for(i=0;i<pRxData[1];i++)

                            printf("%c", PlainText[i]);

                     printf("\n");

       注意,解密的私钥Key.Pr从哪里来?

 

5、实验报告要求

       实验的结果注意观察下列情况,并对比(截图保存)。

1) 发送节点发送密文,接收节点接收后显示密文,对应步骤6。

 

2) 发送节点发送密文,接收节点接收后解密并显示明文,对应步骤8。

 

       请回答以下问题:

1) 为什么密文的长度与明文的长度不一致?

因为进行模指运算的原因,密文长度应与密钥n的长度较为相近,而不是与明文的长度有关。

2) 请写出本小组所用的公钥和私钥的值,包括e,d,n的值。并针对字符'G',列写加密公式和解密公式,手工验算密文是否与步骤6的串口显示结果相同。(字符'G'的ASCII码为71)

e=7,d=103,n=407

C=P^e mod n = 71^7mod407=366(在16进制下为16e,显示正确)

P=C^d mod n =366^103 mod407=71

 

3) 密钥分配问题。本实验例程里面,发送方和接收方均已知公钥和私钥。然而在实际应用中,发送方和接收方针对公钥和私钥应当如何应用才能保证信息的机密性?(提示,发送方是不可能产生公钥或者私钥的,应该在通信前提前拥有接收方的公钥。)

一个公开的叫公钥,一个保密只有自己知道叫私钥.如果有一份信息,用我的公钥加密了,那么只能用我的私钥解密,也就是说很多人都可以给我发加密的信息,但只有我能解的开,所以实现了数据的机密性

4) 实际应用中为什么不将RSA算法直接用于消息加密?

RSA 算法中大数的模幂运算比较费时,这一直是制 约 RSA 发展的瓶颈。

出 于安全性考虑,目前 RSA 密码系统的模数为 1024 ~ 2048 bit, 如此庞大的模数,其运算效率必然受到影响。

 

上一篇:使用python和MySql进行存储加密


下一篇:记一个Java多线程相关的面试题