一、实验内容
对各种传感器采集到的数据提取出来(2种以上类型数据),进行加密和认证操作,编写网络传输程序,在发送端将加密和认证后的数据发出,在接收端对接收到的数据验证和解密,提取出原始的传感器数据。加密算法和认证算法需要自己编写程序,不得使用网上现有的加密工具,必须有可运行的源代码,可采用DES、AES、RC4等对称加密算法对数据进行加密,采用RSA等公钥密码对数据加密密钥进行加密,采用消息认证码或数字签名机制对数据进行认证。
二、采集数据
1.设备连接:
1.1硬件设备
1.2气压
1.3光强
1.4设备连接
2.实验步骤
2.1光强采集步骤:
1)准备 LiteB(ZigBee)节点、Sensor-A 传感器、Ti 仿真器、DC 12V 电源。
2)完成 LiteB(ZigBee)节点与 Ti 仿真器、MiniUSB 线以及 Sensor-A 传感器的连接。
3)使用电源单独为节点供电,并按下节点电源开关。
4)准备工程:将本实验例程拷贝至非中文路径。
5)编译工程:
使用 IAR 软件打开工程文件,点击菜单栏的:Project ->Make 进行工程编译,提示没有错误即表示工程编译成功。
6)打开串口工具,通过 MiniUSB 数据线将电脑与 LiteB 节点进行连接,打开串口工具并配置其波特率为 38400,8 位数据位,无奇偶校验位,1 位停止位,去除十六进制显示,并打开串口。
2.2大气气压采集步骤:
1)准备 LiteB(ZigBee)节点、Sensor-A 传感器、Ti 仿真器、DC 12V 电源。
2)完成 LiteB(ZigBee)节点与 Sensor-A 传感器的连接、仿真器、DC 12V 电源和 MiniUSB 线的连接。
3)使用电源为节点供电,并按下节点电源开关。
4)准备工程:将本实验例程:AirPressure 拷贝至非中文路径。
5)编译工程:使用 IAR 软件打开工程文件,进行工程编译,提示没有错误即表示工程编译成功。
6)打开串口工具:通过 MiniUSB 数据线将电脑与 LiteB 节点进行连接,打开串口工具并配
置其波特率为 38400,8 位数据位,无奇偶校验位,1 位停止位,去除十六进制显示,并打开串口
3.主要代码及注释
3.1光强
-
名称:main()
-
功能:程序入口
-
参数:无
-
返回:无
******************************************************************************************/
void main(void)
{
float light_data = 0; //存储光照度数据变量
char tx_buff[64]; //串口发送缓冲数组
xtal_init(); //系统时钟初始化
bh1750_init(); //光照度传感器初始化
uart1_init(0x00,0x00); //串口初始化
uart1_send_string("Light Intensity Experiment:\r\n");
while(1)
{
light_data = bh1750_get_data(); //获取传感器数值
sprintf(tx_buff,"Light Intensity Value:%.2f lx\r\n",light_data); //字符串复制
uart1_send_string(tx_buff); //串口打印
memset(tx_buff,0,64); //清空串口缓存
delay_s(1); //延时 1s
}
3.2气压
-
名称:main()
-
功能:程序入口
-
参数:无
-
返回:无
******************************************************************************************/
void main(void)
{
float temperature = 0; //存储温度数据变量
long pressure = 0; //存储压力数据变量
float altitude = 0.0; //存储海拔高度变量
char tx_buff[64]; //串口发送缓冲数组
xtal_init(); //系统时钟初始化
uart1_init(0x00,0x00); //串口初始化
if(fbm320_init() == 1)
uart1_send_string("Airpressure OK!\r\n"); //传感器正常串口打印
else{
uart1_send_string("Airpressure Error!\r\n"); //传感器错误串口打印
}
while(1)
{
fbm320_data_get(&temperature,&pressure); //获取温度压力数据
altitude = (101325-pressure)*(100.0f/(101325 - 100131)); //海拔换算
//将字符串添加到串口发送缓存
sprintf(tx_buff,"Temperature:%.1f℃ Pressure:%0.1fhPa\r\n", temperature,pressure/100.0f);
uart1_send_string(tx_buff); //串口打印
sprintf(tx_buff," Altitude:%0.1f m\r\n",altitude); //将字符串添加到串口发送缓存
uart1_send_string(tx_buff); //串口打印
memset(tx_buff,0,64); //清空串口缓存
delay_s(1); //延时 1s
}
}
三、加密解密算法
1.基本原理
2.DES加密算法
DES是分组对称加密算法,将64位明文分块。经初始置换打乱,再16轮Feistel迭代:把数据拆左右32位,右半部分经扩展、与子密钥异或、S盒替换(非线性)、P盒置换(线性)后,和左半部分异或,交换左右;最后逆初始置换输出64位密文,56位有效密钥驱动变换。
3.RSA加密算法
挑选两个小素数p和q,在代码中默认p=17,q=19。计算n=pq,n是RSA算法中的模数,也是公钥和私钥的一部分。算出欧拉函数ϕ(n)=(p−1)∗(q−1)。选取一个与ϕ(n)互质的整数e作为公钥指数,代码里e=5。计算私钥指数d,使ed≡1(mod φ(n)),通过扩展欧几里得算法(代码里简单遍历)来求模逆元得到d。
4.主要代码及注释
4.1DES:
class SDES:
"""简化版DES加密算法(64位分组)"""
def init(self, key):
self.key = key
self.round_keys = [key[i:i+1]*4 for i in range(8)] # 生成轮密钥
def _feistel(self, data, round_key):
"""Feistel轮函数"""
data_int = int.from_bytes(data, 'big')
shifted = ((data_int << 1) | (data_int >> 31)) & 0xFFFFFFFF
shifted_bytes = shifted.to_bytes(4, 'big')
k_int = int.from_bytes(round_key, 'big')
return (shifted ^ k_int).to_bytes(4, 'big')
def encrypt(self, block):
"""加密64位数据块"""
L, R = block[:4], block[4:]
for i in range(8): # 8轮加密
L, R = R, bytes(a^b for a, b in zip(L, self._feistel(R, self.round_keys[i])))
return R + L # 最后一轮不交换
def decrypt(self, block):
"""解密64位数据块"""
L, R = block[:4], block[4:]
for i in range(7, -1, -1): # 逆向轮密钥
L, R = R, bytes(a^b for a, b in zip(L, self._feistel(R, self.round_keys[i])))
return R + L
@staticmethod
def pad(data):
"""(PKCS#7填充 确保数据长度是八倍)"""
pad_len = 8 - (len(data) % 8)
return data + bytes([pad_len] * pad_len)
@staticmethod
def unpad(data):
"""(去除填充)"""
return data[:-data[-1]]
4.2RSA:
class RSA:
"""简化版RSA算法(小素数)"""
def init(self, p=17, q=19):
self.n = p * q
phi = (p-1) * (q-1)
self.e = 5 # 公钥指数
self.d = self._mod_inverse(self.e, phi) # 私钥指数
def _mod_inverse(self, a, m):
"""扩展欧几里得求模逆元"""
for d in range(1, m):
if (a * d) % m == 1:
return d
return None
def encrypt(self, plaintext):
"""加密字节数据"""
return [pow(byte, self.e, self.n) for byte in plaintext]
def decrypt(self, ciphertext):
"""解密为字节数据"""
return bytes(pow(byte, self.d, self.n) for byte in ciphertext)
5.执行界面
发送端:
接收端:
四、消息认证
1.认证方式
对数据进行 PKCS#7 填充,确保数据长度是 8 的倍数。初始化 MAC 值为全 0 字节。按 8 字节分块遍历数据,将每块与当前 MAC 值异或。使用 SDES 算法对最终异或结果加密得到 MAC 值。发送端生成对称密钥加密数据后,调用MAC.compute计算加密数据的 MAC 值,并将加密后的对称密钥、MAC 值和加密数据一起发送。接收端接收数据后,解密对称密钥,使用相同密钥和算法重新计算MAC值,并与接收到的MAC值比较。
2. 主要代码实现
class MAC:
"""(基于DES的MAC认证算法)"""
@staticmethod
def compute(key, data):
"""(计算消息认证码)"""
data = SDES.pad(data)
mac = b'\x00' * 8
sdes = SDES(key)
for i in range(0, len(data), 8):
block = data[i:i+8]
mac = bytes(a^b for a, b in zip(mac, block))
return sdes.encrypt(mac)
五、网络传输
本次实验的网络传输主要通过 Python 的socket库实现,结合自定义的NetworkUtils类进行数据的发送和接收在发送端。
在发送端,主要通过以下步骤完成网络传输:
1.创建套接字:使用socket.socket方法创建一个 TCP 套接字对象。
2.连接服务器:使用connect方法连接到指定的服务器 IP 地址和端口。
3.发送数据:使用NetworkUtils.send_data方法发送加密后的对称密钥、MAC 值和加密数据。
其中,NetworkUtils.send_data方法会在数据前添加长度头,确保接收端能够正确接收完整的数据。
在接收端,主要通过以下步骤完成网络传输:
1.创建套接字并绑定监听:使用socket.socket方法创建一个 TCP 套接字对象,并绑定到指定的端口进行监听。
2.接受客户端连接:使用accept方法接受客户端的连接请求,并为每个客户端创建一个新的线程进行处理。
3.接收数据:使用NetworkUtils.recv_data方法接收加密后的对称密钥、MAC值和加密数据。
其中,NetworkUtils.recv_data方法会先接收长度头,然后根据长度头接收完整的数据。
六、总结与收获
本次实验围绕传感器数据安全传输,借助crypto_utils.py实现核心加密认证。DES类完成64位数据块加解密及填充处理,RSA实现简化密钥加密。MAC类计算消息认证码保证数据完整,NetworkUtils负责网络通信数据收发。结合send.py与receive.py的GUI界面,完成数据从发送端加密传输到接收端解密验证保存的全流程,让我掌握加密算法与网络编程实践,提升项目开发能力。感谢老师的指点与教育,让我对网络安全有更深入的了解。