站内搜索
发作品签到
专业版

#第十届立创电赛#次世代数字钥匙——PocketTrustee

工程标签

2.0k
0
0
3

简介

次世代数字钥匙

简介:次世代数字钥匙
第十届立创电子设计开源大赛

开源协议

CC BY 4.0

创建时间:2025-09-24 18:00:08更新时间:2025-10-26 16:35:27

描述

免责声明

1. PocketTrustee(以下简称本项目)是由社区支持的开源项目,没有任何个人或集体可以为其安全性提供长期保障;

2. 本项目仅供学习、交流使用,严禁将PocketTrustee用于任何需要安全保障的领域;

3. 由于使用本项目造成的财产损失,社区开发者不承担任何责任;

4. 本项目硬件部分以CC BY 4.0协议发放,软件部分以Apache-2.0协议发放,社区开发者不对本项目任何部分的可靠性负责,社区开发者不对衍生项目负责;

5. 本项目所使用的开源库不在“本项目软件”的范围内,因此不受Apache-2.0协议约束,不随同本项目分发,关于这些库的开源协议,请查看库文件夹下的LICENSE文件;

1、项目功能介绍


“数字钥匙超进化”

卡片太多,总是忘记带卡片?

小区门禁是低频卡,手机无法模拟?尝试复制卡片,却被防火墙识破?

CPU卡,滚动码卡,全加密卡,手机模拟无能为力?

聊天软件的密码,工作平台的密码,某个神秘小网站的密码......密码太多记不来,设置为相同的密码又担心泄漏一个全部完蛋?

Authenticator为我生成了强密码,却还要手动输入,断网直接同步失败?

TOTP,FIDO,双因素验证希望有一个物理密钥,但市场上的物理密钥却太贵?

PocketTrustee将解决以上所有问题!

如果你有了解过一些安全产品,那么简单来说,PocketTrustee是这些产品的整合;

PocketTrustee有一个13.56Mhz的NFC天线,首先可以模拟IC卡(用于传输NDEF数据),其次充当IC卡芯片的天线,用于支持物理卡片;由于本质只是给卡片换了个天线,因此理论上PocketTrustee支持所有类型的卡片,只要你能把芯片整出来;

PocketTrustee还有一个125khz的低频天线,用于读取和模拟低频ID卡,弥补了手机/手环NFC模拟不能模拟低频卡的缺点;目前低频ID卡仍有大量老旧小区在用,因此支持ID卡是非常必要的;

除了卡片相关功能,我们还有数字密钥功能;

PocketTrustee的主控STM32L443支持USB Device,TRNG和AES加密,当工作在HID模式下时,可以充当一个键盘;用户可以生成密码,保存密码,然后在需要时使用PocketTrustee自动输入密码,这弥补了Authenticator类软件不能自动输入的缺点,毕竟手动输入一串字母数字符号组合的随机密码可是很痛苦的()

此外,还支持双因素验证,主要体现在TOTP(时间一次性密码)和FIDO2(无密码身份验证协议,目前正在实现),除此之外,其他一切验证协议都是有可能实现的,只是软件更新的问题;

这些安全功能都是常规功能,PocketTrustee不会止步于此,这块小小的数字钥匙有着无穷的开发潜力,请看我们目前想到的特色功能;

2、项目属性


项目为首次公开,公开前由本人独立开发,并为首次参与“立创电子设计大赛”

3、开源协议


项目硬件部分以CC BY 4.0协议发放,软件部分以Apache-2.0协议发放;

你可以在Github上找到本项目的软件部分,并为其贡献代码;

本项目所使用的开源库不在“本项目软件”的范围内,因此不受Apache-2.0协议约束,不随同本项目分发,关于这些库的开源协议,请查看库文件夹下的LICENSE文件;

4、硬件部分


PocketTrustee的硬件部分可以分为高频射频部分、低频射频部分、数字部分,硬件框图如下:

4.1、高频射频部分实现

IC卡工作在13.56Mhz高频段,相比于ID卡可以传输更多信息。IC卡的分类非常多,最常见的是Mifare 1卡(简称M1卡),部分扇区加密的M1卡也称半加密卡,全部扇区加密的卡即全加密卡;

M1卡可以通过漏洞攻击破解,一些厂家在M1卡的基础上改进,出现了无漏洞卡、滚动码卡、CPU卡等,这些卡通常无法被模拟(使用手机NFC模拟时提示卡片被加密,仅能模拟卡号);

PocketTrustee考虑到此问题,集成了IC卡模拟和物理卡槽;IC卡物理卡槽是PocketTrustee全能的关键,等同于为IC卡更换工作环境;

物理卡槽切换使用的是模拟开关PI3USB14;这是专为高频信号设计的模拟开关,-3dB可达815MHz;

IC卡模拟通过PN532芯片实现,虽然PN532是一款比较老的芯片,但是这款经典的芯片支持许多IC卡工具(如MifareOneTool),配合PocketTrustee的透传模式,可以将PocketTrustee作为一个全功能读卡器使用,用于编辑其他卡片;此外PN532支持非加密IC卡模拟功能,支持NDEF协议,可以传递Wi-Fi,URI,个人名片等多种信息;

稚晖君大佬曾设计过一款多功能NFC卡片Link-Card,采用物理开关切换;PocketTrustee选择使用模拟开关,并将物理卡槽设计为SD卡形状,可以很方便地插拔而无需拆开设备外壳,便于添加/去除卡片,算是对Link-Card的一种改进(在这里感谢Link-Card项目为本项目提供了部分设计灵感)

4.2、低频射频部分实现

ID卡工作于125Khz低频,仅能传递ID卡号信息,ID卡号以Manchester编码载波于125Khz信号上;

PocketTrustee选择纯模拟电路实现载波信号提取;

此时,STM32L443的COMP(低功耗比较器)就起到关键作用了,通过与0v电平进行比较,我们就能捕获到Manchester编码的上升下降沿,最后进行软件处理即可,实现原理请见软件部分;

为了防止第三方可复制卡片,部分ID卡门禁读头会尝试先写入卡片,再读取卡片,以此检测用户是否使用了复制卡,也被称为防火墙,PocketTrustee的ID卡模拟只会简单纯粹地输出ID卡号信息,并不会响应写入信号,因此不会被防火墙识破;

4.3、数字部分实现

这部分介绍比较简单,主控选用STM32L443,一款超低功耗MCU,最主要特点是具有硬件AES加密;

PocketTrustee使用了两颗LDO作为电源,其中TPS7A2033为主要电源,处于常开状态;而TPS7A0333专为指纹模块供电,并且可控关闭;这两款LDO均为超低IQ(静态电流) LDO,关断状态下静态电流仅有3nA;

很难利用替换指纹模块来破解认证机制,PocketTrustee选用的ZW0919支持多种加密认证(SM4,AES,RSA等),更换指纹模块将无法识别并导致设备锁死;

4.4、某次神秘bug的启示

PocketTrustee的前几版硬件,出现了按钮一带三的情况,即按下一个按钮,三个按钮的中断全部触发;

为了排查了这个问题,重复打了数版PCB,而问题迟迟不能解决,可把我急坏了(

在多位热心大佬的帮助下,问题最后解决,在这里和大家分享一些可能的原因,供大家设计PCB时规避;

被干扰的通道belike:

 

问题1:回路面积过大

回路面积过大可能形成天线,影响信号传递,请勿模仿(

问题2:地平面不完整/地回路过窄

当地回路过窄,电容放电导致局部地平面电平被抬高,导致中断触发,请勿模仿x2;

现在的PocketTrustee留一个完整的地平面,不怕你流不回去(

问题3:陈年老助焊剂

问题在这里终于得到彻底解决,我使用的助焊剂有些年头了,性质发生了一些变化,导致严重的信号耦合;

各位一定要使用优质的助焊剂,并且记住洗板也是很重要的(

5、软件部分


PocketTrustee的软件设计很有意思,也是一个庞大的工程,在这颗256KB Flash 64KB SRAM的MCU上,可能是无限的!让我们慢慢道来;

4.1、软件特性概述

PocketTrustee运行在FreeRTOS上,并写了一套专用GUI;

我们选择的工具链是CMake+ARM-GCC+Ninja,主要程序选择C++编写,全开源工具链也不失为本项目的一大特点;

我们的软件长期更新,你可以在Github获取最新的固件,也欢迎各位大佬的贡献;

4.2、GUI

虽然PocketTrustee是一个数字钥匙,开发重心应该是安全功能,但我却在GUI的设计上头疼了很久;

大部分的GUI库,即使是轻量级GUI库,都是为彩屏设计,集成了许多控件,对于单色屏(尤其是刷新率极低的墨水屏)非常不友好,并且占用大量flash;

因此我为PocketTrustee写了一个极简GUI,专为墨水屏设计,仅由一个cpp文件和一个头文件组成,且自由度极高(本身不带有任何控件,渲染行为均由用户定义的回调函数实现);

这个GUI占用了9.4K的静态内存(双缓冲,每一个缓存4736字节),不使用动态内存,目前在PocketTrustee上表现良好;

STM32L443的SRAM分为SRAM1(48KB)和SRAM2(16KB),PocketTrustee将SRAM2用于显存和FS缓存,而堆栈和全局变量存储在SRAM1中,充分利用L4的内存布局特性;

GUI任务运行在一个独立的Task中,并在阻塞状态下等待Notify,阻塞状态的Task不会影响Tickless LowPower模式的进入;

FreeRTOS的直达任务通知在这里发挥了很大作用;一方面,我们不希望GUI任务在没必须刷新屏幕时占用CPU,另一方面,刷新这种耗时操作也不应阻塞其他任务;

通过直达通知,GUI任务在空闲时会自动处于阻塞状态,在刷新完成前,不会响应其他通知,从另一个角度完成了“软件消抖”的操作;

4.3、AES密钥,PIN保护,MPU和Firewall

用户的所有密码数据都在经过AES加密后存储于外部NAND Flash;

此外,PocketTrustee有一个由用户设置的六位PIN码,用于在设备被暂时锁定(如指纹错误次数过多)时进行验证解锁;

PIN码仅有一次输入机会,若输入错误,AES寄存器将被清空,同时设备被锁死;

除了爆破性破解(然而很难),只要我们能安全存储AES密钥和PIN码,那么其他数据就能被安全存储;

依靠L系列MCU超低功耗的特性,PocketTrustee的MCU设计为永不断电,并且AES密钥存储在AES-KEY寄存器中,而PIN码存储于一个受MPU和Firewall保护的特定内存区域中;

这种操作带来的好处是,常规方法将难以提取出密钥,保证了安全性,但同时意味着一旦MCU复位,密钥将丢失,设备无法再使用;

不必担心因为电量耗尽而复位的情况,由于被清空的只是密钥寄存器,数据仍然存在于Flash中,可以通过授权的上位机工具恢复数据,避免意外复位丢失密码的情况;

那如果设备丢失该怎么办?PocketTrustee提供了数据备份功能,如果设备丢失,通过上位机可以查询到备份的密码;

Firewall是一个很少被大家提及的特性,鲜有资料可以查询,那么我们来看看PocketTrustee中Firewall是如何保护PIN码的;

Firewall的工作特点是:被保护的数据段(可以是变量也可以是可执行数据)只能通过特定的入口进入,且进入后不能“非法跳出”;

这样就为受保护的数据和代码构建起一道墙,将墙内操作和墙外隔离开,因此叫Firewall;Firewall在使能后只能通过系统复位来关闭;

PocketTrustee将PIN码的存储和管理部分的代码使用Firewall保护起来,即使对于发起验证的方法来说,这部分操作都是不透明的;

 

4.4、Manchester解码

ID卡号通过Manchester编码载波于125Khz信号上,通过上面介绍的硬件电路,我们已经可以得到载波信号;

要读出卡号,还需要对载波信号进行Manchester解码;

STM32的COMP会在每一个上升下降沿触发中断,通过HAL_COMP_GetOutputLevel可以得到此时的LF_IN电平;

LPTIM提供一个4us的时基,配合COMP,很容易读出数据;

4.5、USB-Device和CBOR

PocketTrustee的USB协议栈是CherryUSB,这是一个国创开源的USB协议栈,详细信息请见cherry-embedded/CherryUSB: CherryUSB is a tiny and beautiful, high performace and portable USB host and device stack for embedded system with USB IP

我们主要使用到CDC和HID class,分别用于与上位机通讯和模拟键盘输入;

使用CDC与上位机通信有一个优势,即不需要安装驱动,兼容性更好;

CBOR是简明二进制对象的缩写,在WebAuth中使用广泛;

PocketTrustee的cbor编解码库是zcbor,详细情况请见NordicSemiconductor/zcbor: Low footprint C/C++ CBOR library and Python tool providing code generation from CDDL descriptions.

不论是FIDO2协议还是与上位机的通信,都用到了CBOR,受于篇幅限制这里不赘述;

4.6、外部Flash与LittleFS

GUI所使用的资源,以及用户数据全部存储于外部Flash,并使用LittleFS进行管理;

LittleFS是开源的文件系统,支持掉电保护(虽然我们用不上)和擦写均衡;

PocketTrustee的文件加密在前端进行,这意味着加密文件的文件信息是开放的,但只能读出被加密后内容,这种设计避免了不必要的加密带来的性能损耗,同时保证数据安全;

4.7、RTC,Timestamp与TOTP

不同于F1中直接使用CNTH和CNTL计秒的操作,L4提供了两个32bit寄存器,以BCD格式直接存储时间和日期

TOTP(基于时间的一次性口令)是一种双因素认证方法,TOTP通过当前时间戳来计算口令,因此不依赖于网络连接;

理解TOTP前,先来看看OTP(一次性口令)

了解原理后,PocketTrustee的TOTP实现就非常清晰了;

支持TOTP的网站会交给用户一个二维码,这个二维码包含密钥信息,当然PocketTrustee设备本身不能扫描二维码,但可以通过上位机分析后将密钥数据发送给设备;

密钥被AES加密后保存在外部NAND-flash内,使用时解密,结合当前时间戳计算即得到口令;

4.8、低功耗设计,FreeRTOS Tickless LowPower

低功耗是本项目设计的最大难点,体积限制了最大电池容量,而“钥匙”的定位会让人觉得这并不是需要经常充电的设备;

为了保持设备低功耗,首先我们使用了FreeRTOS的Tickless低功耗模式;

FreeRTOS的Tickless LowPower模式保证设备在空闲时能及时进入睡眠状态;

然而,最大深度睡眠时长受限于SysTick计时器,一般只有500ms;

好在PocketTrustee的软件设计十分紧凑,因此跳出睡眠只可能由外部操作触发;在进入停止模式后,MCU的PLL,MSI,HSI,HSE全部停止,SysTick也随之停止,此时睡眠跳出只能被外部中断触发,延长了最大睡眠时间;

一旦MCU空闲,即进入STOP2模式,该状态下MCU几乎完全不耗电;

通过CubeMX的PCC分析,主控在正常速度运作时的功耗为5.08mA

可以看到,主要功耗来源是用于产生125khz激励信号的TIM1,以及与PN532通讯的USART3;

不过,PocketTrustee的软件设计中,当不使用到某一项功能时,其相关外设时钟会被完全关闭,因此,即使是运行状态下,也不会达到最大功耗;

通过以上低功耗操作,算入其他元器件后,我们将PocketTrustee的静态总功耗降低到了200uA,如果是一颗500mAh的电池,那么理论续航就来到了2500小时,即104天;

平时刷卡就完全不耗电吗?其实还真是!这里我们测量的静态总功耗包括了模拟开关的功耗,刷卡时,PocketTrustee并不必要从睡眠中切出,只有切换卡片时才有必要唤醒设备;

需要USB的功能就更不必说,接上usb后只会越用电越多(

4.10、PocketTrusteeCLI

PocketTrusteeCLI是用于管理PocketTrustee的命令行工具,使用Python编写,随同PocketTrustee主软件分发,你可以在PocketTrustee仓库的tools文件夹下找到PocketTrusteeCLI的源码;

使用CLI工具可以初始化设备,添加/删除/编辑卡片和密码,管理TOTP,名片WiFi信息,以及进行数据备份和还原等

4.11、写不下去了

其实我们还有很多内容没有说;例如:指纹模块的通讯;如何处理上位机通信;ID卡模拟的实现;

但是立创的字数限制实在太紧了,如果大家对项目有任何疑惑,欢迎通过第十节提到的方式联系我;

4.12、如何编译,刷写固件

为了便于评委评估项目,附件区提供了拍摄演示视频时所使用的固件的源代码;

如果你打算复刻PocketTrustee,请前往Github或者Gitee下载最新版本源码进行编译,并参照README编译指南,而不是使用这里的演示版本;

对于安全设备,使用最新固件非常重要,请一定注意,以下编译方法仅适用于附件区提供的源码;

1. 下载工具链和刷写工具
下载STM32 CubeCLT并安装,如果你已经预先安装了CMake,ARM-GCC和ninja则可以跳过此步;

下载STM32 CubeProgrammer,实际上Cube CLT集成了CLI版本的CubeProgrammer,如果你愿意,也可以选择使用CLI版本的CubeProgrammer;

2. 编译
打开终端并转到项目目录下,逐行执行以下命令
cmake --preset "Debug"
cd ./build/Debug
ninja

在build/Debug文件夹下的PocketTrustee.elf即为编译产物

不要编译Release版,代码优化会造成一些无法预测的bug

3. 烧录固件并初始化
使用Cube Prog将固件上传到设备上即可,可选择性开启读保护;

现在需要使用上位机进行必要的初始化操作;连接设备和电脑,使用CLI工具(在tools文件夹下,使用python运行main.py),执行指令:

connect -a --init

随后根据提示操作即可,若中途失败,请重试;

6、BOM清单


元器件BOM表请见附件区,这里仅补充其他配件的参考购买方式;

墨水屏选用了佳显公司的GDEY029T94,支持4灰度;

指纹模块是海凌科公司的ZW0919;

电池选择213455锂离子聚合物电池,额定容量500mAh(亲测283455也能用,但底下塞不下天线);

外壳可以直接在嘉立创3D打印,树脂材质和尼龙材质均可;

NFC天线和低频天线可以自行选购,需要注意的是记得根据线圈电感修改谐振电容大小;我自己选用的是漆包线线圈,NFC线圈尺寸为30x35mm,低频线圈为32mm圆形线圈(电感345uH),很容易购买到,这里不贴链接;

更多信息请参考第九节——如何复刻;

7、大赛LOGO验证


 

 

8、演示您的项目并录制成视频上传


请见视频区

9、复刻指南


哪个工科男不想拥有一块PocketTrustee,让我手把手教你复刻!

9.1、打板,打印外壳

可以直接下载附件区的Gerber制版文件或者自行导出进行打样,推荐使用沉金工艺;(每月都可以白嫖嘉立创的4层沉金)

主板板厚:0.8mm;IC卡槽板厚:1.6mm;

请务必检查好板厚,打错了很可能无法安装

下载附件区的外壳文件进行打印,推荐嘉立创的1172 Pro尼龙,当然树脂也是可以的;

PS:外壳有开发版和普通版,区别在于调试接口有没有开孔;虽然出于安全考虑,应当打普通版,然而为了便于上传固件,还是强烈建议打开发版

开发版的调试接口开小了,需要手动再剪一下,1172Pro比较软,使用小刀切出口子即可;

9.2、采购元器件,焊接,实体卡片

元器件按照BOM表买就可以了,关于其他的配件(如电池和指纹模块)请见第六节BOM清单部分;

刷锡膏,热风枪,各位焊武帝一定不需要我多指导了;

这里大家可以选择性修改充电IC的电阻,默认的设定是50mA(也即0.1C),如果你希望充电电流能更大,可以适当调小阻值(计算公式给到了下方)

然而注意,普通锂离子聚合物电池的充电C数都比较小,请考虑由于增大充电电流带来的风险

实体卡片转移到卡槽上,需要剪卡然后将芯片取出来

用手机闪光灯找到并标记芯片所在位置,然后剪卡,就能拿出芯片了

用少量焊锡以贴片的形式焊上芯片,一定有芯片的一面朝下,背面的铜箔是导电的,会导致短路

焊接时不要高温,这些ic芯片非常不耐热,拿风枪吹久了就会导致损坏(我已经废掉一张武汉通了(

9.3、组装

先将指纹模块上自带的插座吹掉,那个太厚了;随后焊几根线上去,注意不要使用太粗的线(我这里直接使用漆包线);

卡到外壳上,周围封胶(708硅胶好使);

连接指纹模块和主板,再连接天线;
注意,我这里选择了漆包线天线导致太厚无法塞入下方空间,只能放在主板上面;这会导致信号大打折扣,尤其是低频天线(作者亲自踩坑);因此尽量把你的天线放在底下

最好垫隔磁片,我没有隔磁片就裁剪静电袋用了

扣上屏幕,连接电池,然后记得短接用来测试电流的两个脚,固定好主板,就能把屏幕合上了;

9.4、编译,上传固件,初始化

这部分可能随着软件更新而发生变化,所以请前往Github或者Gitee并参照那里的README进行操作;

9.5、结束

Enjoy your device.

10、开源精神:共享,贡献


PocketTrustee的源码目前由我本人维护,长期更新,请大家在Github上给我一个Star,留意后续更新;

如果你发现了源码中的Bug,或者有功能新点子,可以通过Issue反馈给我,我看到后会及时处理;

如果不会使用Github或Gitee,也可以加入我们的Issue&Ideas群,在这里反馈问题或新点子,软件更新动态也将在这里公布;

若两者都不便使用,可以通过邮箱联系到我:xlimitarea@outlook.com;

不过本人不经常看邮箱,邮件可能无法即使回复;

为Repo贡献可直接PR,我会在评估代码后拉取PR;

 

 

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

3D模型

序号文件名称下载次数
暂无数据

附件

序号文件名称下载次数
1
外壳.zip
4
2
Gerber_CardContainer_2025-10-14.zip
1
3
Gerber_PCB1_2025-10-14.zip
2
4
BOM_Trustee_1_PCB1_2025-10-14.xlsx
2
5
PocketTrustee演示版代码.zip
1
克隆工程
添加到专辑
0
0
分享
侵权投诉
知识产权声明&复刻说明

本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。

请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。

评论

全部评论(1
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航