10、BLE密钥管理漏洞:LTK存储风险、CSRK泄露、IRK滥用、Android KeyStore保护

聊到BLE安全,很多人第一反应是配对过程。嗯,配对确实重要。但我个人觉得,真正决定安全下限的,其实是配对之后的密钥管理。

你想想看,就算配对过程做得再完美,如果密钥存得跟明文似的,那跟没锁门有什么区别?我在项目中就见过不少这样的案例——设备配对成功了,加密也建立了,结果攻击者从手机文件系统里直接把LTK捞了出来。说白了,密钥管理才是那个“木桶最短的板”。

LTK(长期密钥)存储风险

LTK是BLE连接加密的核心。配对完成后,双方会协商出一个LTK,后续重连时直接用这个密钥恢复加密会话,不用再走一遍配对流程。

但问题来了——LTK存在哪儿?

我见过最夸张的做法,是把LTK直接写在SharedPreferences里。嗯,你没看错,明文。攻击者只要拿到root权限,或者通过备份漏洞,就能把LTK拖走。有了LTK,他就能冒充合法设备,解密所有通信内容。

⚠️ 注意: LTK泄露意味着加密会话完全失效。攻击者不需要破解算法,只需要偷钥匙。

正确的做法是什么?Android提供了KeyStore系统。但很多开发者嫌麻烦,或者觉得“我的应用没那么重要”,就绕过去了。我曾经在一个IoT项目里接手过这样的烂摊子——前任开发者把LTK存成了文件,权限还是全局可读的。修复起来真是头大。

CSRK(连接签名解析密钥)泄露

CSRK用于数据签名。在BLE中,有些场景不需要加密,但需要保证数据完整性。这时候就用CSRK来签名数据。

CSRK泄露的后果是什么?攻击者可以伪造签名数据。比如一个智能门锁,收到“开锁”指令,签名验证通过就执行。如果CSRK泄露了,攻击者就能伪造任意指令。

我记得有个真实案例——某品牌智能灯泡,CSRK硬编码在固件里,而且所有设备共用同一个密钥。攻击者反编译App就拿到了CSRK,然后可以控制整个城市里所有该品牌的灯泡。嗯,这已经不是安全问题了,这是设计缺陷。

💡 建议: CSRK应该每个设备独立生成,并且存储在安全硬件中。不要硬编码,不要共用。

IRK(身份解析密钥)滥用

IRK用于解析随机地址。BLE设备为了保护隐私,会使用随机地址而不是固定MAC地址。但接收方需要用IRK来解析这个随机地址,确认是谁在跟自己通信。

IRK滥用的情况比较隐蔽。有些开发者把IRK当成万能密钥,用来加密数据、签名消息。这其实很危险——IRK的设计用途只有一个:地址解析。用在其他地方,不仅效率低,还可能引入意想不到的漏洞。

我遇到过一款可穿戴设备,开发者把IRK直接当成了LTK用。结果呢?地址解析和加密通信共用同一个密钥。攻击者只要捕获一次地址解析过程,就能推导出加密密钥。这设计,怎么说呢,一箭双雕——一个漏洞废了两个安全机制。

密钥类型 设计用途 滥用后果
LTK 加密通信 通信被解密
CSRK 数据签名 签名被伪造
IRK 地址解析 隐私泄露、密钥推导

Android KeyStore保护

Android KeyStore是官方推荐的密钥存储方案。它利用硬件安全模块(如TEE或StrongBox)来保护密钥材料。说白了,密钥一旦存入KeyStore,应用层代码根本拿不到明文。

使用KeyStore有几个要点:

  • 密钥生成:在KeyStore内生成密钥,而不是在外面生成再导入。这样密钥材料永远不会离开安全硬件。
  • 用途限制:创建密钥时指定用途,比如只用于加密或只用于签名。防止密钥被滥用。
  • 用户认证绑定:可以设置密钥在用户认证后才可用。比如需要指纹或锁屏密码。
// 在KeyStore中生成AES密钥的示例
KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(
        "ble_ltk_key",
        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
        .setKeySize(128)
        .setUserAuthenticationRequired(true) // 需要用户认证
        .build();

KeyGenerator keyGenerator = KeyGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(spec);
keyGenerator.generateKey();
🔑 核心要点: 密钥管理不是“存起来”那么简单。要用对地方、用对方式、用对存储介质。KeyStore不是万能药,但不用KeyStore几乎是毒药。

知识体系总览

下面这张图梳理了BLE密钥管理的核心风险与防护思路。我习惯在做安全设计前先画这么一张图,把攻击面理清楚。

BLE密钥管理风险与防护 BLE密钥类型 LTK 长期密钥 CSRK 签名密钥 IRK 身份密钥 ⬇ 常见风险 ⬇ 明文存储 SharedPreferences/文件 硬编码/共用 固件中写死 用途混淆 IRK当LTK用 ⬇ 防护方案 ⬇ Android KeyStore + 硬件安全模块(TEE/StrongBox) 密钥生成在安全硬件内 · 用途限制 · 用户认证绑定

这张图把密钥类型、常见风险、防护方案串在了一起。你可以看到,三种密钥各有各的用途,也各有各的死法。但最终的防护方案是统一的——用Android KeyStore,配合硬件安全模块。

我个人习惯在项目初期就把密钥管理方案定下来。不要等到上线了再补,那时候改起来成本太高了。我曾经在一个项目里,因为前期没规划好密钥存储,后期不得不给所有已售设备做OTA升级。那滋味,嗯,不想再体验第二次。

📌 避坑指南: 我曾经接手过一个BLE项目,LTK存在外部存储里,权限还是MODE_WORLD_READABLE。修复方案是把所有密钥迁移到KeyStore,但已经泄露的密钥无法召回。所以,一开始就用对方案,比事后补救重要得多。

公众号:蓝海资料掘金营,微信deep3321