广工物联网信息安全实验报告文档格式.docx
《广工物联网信息安全实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《广工物联网信息安全实验报告文档格式.docx(29页珍藏版)》请在冰点文库上搜索。
三、实验原理
假设所有发送及接收节点均工作在同一信号,很明显,如果发送的数据是明文的话,则每个节点均可监听到其他节点发送的数据。
若不希望信息被XX的节点所监听,可采用加密算法实现保密性。
四、实验内容
1)本实验程序可在《指导书》4.4节程序上进行修改,可节约时间。
信道编号不用更改。
2)增加一个替换密码表产生函数KeyGenerator()。
/*密码表产生函数*/
voidKeyGenerator(uint8*Key,unsignedintseed)
{
inti,j,k;
chart;
for(i=0;
i<
26;
i++)Key[i]=97+i;
//密码表初始化
for(k=0;
k<
100;
k++)
{
j=seed%26;
i=k%26;
//得到交换顺序
t=Key[j];
Key[j]=Key[i];
Key[i]=t;
//交换字母
seed=seed*(seed+7)-13;
//随机发生器
}
}
3)增加一个加密函数Encrytion()。
仅对明文中小写英文字母进行加密,其他字符不变。
/*加密函数*/
voidEncrytion(uint8*PlainText,uint8*CipherText,uint8*Key,intTextLen)
inti;
TextLen;
i++)
if(PlainText[i]>
=97&
&
PlainText[i]<
=122)
CipherText[i]=Key[PlainText[i]-97];
else
CipherText[i]=PlainText[i];
4)增加一个发送数据函数rfSendData()。
发送节点每隔1s发送一次数据
/*发送数据函数*/
voidrfSendData(void)
uint8PlainText[]={'
h'
'
e'
l'
o'
1'
5'
\r'
\n'
};
//待发送的数据
uint8Key[26];
//密码表
uint8CipherText[sizeofPlainText];
KeyGenerator(Key,12);
//12为种子,可随意更改
Encrytion(PlainText,CipherText,Key,sizeofPlainText);
//加密产生密文
while(TRUE){
basicRfSendPacket(RECV_ADDR,PlainText,sizeofPlainText);
//发送数据
halMcuWaitMs(1000);
上面的PlainText[]数组中第6、7字节改为各实验小组的组号。
KeyGenerator(Key,12);
中的12为种子值,各实验小组可随意更改。
5)修改接收数据函数rfRecvData()。
接收节点不断接收各个发送节点发送的信息,并通过串口显示。
/*接收数据函数*/
voidrfRecvData(void)
uint8pRxData[128];
//用来存放接收到的数据
intrlen;
basicRfReceiveOn();
//打开接收器
while(TRUE){
while(!
basicRfPacketIsReady());
//等待直到数据准备好
rlen=basicRfReceive(pRxData,sizeofpRxData,NULL);
//接收数据
if(rlen>
0){//接收到数据
printf(pRxData);
}
6)修改主函数main()。
将main()中的如下语句部分修改。
#ifNODE_TYPE
rfSendData();
#else
rfRecvData();
#endif
五、实验步骤
1)将工程文件main.c中的节点类型变量NODE_TYPE的值设置为1,选择Project->
RebuildAll重新编译工程;
将CC2530仿真器连接到第1个CC2530节点板,上电CC2530节点板,然后点击菜单Project->
Downloadanddebug下载程序到此节点板。
此节点以下称为发送节点。
2)将工程文件main.c中节点类型变量NODE_TYPE第值设置为0,选择Project->
RebuildAll重新编译工程。
将CC2530仿真器连接到第2个CC2530节点板,上电CC2530节点板,然后点击菜单Project->
此节点以下称为接收节点。
3)将发送节点,上电并复位。
4)将接收节点通过串口线连接到PC上,打开串口调试助手,配置串口助手波特率为19200。
上电并复位接收节点,可看到串口上打印出信道监听接收到的数据。
这时候数据应该是明文。
5)修改发送函数rfSendData()。
将basicRfSendPacket(RECV_ADDR,PlainText,sizeofPlainText);
更改为basicRfSendPacket(RECV_ADDR,CipherText,sizeofCipherText);
6)重复上面第1步,更新发送节点程序。
7)将发送节点上电并复位。
8)将串口移至接收节点。
上电并复位接收节点,注意观察串口上打印的结果。
9)自己编写一个解密函数
voidDecrytion(uint8*CipherText,uint8*PlainText,uint8*Key,intTextLen);
10)更改接收数据函数rfRecvData()。
对每次接收到的信息,先进行解密,再通过串口打印。
(注意:
解密时所用的密码表必须与加密时所用的密码表相同才能正确解密。
决定密码表的因素为seed值。
)
六、实验结果
实验的结果注意观察三种情况并对比。
1)发送数据均采用明文。
2)发送数据采用密文,但接收数据没有解密。
3)发送数据采用密文,接收数据后解密。
结果图1——自己编写的解密函数:
结果图2——改写的接收数据函数rfRecvData():
结果图3——发送数据均采用明文:
结果图4——发送数据采用密文,但接收数据没有解密:
结果图5——发送数据采用密文,接收数据后解密:
七、实验总结
经过本次实验,我掌握了常规加密算法中替换算法的原理,能够自己完成编写解密函数和相应地修改接收函数,更深刻理解了加密算法和解密算法的运作。
此外,在发送明文时要注意在发送的数据末尾加上结束符'
\0'
,否则会出现乱码情况。
实验三消息认证实验
掌握消息摘要Hash算法的原理。
掌握消息认证的方法。
假设所有发送及接收节点均工作在同一信号,每个节点均可监听到其他节点发送的数据。
如何确信消息是来源声称的身份所发送的?
同时,如何确保消息在传输过程中没有收到篡改?
解决方法是采用消息认证机制。
四、实验步骤
2)增加下列三个函数和有关定义。
#defineMD_LEN5//消息摘要长度,字节(40bit)
//简化版的消息摘要,长度为5字节
#defineBLOCK_SIZE16//Hash处理的块长度,字节(128bit)
//简化版的SHA处理数据块大小,长度为16字节
//字节循环左移函数
uint8crol(uint8c,uint8b)
{
uint8left=c<
<
b;
uint8right=c>
>
(8-b);
uint8temp=left|right;
returntemp;
}
//简化版的SHA函数
voidHashTransfer(uint8*yText,uint8*MD)
uint8A=MD[0],B=MD[1],C=MD[2],D=MD[3],E=MD[4];
uint8TA,TB,TC,TD;
20;
i++)//只做20步,用一个逻辑函数
TA=A;
TB=B;
TC=C;
TD=D;
A=crol(A,3)+(B&
C)|(~B&
D)+E+yText[i%MD_LEN];
B=TA;
C=crol(TB,6);
D=TC;
E=TD;
MD[0]=MD[0]^A;
MD[1]=MD[1]^B;
MD[2]=MD[2]^C;
MD[3]=MD[3]^D;
MD[4]=MD[4]^E;
//消息摘要函数
voidHash(uint8*Text,uint8*MD,intTextLen)
intleftLen=TextLen;
uint8yText[BLOCK_SIZE];
uint8IV[MD_LEN]={'
\x67'
'
\xEF'
\x98'
\x10'
\xC3'
memcpy(MD,IV,MD_LEN);
//初始化MD
//简化版的分块,不足一个分块大小的后面补0
(TextLen/BLOCK_SIZE+1);
if(leftLen/BLOCK_SIZE!
=0)
{
memcpy(yText,Text+i*BLOCK_SIZE,BLOCK_SIZE);
memcpy(yText,Text+i*BLOCK_SIZE,leftLen);
memset(yText+leftLen,0,BLOCK_SIZE-leftLen);
//简化版SHA转换
HashTransfer(yText,MD);
leftLen=leftLen-BLOCK_SIZE;
3)增加一个发送数据函数rfSendData()。
发送节点每隔1s发送一次数据。
发送数据的格式为:
字段名称
消息内容长度
消息内容
HMAC
长度(字节)
1
2~256
5
代码:
uint8PlainText[]={"
No.15:
GuangdongUniversityofTechnology.\n"
};
//待发送的数据
uint8MD[MD_LEN];
uint8pTxData[128];
//用来存放发送数据
Hash(PlainText,MD,sizeofPlainText);
//产生消息摘要
pTxData[0]=sizeofPlainText;
memcpy(pTxData+1,PlainText,sizeofPlainText);
memcpy(pTxData+(sizeofPlainText)+1,MD,MD_LEN);
basicRfSendPacket(RECV_ADDR,pTxData,(sizeofPlainText)+6);
4)修改接收数据函数rfRecvData()。
uint8Len;
unsignedcharFlag;
注意:
这个时候pRxData是不是字符串?
里面是否含有非ASCII字符?
为什么?
5)编写一个消息摘要认证函数MDCertify()。
其中省略号部分自己填充完成。
/*消息认证函数*/
unsignedcharMDCertify(uint8*Msg,uint8*MD,uint8Len)
uint8MDx[MD_LEN];
unsignedcharret;
//认证的结果,1:
正确,0:
不正确
Hash(Msg,MDx,Len);
……//比较MD和MDx
returnret;
6)修改接收数据函数rfRecvData(),添加如下代码。
接收节点不断接收各个发送节点发送的信息,然后认证MAC,并通过串口显示认证结果。
printf(pRxData);
Len=*pRxData;
//获得消息内容的长度
Flag=MDCertify(pRxData+1,pRxData+1+Len,Len);
//认证消息
if(Flag)
printf("
Correct!
\n"
);
else
Incorrect!
(1)上面代码应该放在函数rfRecvData()的什么地方,请自行思考。
(2)如果希望串口输出不要出现乱码(非ASCII字符),上面的代码应该如何修改?
7)上面的消息认证过程中没有使用任何密钥,请自行修改代码,在消息的前面增加一个字节作为秘密值。
这个秘密值各个小组可自行设定。
发送节点的参考代码:
uint8secret=15;
//秘密值可修改,如自己的组号
uint8Text[(sizeofPlainText)+1];
Text[0]=secret;
for(i=0;
(sizeofPlainText);
Text[i+1]=PlainText[i];
Hash(Text,MD,(sizeofPlainText)+1);
此时,接收节点先不用更改,观察消息认证是否正确。
8)接收节点收到消息之后,同样需要在消息的前面增加一个字节的秘密值,然后才进行消息认证。
修改消息摘要认证函数MDCertify()。
增加一个形参secret。
unsignedcharMDCertify(uint8*Msg,uint8*MD,uint8Len,uint8secret);
要求在消息认证函数里面,可以使用secret参数参与MD的计算。
五、实验结果
实验的结果注意观察下列情况,并对比(截图保存)。
1)发送节点发送消息,接收节点接收后显示,对应步骤4。
2)发送节点发送消息,接收节点接收后验证消息并显示,对应步骤6。
3)发送节点使用秘密值计算MD,但接收节点没有使用秘密值或者不知道秘密值,对应步骤7。
4)发送节点使用秘密值计算MD,接收节点使用相同的秘密值认证消息,对应步骤8。
对实验结果中出现乱码(非ASCII字符)的情形,要说明为什么出现?
六、实验总结
经过本次实验,我较为熟练地掌握了消息摘要Hash算法的原理和消息认证的方法,能够自己完成编写一个消息摘要认证函数,并且学会了在消息认证过程中如何进行加密。
实验四公钥加密算法实验
掌握消息RSA密钥生成和加密算法的原理。
RSA算法的关键是生成公钥私钥对。
本实验采用了一个简化的算法,通过一个给定的seed(实验组号)搜索两个不同的素数(100以内),并计算出公钥PubliceKey(e,n)和私钥PrivateKey(d,n)。
RSA加/解密公式为C=Pemodn和P=Cdmodn,其中的幂指数运算速度慢,可采用下面的公式进行转换:
C=Pemodn=((...((P*Pmodn)*Pmodn)*Pmodn)......)*Pmodn
此外,RSA算法的明文和密文均为0到n-1之间的整数,而一般传送消息的长度单位为字节(8bits),n的大小与消息长度难以匹配。
因此,本实验采用如下的特殊处理方法:
(1)令选定公钥/私钥的n值小于65536,即n值小于16bits的二进制。
(2)将消息的每个字节(8bits)作为一个明文块。
(3)每个明文块进行RSA加密后,得到的密文块为16bits,用2个字节存放。
即密文的长度为明文的2倍。
(4)接收方收到的密文,按2个字节为一个密文块进行RSA解密,解密后的结果只保留低8bits。
2)增加下列有关公钥和私钥的定义(全局定义)。
typedefstruct
unsignedinte;
unsignedintn;
}RSA_PUBLICKEY;
unsignedintd;
}RSA_PRIVATEKEY;
RSA_PUBLICKEYPu;
RSA_PRIVATEKEYPr;
}RSA_KEY;
3)增加一个RSA公钥/私钥产生函数。
RSA_KEYCreateRSAKey(unsignedintseed)
RSA_KEYRSAKey;
unsignedinti,j;
unsignedinta,b,temp;
unsignedintp=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){
i!
=p&
q==0)
q=i;
RSAKey.Pu.n=p*q;
RSAKey.Pr.n=p*q;
fi=(p-1)*(q-1);
//找出一个小于fi且与fi互素的e
for(i=3;
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);
e=%d,d=%d,n=%d\n"
RSAKey.Pu.e,RSAKey.Pr.d,RSAKey.Pu.n);
returnRSAKey;
4)增加一个RSA加密函数。
//RSA加密函数,PlainText为8bit数组,CipherText为16bits数组,Len为PlainText长度
voidRSA_Encrypt(RSA_PUBLI