低功耗蓝牙BLE之AES-128加密算法

版权声明:

博主:枫之星雨

声明:本文为博主原创文章,转载请注明原文出处。

博文地址:http://blog.csdn.net/zzfenglin

邮箱:[email protected]

QQ号:454086991(申请加好友时请备注”技术交流“)

加密

在连接时,可以对净荷中的数据进行加密,确保数据的机密性,从而抵御攻击者。机密性是指第三方“攻击者”由于没有加密链路的共享密钥,因此无法拦截、破译或读取消息的原始内容。

加密数据包含一个消息完整性校验值,表明该数据包已经过认证。为了验明发送方的有效身份,认证使用共享密钥为已加密的数据计算签名,可防止第三方篡改数据包中的任何内容。通过认证,消息的接收方能够确信收到的数据包来自一个可信设备。

加密数据包还包含一个数据包计数器,用来防止重放攻击。重放攻击是这样一种攻击方式:攻击者截取一个既有的消息,随后再次发送该消息以期望收到响应。试想,假如没有重放攻击保护,攻击者有可能扫描到某个设备的大量数据包,然后再次发送这些数据包,其结果可能不堪设想。显然,防止重放攻击是一件非常重要的事情。

AES-128加密算法简介

低功耗蓝牙中的所有加密和认证都基于同一个加密引擎,称为高级加密系统(AES)。AES最初源自美国的一项政府计划,试图寻找未来可用的加密引擎。一直以来,AES被用于许多有线和无线标准,迄今为止安全研究人员还没有找到其算法的弱点。

AES可以有多种形式,取决于在给定的时间内能够处理的数据块以及密钥的大小。低功耗蓝牙使用128位的密钥和128位的数据块。也就是说,所有密钥的长度均为128位,每次加密生成的密文长度为16个字节。

AES加密块非常简单,它包含两个输入和一个输出。两个输入分别为128位的密钥值和128位的纯文本数据块,输出则为128位的加密数据块。密钥和纯文本在使用上有一些不同;纯文本可以直接为加密块使用,但密钥必须经过处理后才能使用。可见,更有效的方法是只设立一个密钥,用于不同的纯文本块以进行快速加密,而非使用不同的密钥为每个块加密。

在低功耗蓝牙里,AES加密引擎被用于下列四个基本功能:

1.加密净荷数据

2.计算消息完整性校验值

3.数据签名

4.生成私有地址

数据签名在安全管理器中定义,生成私有地址在通用访问规范中定义。

注意,本文主要是为了讲解AES-128算法在BLE设备和安卓手机之间通信时使用的过程,所以并没有去深入研究讲解AES算法。如果有对该算法感兴趣的,可以去网上搜索相关资料深入了解一下。

AES-128加解密方法源码

我们的实验案例是BLE设备端(从机)发送加密的数据给安卓手机(主机)并解密出原始有效数据,以及安卓手机(主机)发送加密的数据给BLE设备端(从机)并解密出原始有效数据。通信过程不便于演示,所以我们换种方式来呈现我们的实现源码:同样的原始有效数据,同样的加解密Key,分别在设备端和Java测试环境中对原始有效数据进行加密然后解密,通过看设备端和Java测试环境中加密之后的数据是否一致以及解密之后的数据是否一致,来判断我们的数据加密传输能否成功,如果加密之后数据一致并且解密之后的数据也一致,那加密传输就可以成功实现。

1.BLE设备端测试程序。

(1)测试环境:

开发环境:IAR8.20版本,Windows XP系统

测试设备:CC2541/CC2540开发板

测试例程:1.4.0协议栈中“simpleBLEPeripheral”例程

(2)实现源码:

/****************************************************************
* 名    称: Aes128EncryptAndDecrypTest()
*
* 功    能: 测试AES-128 加解密,注意我们加密时需要key,
*		      加密后的数据用于通信;同样解密的时候也
*		      需要用同一个key进行解密,这样,如果对方
*		      没有key 就无法解密出原始数据,进而保护了
*		      用户数据不被截取。
*
* 入口参数: 无
* 出口参数: 无
****************************************************************/
static void Aes128EncryptAndDecrypTest(void)
{
	int i = 0;
	// 加密秘钥 16个字节也就是128 bit
	uint8 key[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};

	// 需要加密的数据(保证16个字节,不够的自己填充)
	uint8 source_buf[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};

	// 加密后数据存放区
	uint8 encrypted_buf[16];

	// 解密后数据存放区
	uint8 deccrypted_buf[16];

	// 开始加密,加密后的数据存放到encrypted_buf
	LL_Encrypt( key, source_buf, encrypted_buf );

	// 开始解密,将解密后的数据存到deccrypted_buf
	LL_EXT_Decrypt( key, encrypted_buf, deccrypted_buf );

	//打印原始数据
	tx_printf("source:");
	for(i = 0;i < 16;i++)
	{
		txprintf("0x%02x ",source_buf[i]);
	}
	tx_printf("");
	//打印加密后的数据
	tx_printf("encrypte:");
	for(i = 0;i < 16;i++)
	{
		txprintf("0x%02x ",encrypted_buf[i]);
	}
	tx_printf("");
	//打印解密后的数据
	tx_printf("deccrypte:");
	for(i = 0;i < 16;i++)
	{
		txprintf("0x%02x ",deccrypted_buf[i]);
	}
	tx_printf("");

}

上述测试方法放到“simpleBLEPeripheral.c”文件中,在初始化函数“SimpleBLEPeripheral_Init”里面最后的地方调用上述测试方法“Aes128EncryptAndDecrypTest();”就可以了。

通过上述测试方法,我们看到设备端加密用的是“LL_Encrypt”方法,解密用的是“LL_EXT_Decrypt”方法,这两个方法的声明在“Ll.h”头文件中,这个头文件被“hci.h”头文件引用,所以如果提示找不到这两个方法的时候,我们引用“hci.h”头文件即可。因为上面的注释比较详细,所以我们就不再赘述了。

(3)测试结果:

2.安卓手机端测试程序

(1)测试环境:

开发环境:Eclipse开发工具,Windows XP系统。

测试设备:Eclipse开发工具编译java工程可以在控制台输出结果。

(2)测试源码:

package com.zzfenglin.aes;

import java.util.Formatter;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class AesEntryDetry {
	// 加密秘钥 ,16个字节也就是128 bit
	private static final byte[] AES_KEY = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
			12, 13, 14, 15, 16 };

	// 需要加密的数据(保证16个字节,不够的自己填充)
	private static final byte[] SOURCE_BUF = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
			11, 12, 13, 14, 15, 16 };

	// Java测试工程入口方法,在这个方法中调用加解密方法并打印结果
	public static void main(String[] args) throws Exception {
		// 需要加密的原始数据转化成字符串并打印到控制台
		String strSource = BytetohexString(SOURCE_BUF);
		System.out.println("source:\n" + strSource);

		// 调用加密方法,对数据进行加密,加密后的数据存放到encryBuf字节数组中
		byte[] encryBuf = encrypt(AES_KEY, SOURCE_BUF);
		// 将加密后的字节数组数据转成字符串并打印到控制台
		String strEncry = BytetohexString(encryBuf).toLowerCase();
		System.out.println("encrypte:\n" + strEncry);

		// 调用解密方法,对数据进行解密,解密后的数据存放到decryBuf字节数组中
		byte[] decryBuf = decrypt(AES_KEY, encryBuf);
		// 将解密后的字节数组数据转成字符串并打印到控制台
		String strDecry = BytetohexString(decryBuf);
		System.out.println("decrypte:\n" + strDecry);

	}

	// 加密方法
	private static byte[] encrypt(byte[] key, byte[] clear) throws Exception {
		SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
		Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
		byte[] encrypted = cipher.doFinal(clear);
		return encrypted;
	}

	// 解密方法
	private static byte[] decrypt(byte[] key, byte[] encrypted)
			throws Exception {
		SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
		Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
		cipher.init(Cipher.DECRYPT_MODE, skeySpec);
		byte[] decrypted = cipher.doFinal(encrypted);
		return decrypted;
	}

	// 字节数组按照一定格式转换拼装成字符串用于打印显示
	private static String BytetohexString(byte[] b) {
		int len = b.length;
		StringBuilder sb = new StringBuilder(b.length * (2 + 1));
		Formatter formatter = new Formatter(sb);

		for (int i = 0; i < len; i++) {
			if (i < len - 1)
				formatter.format("0x%02X:", b[i]);
			else
				formatter.format("0x%02X", b[i]);

		}
		formatter.close();

		return sb.toString();
	}
}

Java测试实例工程的CSDN下载链接如下:

http://download.csdn.net/detail/zzfenglin/9555823

(3)测试结果:

3.通过BLE设备端测试程序和安卓手机端测试程序结果的比较,我们发现原始有效数据和加密的Key都一样的情况下,二者加密的数据和解密后的数据也都一致,这就保证了设备端把加密数据发给安卓手机端之后,安卓手机端可以成功解密,并且安卓手机端发送加密数据给设备端之后,设备端也可以成功解密。上述的安卓手机端测试代码是在Java工程中,后期要在安卓工程中使用的话,只需要将相关的方法拷贝出去,或者将上述测试的Java文件改写成安卓工程中的一个工具类即可。

Java端参考资料

AES参考代码如下:

算法/模式/填充			16字节加密后数据长度			不满16字节加密后长度
AES/CBC/NoPadding				16						不支持
AES/CBC/PKCS5Padding				32						16
AES/CBC/ISO10126Padding			32						16
AES/CFB/NoPadding				16						原始数据长度
AES/CFB/PKCS5Padding				32						16
AES/CFB/ISO10126Padding			32						16
AES/ECB/NoPadding				16						不支持
AES/ECB/PKCS5Padding				32						16
AES/ECB/ISO10126Padding			32						16
AES/OFB/NoPadding				16						原始数据长度
AES/OFB/PKCS5Padding				32						16
AES/OFB/ISO10126Padding			32						16
AES/PCBC/NoPadding				16						不支持
AES/PCBC/PKCS5Padding			32						16
AES/PCBC/ISO10126Padding			32						16

可以看到,在原始数据长度为16的整数倍时,假如原始数据长度等于16*n,则使用NoPadding时加密后数据长度等于16*n,其它情况下加密数据长度等于16*(n+1)。在不足16的整数倍的情况下,假如原始数据长度等于16*n+m[其中m小于16],除了NoPadding填充之外的任何方式,加密数据长度都等于16*(n+1);NoPadding填充情况下,CBC、ECB和PCBC三种模式是不支持的,CFB、OFB两种模式下则加密数据长度等于原始数据长度。

时间: 2024-10-07 11:12:17

低功耗蓝牙BLE之AES-128加密算法的相关文章

使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发具体解释

转载请注明来源: http://blog.csdn.net/kjunchen/article/details/50909410 使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发具体解释 演示样例源代码: https://github.com/junkchen/BleLib/tree/master/sample Android ble4.0开发基础篇:http://blog.csdn.net/kjunchen/article/details/50339549 BleLib是An

低功耗蓝牙BLE之连接事件、连接参数和更新方法

转自:http://blog.csdn.net/zzfenglin/article/details/51304084 连接事件 在一个连接当中,主设备会在每个连接事件里向从设备发送数据包.一个连接事件是指主设备和从设备之间相互发送数据包的过程.连接事件的进行始终位于一个频率,每个数据包会在上个数据包发完之后等待 150μs 再发送. 连接间隔决定了主设备与从设备的交互间隔:它是指两个连续的连接事件开始处的时间距离,可以是7.5ms ~ 4s内的任意值,但必须为 1.25ms 的整数倍.要确定从设

深入浅出低功耗蓝牙(BLE)协议栈

BLE协议栈为什么要分层?怎么理解BLE"连接"?如果BLE协议只有ATT层没有GATT层会发生什么? 协议栈框架 一般而言,我们把某个协议的实现代码称为协议栈(protocol stack),BLE协议栈就是实现低功耗蓝牙协议的代码,理解和掌握BLE协议是实现BLE协议栈的前提.在深入BLE协议栈各个组成部分之前,我们先看一下BLE协议栈整体架构. 如上图所述,要实现一个BLE应用,首先需要一个支持BLE射频的芯片,然后还需要提供一个与此芯片配套的BLE协议栈,最后在协议栈上开发自己

Android 低功耗蓝牙BLE 开发注意事项

基本概念和问题 1.蓝牙设计范式? 当手机通过扫描低功耗蓝牙设备并连接上后,手机与蓝牙设备构成了客户端-服务端架构.手机通过连接蓝牙设备,可以读取蓝牙设备上的信息.手机就是客户端,蓝牙设备是服务端. 手机做为客户端可以连接多个蓝牙设备,所以手机又可以叫中心设备(Central),蓝牙设备叫外围设备(Peripheral). 还有另外一个称谓:手机叫主设备(Master),蓝牙设备叫从设备(Slave). Android4.3 开始支持低功耗蓝牙,此版本只支持单模式:同时只能工作在中心设备模式或者

Android低功耗蓝牙(蓝牙4.0)——BLE开发(上)

段时间,公司项目用到了手机APP和蓝牙设备的通讯开发,这里也正好对低功耗蓝牙(蓝牙4.0及以后标准)的开发,做一个总结. 蓝牙技术联盟在2010年6月30号公布了蓝牙4.0标准,4.0标准在蓝牙3.0+HS标准的基础上增加了对低功耗蓝牙(BLE)的支持.相比原有的普通蓝牙和高速蓝牙,BLE最大的特点就是低功耗,低延时,快速的搜索和连接速度,但数据传输速度相比传统蓝牙低.接下去将从BLE的概念以及代码两个方面介绍Android下的BLE. 先来说说基本概念: 1.BLE相关概念 1.1 GATT.

Android-低功耗蓝牙(BLE)-客户端(主机/中心设备)和服务端(从机/外围设备)

一.Android 低功耗蓝牙(BLE)的API简介 从Android 4.3(API 18)才支持低功耗蓝牙(Bluetooth Low Energy, BLE)的核心功能, BLE蓝牙协议是GATT协议, BLE相关类不多, 全都位于android.bluetooth包和android.bluetooth.le包的几个类: android.bluetooth. .BluetoothGattService 包含多个Characteristic(属性特征值), 含有唯一的UUID作为标识 .Bl

低功耗蓝牙(BLE)在 Android APP 中的应用

低功耗蓝牙(BLE)在 Android APP 中的应用 前言 最近公司接了一个新项目,用户可以把自己的乐器跟Phone或Pad连接起来,当弹奏乐器的时候,会把演奏情况同步反馈到设备上,方便用户练习,有点类似于之前玩过的一款叫[ 吉他英雄 ]的游戏.不过这次不用插线,直接蓝牙无线连接就可以了. 那么问题来了,因为弹奏的时候数据传输一直在进行,但是如果要一直打开蓝牙的话是很费电的,也许没几首曲子下来设备的电量就耗掉了不少,这当然是无法接受的.那有没有什么好的解决方案呢? 运气真好,Android在

【原创】Android 5.0 BLE低功耗蓝牙从设备应用

如果各位觉得有用,转载+个出处. 现如今安卓的低功耗蓝牙应用十分普遍了,智能手环.手表遍地都是,基本都是利用BLE通信来交互数据.BLE基本在安卓.IOS两大终端设备上都有很好支持,所以有很好发展前景. 现市面上各种手环.手表的智能设备中基本都充当"从设备"这样的角色,基本由智能设备完成蓝牙广播,由手机进行连接,然后交互数据. 根据上述方式的应用在安卓4.3.IOS 7.0的版本上就得到了支持,应用也比较广泛,园里应该有很多相关实现,大家可以自己找找,如果不愿意找,抽空再写一篇. 今天

Android BLE与终端通信(五)——Google API BLE4.0低功耗蓝牙文档解读之案例初探

Android BLE与终端通信(五)--Google API BLE4.0低功耗蓝牙文档解读之案例初探 算下来很久没有写BLE的博文了,上家的技术都快忘记了,所以赶紧读了一遍Google的API顺便写下这篇博客心得 Google API:http://developer.android.com/guide/topics/connectivity/bluetooth-le.html#terms 其实大家要学习Android的技术,Google的API就是最详细的指导书了,而且通俗易懂,就算看不懂