尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Tasmota 中的 Keeloq 加密算法库:从 NLF 位密码原理到 Jarolift 卷帘实战

Tasmota 中的 Keeloq 加密算法库:从 NLF 位密码原理到 Jarolift 卷帘实战 Tasmota 中的 Keeloq 加密算法库从 NLF 位密码原理到 Jarolift 卷帘实战【免费下载链接】TasmotaAlternative firmware for ESP8266 and ESP32 based devices with easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX. Full documentation at项目地址: https://gitcode.com/GitHub_Trending/ta/Tasmota导读Keeloq 是 Microchip 广泛用于遥控钥匙RKERemote Keyless Entry与无线门禁系统的分组密码算法。本文以 Tasmota 仓库中的 KeeloqLib 为核心完整讲解该库在 Arduino/ESP8266/ESP32 平台上的封装接口、加密/解密实现细节并结合仓库内xdrv_36_keeloq.ino展示它如何被真实应用于 Jarolift 卷帘rolladen遥控信号的加解密与 433 MHz 射频发射帮助读者既掌握 Keeloq 算法本身的原理也能在自有项目中复用这套实现。一、Keeloq 算法与 KeeloqLib 的定位1.1 算法背景与许可注意事项Keeloq 是一种 32 位分组密码采用 64 位密钥因实现轻量、功耗低而被大量用于无线门锁、车库门与卷帘遥控器。仓库 READMElib/lib_rf/KeeloqLib/README.md给出了三点关键说明该实现已用 Microchip 官方 SDK 的多组测试用例做过比对验证结果一致Keeloq 算法本身没有专利但 Microchip 对“将 Keeloq 应用于安全免钥匙进入secure keyless entry”这一应用场景持有专利因此在非 Microchip 处理器上用它做商业化的免钥匙进入产品并不明智个人实验学习没有问题。一句话总结算法可自由研究商用要谨慎买 Microchip 的处理器。这是在使用该库前必须先明确的边界。1.2 库的组成与适用平台KeeloqLib 位于 lib/lib_rf/KeeloqLib目录结构如下src/KeeloqLib.h类声明与公共接口src/KeeloqLib.cpp528 轮加密/解密核心实现tests/KeeloqLibTest/KeeloqLibTest.inoArduino 测试示例keywords.txtArduino IDE 语法高亮映射library.propertiesArduino 库元数据。根据 library.properties该库版本为 1.1支持架构为esp8266,esp32开发与测试环境为 Arduino IDE同时它也能在普通 AVR Arduino 上编译运行头文件按 Arduino 版本自动选择Arduino.h或WProgram.h。二、核心 API64 位密钥、32 位数据加解密2.1 接口定义src/KeeloqLib.h 中定义了唯一一个类Keeloq接口非常精简class Keeloq { public: Keeloq( const unsigned long keyHigh, const unsigned long keyLow ); unsigned long encrypt( const unsigned long data ); unsigned long decrypt( const unsigned long data ); private: unsigned long _keyHigh; unsigned long _keyLow; };参数说明参数/方法类型含义keyHighunsigned long32 位64 位密钥的高 32 位keyLowunsigned long32 位64 位密钥的低 32 位encrypt(data)入参/返回值均为unsigned long对 32 位明文加密返回 32 位密文decrypt(data)入参/返回值均为unsigned long对 32 位密文解密还原 32 位明文构造时两个 32 位变量拼成完整 64 位密钥encrypt与decrypt对单个 32 位分组操作且二者互为逆运算即decrypt(encrypt(x)) x。2.2 构造函数实现src/KeeloqLib.cpp 中构造函数仅保存两个密钥字Keeloq::Keeloq(const unsigned long keyHigh, const unsigned long keyLow) : _keyHigh( keyHigh ), _keyLow( keyLow ) { }三、算法原理与 528 轮核心实现Keeloq 本质是一个非线性反馈移位寄存器NLFSR结构的分组密码。库中定义了一个关键的查表常量#define KeeLoq_NLF (0x3A5C742EUL)这个 32 位常量0x3A5C742E就是 Keeloq 的非线性函数NLFNonLinear Function查找表其第i位i 0..31作为 5 个输入位组合1, 2, 4, 8, 16 加权的输出真值。32 位常量共含 32 个输出位正好覆盖 5 输入的 32 种组合。3.1 加密528 轮右移encrypt 的实现unsigned long Keeloq::encrypt( const unsigned long data ) { unsigned long x data; unsigned long r; int keyBitNo, index; unsigned long keyBitVal,bitVal; for ( r 0; r 528; r ) { keyBitNo r 63; if(keyBitNo 32) keyBitVal bitRead(_keyLow,keyBitNo); else keyBitVal bitRead(_keyHigh, keyBitNo - 32); index 1 * bitRead(x,1) 2 * bitRead(x,9) 4 * bitRead(x,20) 8 * bitRead(x,26) 16 * bitRead(x,31); bitVal bitRead(x,0) ^ bitRead(x, 16) ^ bitRead(KeeLoq_NLF,index) ^ keyBitVal; x (x1) ^ bitVal31; } return x; }逐行拆解密钥位选择keyBitNo r 63即每 64 轮循环一次完整 64 位密钥keyBitNo 32时取_keyLow的第keyBitNo位否则取_keyHigh的第keyBitNo - 32位NLF 索引计算取当前状态x的第 1、9、20、26、31 位按 1/2/4/8/16 加权合成 0~31 的索引查表KeeLoq_NLF反馈位bitVal bit0(x) ^ bit16(x) ^ NLF[index] ^ keyBit即状态位 0、状态位 16、非线性函数输出与密钥位四者异或移位x (x1) ^ bitVal31整体右移 1 位并把反馈位送入最高位——这是标准 NLFSR 的移位反馈过程。加密共迭代 528 轮0x3A5C742E也常与 528 这个轮数一起出现在各类 Keeloq 实现中528 8×64 16即 8 轮完整密钥循环外加 16 轮。3.2 解密528 轮左移与密钥逆序decrypt 是加密的镜像过程for (r 0; r 528; r) { keyBitNo (15-r) 63; ... index 1 * bitRead(x,0) 2 * bitRead(x,8) 4 * bitRead(x,19) 8 * bitRead(x,25) 16 * bitRead(x,30); bitVal bitRead(x,31) ^ bitRead(x, 15) ^ bitRead(KeeLoq_NLF,index) ^ keyBitVal; x (x1) ^ bitVal; }与加密相比解密有三处镜像对应维度加密解密密钥位序r 63正序(15-r) 63逆序且偏移 15NLF 输入位位 1, 9, 20, 26, 31位 0, 8, 19, 25, 30整体下移 1 位异或的线性位位 0 与位 16位 31 与位 15对称位置移位方向右移x1左移x1这体现了分组密码“加解密同构”的设计思想只要把移位方向、密钥使用顺序和位索引对称翻转同一个 NLF 表即可完成解密。四、测试示例与自验证4.1 示例程序tests/KeeloqLibTest/KeeloqLibTest.ino 提供了一个开箱即用的 Arduino 测试串口波特率 9600#include KeeloqLib.h void setup( void ) { Serial.begin(9600); Keeloq k(0x01020304,0x05060708); const unsigned long p 6623281UL; const unsigned long enc k.encrypt(p); const unsigned long dec k.decrypt(enc); Serial.print(Plaintext : ); Serial.println(p,DEC); Serial.print(After encrypt: ); Serial.println(enc,HEX); Serial.print(After decrypt: ); Serial.println(dec,DEC); }预期行为密钥keyHigh 0x01020304keyLow 0x05060708明文6623281十进制enc输出 32 位密文十六进制dec必须重新还原为6623281以此验证加解密互为逆运算。由于该实现与 Microchip SDK 输出一致只要dec p即可确认当前平台的实现与官方算法兼容。这个模式也可以扩展为已知明文/密文对的回归测试固定密钥后把enc的十六进制结果记录下来后续改动后重新跑一遍比对。4.2 依赖与编译测试示例依赖KeeloqLib.h在 Arduino IDE 中把 lib/lib_rf/KeeloqLib 目录放入libraries路径即可在 PlatformIO 中则把该目录加入lib_deps或lib_extra_dirs。库头文件会根据编译目标自动选择Arduino.hArduino 1.0或WProgram.h旧版本。五、仓库实战Tasmota 的 Jarolift 卷帘驱动xdrv_36_keeloq.inoKeeloqLib 在 Tasmota 中的真实用途是驱动 Jarolift 卷帘遥控协议对应驱动文件 xdrv_36_keeloq.ino。这是理解该库价值的最佳落地案例。5.1 硬件与配置前提从驱动头部注释可以确认硬件要求使用硬件 SPI 与CC1101433 MHz 射频收发芯片需要两个用户可配置 GPIOGPIO_CC1101_GDO0与GPIO_CC1101_GDO2实际只有GPIO_CC1101_GDO0被使用由 CC1101 库决定必须为 GPIO05GDO2为“假”GPIO仅作占位。编译开关为USE_KEELOQ在 my_user_config.h 中可见其定义说明//#define USE_KEELOQ // Add support for Jarolift rollers by Keeloq algorithm (4k5 code)即启用后固件约增加 4.5 KB 代码。需要特别注意的是tasmota_globals.h 中在部分 ESP32 配置下会#undef USE_KEELOQ原因是所用 cc1101 库与 ESP32 不兼容tasmota_configurations.h 与 tasmota_configurations_ESP32.h 中的多数配置集也默认禁用它xsns_121_tfa_marbella.ino 中明确#error USE_TFA_MARBELLA and USE_KEELOQ both drive the CC1101 and cannot be combined——二者共享 CC1101不能同时启用。因此实际运行前提以 ESP8266 为主且不能与 TFA Marbella 传感器功能共存。5.2 主密钥与设备密钥的派生Keeloq 的第一个用途Jarolift 协议使用“主密钥master key→ 设备密钥device key”的两级派生。在 CmdSet 中用户通过命令KeeloqSet写入主密钥的高 32 位、低 32 位、序列号与计数器Settings-keeloq_master_msb param[0]; Settings-keeloq_master_lsb param[1]; Settings-keeloq_serial param[2]; Settings-keeloq_count param[3];随后 GenerateDeviceCryptKey 用主密钥构造Keeloq对象并对“序列号 固定标志位”做解密来派生出该设备专用的 64 位设备密钥Keeloq k(Settings-keeloq_master_msb, Settings-keeloq_master_lsb); jaroliftDevice.device_key_msb k.decrypt(jaroliftDevice.serial | 0x60000000L); jaroliftDevice.device_key_lsb k.decrypt(jaroliftDevice.serial | 0x20000000L);这里把serial | 0x60000000与serial | 0x20000000两个 32 位数据分别解密得到设备密钥的高、低半字。这是 Keeloq 双向性的典型应用主密钥参与“加密式”的密钥派生反方向使用decrypt。5.3 遥控数据帧的构造Keeloq 的第二个用途CmdSendButton 中按钮值取值约定为0x8上、0x4停止、0x2下、0x1学习。真正组帧在 CreateKeeloqPacketKeeloq k(jaroliftDevice.device_key_msb, jaroliftDevice.device_key_lsb); unsigned int result (jaroliftDevice.disc 16) | jaroliftDevice.count; jaroliftDevice.pack | jaroliftDevice.serial 0xfffffffL; jaroliftDevice.pack | (jaroliftDevice.button 0xfL) 28; jaroliftDevice.pack 32; jaroliftDevice.enc k.encrypt(result); jaroliftDevice.pack | jaroliftDevice.enc;可以看到明文result (disc 16) | count即“频道标识默认0x0100占高 16 位 滚动计数器占低 16 位”用设备密钥而非主密钥对result做encrypt得到 32 位密文最终 64 位发送包pack高 32 位为“序列号(28 位) 按钮(4 位)”低 32 位为 Keeloq 密文。这个结构完整展示了 Keeloq 在真实 RKE 协议中的标准用法把易变的计数器与频道标识加密成认证码与明文序列号、按钮位一起构成空中帧。滚动计数器每次发送后自增并回写Settings-keeloq_count见 CmdSendButton确保重放攻击失效。5.4 空中发射与命令一览组帧完成后驱动通过SendSyncPreamble(13)发送 13 组同步前导再逐位调用 SendBit 按 400 µs/800 µs 的脉宽编码发送 72 位数据每帧重复发送 2 次并使用noInterrupts()/interrupts()保护发送时序。驱动对外暴露三条控制台命令见 kJaroliftCommands命令函数作用KeeloqSet msb,lsb,serial,countCmdSet写入主密钥高/低 32 位、序列号、计数器并派生设备密钥KeeloqSendButton nCmdSendButton按按钮值0x8/0x4/0x2/0x1构造并发射一帧KeeloqSendRaw bitsCmndSendRaw直接按1/0字符串原样逐位发射调试用四个参数分别持久化到 tasmota_types.h 中定义的keeloq_master_msb、keeloq_master_lsb、keeloq_serial、keeloq_count四个uint32_t字段。六、在自己的项目里复用 KeeloqLib总结一套可复用的集成路径引入库复制 lib/lib_rf/KeeloqLib 到你的 Arduinolibraries目录或 PlatformIO 的lib目录初始化Keeloq k(keyHigh, keyLow);其中两个 32 位参数拼接为 64 位密钥加解密uint32_t enc k.encrypt(plain);、uint32_t plain k.decrypt(enc);自测仿照 KeeloqLibTest.ino 验证decrypt(encrypt(x)) x再与 Microchip SDK 已知向量比对协议集成参考 xdrv_36_keeloq.ino 的模式——用主密钥解密派生子密钥、用子密钥加密计数器与标识组成帧注意平台限制当前仓库中该库与 CC1101 的组合主要面向 ESP8266部分 ESP32 配置集已#undef USE_KEELOQ且不能与USE_TFA_MARBELLA并存。结语从 528 轮 NLFSR 的位级实现到 Arduino 测试样例再到 Tasmota 中 Jarolift 卷帘驱动的完整落地KeeloqLib 虽只有两个源文件却把 Keeloq 算法的全部核心要素64 位密钥、32 位分组、NLF 查表、双向加解密、密钥派生与滚动计数器组帧浓缩其中。无论你是想学习分组密码的轻量实现还是需要兼容 Microchip RKE 协议的无线项目都可以直接以本仓库的 KeeloqLib 为起点在个人实验范围内放心使用同时谨记 README 中关于商业应用的专利提醒。【免费下载链接】TasmotaAlternative firmware for ESP8266 and ESP32 based devices with easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX. Full documentation at项目地址: https://gitcode.com/GitHub_Trending/ta/Tasmota创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表