基于Teensy 4.1的硬件密码保险箱DIY:从加密原理到工程实践

硬件隔离Teensy 4.1密码保险箱
于 2026-05-28 13:15:56 修改
·本内容遵循CC 4.0 BY-SA版权协议

1. 项目概述:为什么我们需要一个硬件密码保险箱?

在数字生活里,密码管理器已经成了必需品。从浏览器插件到独立的桌面应用,它们确实方便,把我们从记忆几十个复杂密码的苦海中解救出来。但不知道你有没有想过一个问题:这些软件,终究是运行在你的电脑或手机操作系统上的。你的操作系统里,除了密码管理器,还跑着成千上万个其他进程——浏览器、邮件客户端、后台更新服务,甚至是你无意中下载的某个小工具。任何一个进程如果被恶意软件劫持或本身就是恶意的,理论上都有可能窥探到密码管理器内存中的数据,或者通过键盘记录、屏幕截图等方式窃取你的主密码。软件层面的安全,就像把宝藏锁在一个有很多扇门和窗户的房间里,你永远无法确定是否有一扇窗忘了关。

这就是硬件隔离(Hardware Isolation)理念的价值所在。把最敏感的操作——加密、解密、密钥存储——放到一个独立的、功能单一的硬件设备里去完成。这个设备只干这一件事,没有复杂的操作系统,没有网络栈,更没有其他乱七八糟的进程。它就像一个物理的“保险箱”,你的秘密只在里面被处理,与外部那个充满潜在威胁的计算环境完全隔离开。我这次折腾的 Midbar (Teensy 4.1) V3.0 项目,就是基于这个思路的一次实践。它本质上是一个基于 Teensy 4.1 高性能微控制器的独立硬件密码保险箱。

这个DIY项目能做什么?很简单,也很核心:安全地存储你的登录凭证(用户名、密码、网站)和信用卡信息。你可以通过USB键盘来操作它,所有数据在存入设备时,会经过一个我称之为“丧心病狂”的加密链(3DES + AES + Blowfish + Serpent,工作在CBC模式)进行加密,并用HMAC-SHA256来保证数据完整性。加密后的数据可以选择存储在芯片内部的EEPROM(断电不丢失的存储器,空间有限但速度快),或者外接的Micro SD卡上(空间近乎无限)。当你需要用时,解锁设备,它可以把密码“敲”进你的电脑——对,它自己可以模拟成一个USB键盘,自动输入,你连看都不用看,避免了被肩窥或截屏的风险。

适合谁来玩这个项目?如果你是对嵌入式开发、硬件安全有兴趣的开发者、极客,或者单纯是对现有软件密码管理器心存疑虑,想拥有一个完全由自己掌控的“物理密码本”的安全爱好者,那么这个项目会是一个绝佳的起点。它不只是一个焊接和刷固件的体力活,更涉及加密算法应用、存储管理、人机交互设计等一系列有趣的问题。接下来,我会带你从设计思路到每个焊点,从加密原理到避坑指南,完整地复现这个硬件数据保险库。

2. 核心设计思路与安全架构解析

2.1 硬件选型:为什么是Teensy 4.1?

市面上微控制器那么多,从Arduino Uno到ESP32,为什么这个项目选择了Teensy 4.1?这背后是性能、接口和生态的综合考量。

首先,加密是计算密集型任务。我们采用的加密链(后面会细说)涉及多次块加密操作,对处理器的算力有一定要求。Teensy 4.1搭载了NXP的i.MX RT1062跨界MCU,这是一颗主频高达600 MHz的Cortex-M7内核。对比常见的AVR(16 MHz)或ESP8266(80-160 MHz),它的计算能力有数量级的提升。这意味着加密解密操作几乎是瞬间完成,用户不会有明显的等待感,体验流畅。我曾尝试在性能较弱的板子上跑同样的算法,输入一个长密码后要等上好几秒,体验非常糟糕。

其次,丰富的内置存储和接口。Teensy 4.1自带8MB的Flash(用于存储程序)和1MB的RAM,这为相对复杂的菜单系统和数据缓冲区提供了充足空间。更重要的是,它板载了一个Micro SD卡槽。对于密码管理器这类应用,存储扩展能力至关重要。内部EEPROM(通过模拟实现,约1KB)容量有限,只能存少量核心凭证(如最常用的16组登录信息)。而SD卡可以让你存储成百上千条记录,包括那些不常用但必须记住的各类账户信息。此外,它原生支持USB Host功能,这意味着我们可以直接连接USB键盘作为输入设备,无需额外的USB Host Shield模块,简化了硬件设计。

最后,强大的社区与库支持。PJRC为Teensy提供了极其优秀的Arduino核心兼容库和Teensyduino插件,使得在Arduino IDE下开发变得非常方便。像我们需要的TFT显示屏驱动(Adafruit_ST7735)、加密算法库(虽然部分需要自己实现或整合)等,都有成熟的生态支持。这大大降低了开发门槛,让我们能把精力集中在应用逻辑和安全设计上,而不是底层驱动调试。

注意:Teensy 4.1的IO引脚是3.3V电平,且不兼容5V。在连接外部器件(如显示屏)时,务必确认其工作电压。错误接入5V信号可能会永久损坏芯片。

2.2 安全架构核心:加密链与完整性验证

软件密码管理器的核心是加密算法。Midbar V3.0的安全模型建立在两个支柱上:一个强大的加密链,和一个可靠的完整性验证机制

1. 加密链:3DES + AES + Blowfish + Serpent (CBC Mode)

看到这一串名字,你的第一反应可能是“过度设计”或“套娃”。确实,在密码学中,通常认为一个经过充分验证的强算法(如AES-256)就足够了。我设计这个加密链的初衷,更多是出于一种“深度防御”的思维实验,并解决早期版本中的一个设计缺陷。

  • 什么是超级加密(Superencryption)? 正如NIST所定义的,它指的是对已经加密过的密文再次进行加密的操作。我们这个加密链就是依次执行:明文 -> 3DES加密 -> AES加密 -> Blowfish加密 -> Serpent加密 -> 最终密文。理论上,这样一个串联的强度至少不低于其中最强的那个算法,并且由于组合了不同的算法和更长的总体密钥长度,可能会对某些针对特定算法的未知攻击增加额外的抵抗力,同时也会输出熵值更高的密文。
  • 为什么是CBC模式? 这是我从V2.0版本升级到V2.5版本时一个关键的修正。早期版本使用了一种类似ECB的怪异模式。在ECB模式下,相同的明文块会产生相同的密文块。攻击者虽然不能通过交换密文块来构造合法密文(因为每个块都单独用HMAC保护了),但他可以将密文A的第n块,替换为密文B的第n块。解密后,对应的明文块就会被替换,可能导致信息泄露或篡改。切换到CBC(密码块链接)模式后,每个明文块在加密前,都会先与前一个密文块进行异或操作。这样,如果攻击者替换了中间任何一个密文块,不仅会导致该块解密出的明文乱码,还会级联影响到下一个块的解密,因为下一个块的解密依赖于被篡改的密文块。这使得对密文的任何局部篡改都会产生全局性的、明显的错误,更容易被完整性检查发现。
  • 密钥派生与主密码:所有加密算法的密钥,都部分派生自用户设置的主密码。这意味着,即使有人物理上拿到了你的Teensy设备和解密固件,没有你的主密码,他也无法推导出正确的加密密钥来解密数据。这是密码管理器的安全基石。主密码本身并不直接存储,而是通过一个密钥派生函数(在代码中实现)来生成加密所需的各个密钥分量。

2. 完整性验证:HMAC-SHA256

加密保证了机密性,但无法防止密文被篡改。攻击者可能通过物理方式(如对EEPROM/SD卡进行位翻转攻击)或软件漏洞来修改存储的密文。为了检测这种篡改,Midbar使用了基于HMAC-SHA256的消息认证码。

  • 工作原理:当用户保存一条记录(例如一组账号密码)时,Midbar会先将所有字段(用户名、密码、网站)拼接成一个完整的字符串,然后使用一个独立的认证密钥(同样由主密码派生)计算这个字符串的HMAC-SHA256值,得到一个“标签”(Tag)。这个标签随后被加密,并与加密后的数据一起存储。
  • 验证过程:当用户读取记录时,设备先解密数据,再解密之前存储的标签。然后,它对刚解密出来的明文数据重新计算一次HMAC-SHA256标签。最后,比较新计算的标签和解密出来的旧标签是否一致。
  • 结果:如果两者匹配,说明数据自存储以来未被篡改。如果不匹配,Midbar会明确提示“完整性验证失败”,警告用户数据可能已损坏或被恶意修改。这就像在保险箱上贴了一张特殊的封条,一旦被打开或调包,封条就会断裂。

实操心得:关于“位翻转攻击” 原文提到这种攻击“kinda works”。在嵌入式环境中,由于宇宙射线、电源波动等原因,存储单元(如EEPROM)确实可能发生位翻转(0变1或1变0)。HMAC-SHA256对此非常敏感,哪怕只改变一个比特,计算出的标签也会截然不同,从而被检测到。所以,虽然攻击在物理上可能发生,但几乎不可能“悄无声息”地通过完整性验证。这反而体现了HMAC在这种场景下的价值。

2.3 存储策略:EEPROM与SD卡的分工

Midbar采用了分层存储策略,兼顾了速度、安全性和容量。

  • EEPROM(内部存储)

    • 特点:速度快,访问延迟极低,与MCU内核紧密耦合。但容量非常小(Teensy 4.1通过Flash模拟的EEPROM约1KB)。
    • 用途:用于存储最核心、最常用的少量记录(设计容量为16组登录信息+12组信用卡信息)。因为空间宝贵,这里做了一些优化:所有记录共享一个初始化向量(IV),并且对整个EEPROM数据区进行一次性的完整性校验,而不是为每条记录单独存储HMAC标签。这样可以节省大量空间。
    • 优点:访问迅速,适合存放需要快速调用的核心密码(如电脑登录密码、邮箱主密码)。
    • 缺点:容量硬伤,无法扩展。
  • Micro SD卡(外部存储)

    • 特点:容量巨大(以GB计),可以存储海量记录。但访问速度相对较慢,且是物理上可移除的介质。
    • 用途:存储大量的、不常使用的记录。每条记录都拥有自己独立的IV和HMAC-SHA256标签,安全性更高。理论上,只要卡空间足够,你可以存储成千上万条记录。
    • 优点:容量无限,便于备份(可以直接复制卡上的加密文件到电脑)。
    • 缺点:SD卡有寿命限制(读写次数),且物理上可能丢失或损坏。因此,定期备份SD卡数据是必要的。

这种设计非常实用:把高频、核心的数据放在快速的“内存保险箱”(EEPROM),把低频、归档的数据放在大容量的“仓库保险箱”(SD卡)。你需要权衡的是,哪些密码值得占用宝贵的EEPROM空间。

3. 硬件组装与核心电路详解

3.1 物料清单与采购建议

要复现这个项目,你需要准备以下核心部件。我在这里列出了一些选购时的注意事项,能帮你避开不少坑。

部件 数量 说明与选购建议
Teensy 4.1 开发板 1 项目的核心。务必确认是4.1版本,它带有SD卡槽。4.0版本没有,需要额外接模块。
1.77英寸 TFT LCD 显示屏 1 驱动芯片需为 ST7735。这是最常见的一种,价格便宜,库支持完善。注意分辨率为128x160。
USB-A 母座 1 用于连接USB键盘。可以从旧的电脑机箱前面板扩展挡板上拆,或者单独购买。
USB键盘 1 任何标准USB全尺寸或迷你键盘均可。用于输入主密码和操作菜单。
Micro SD 卡 1 可选,但强烈推荐。用于扩展存储。容量无需太大,1GB或2GB足够,但必须格式化为 FAT32 文件系统。
杜邦线(公对公、公对母) 若干 用于连接各部件。建议多备一些不同长度的。
面包板或PCB 1 用于固定和连接电路。初期验证用面包板,想做成品可以考虑设计或购买一个简单的PCB。
5V / 3.3V 电源 1 Teensy 4.1可通过USB口供电,非常方便。

关于显示屏的特别提醒:市面上ST7735驱动的1.77寸屏有很多变种,它们的引脚顺序、背光控制方式可能不同。最常见的是带CS, RST, DC, MOSI, SCK, VCC, GND, BL 这8个引脚的模块。其中 BL(背光) 引脚的处理方式五花八门:有的要求接3.3V常亮,有的要求接GND常亮,有的可以通过PWM调光,还有的可以不接。在连接前,最好找到你这款屏的数据手册或卖家提供的说明。一个安全的做法是:先不接BL,如果上电后屏幕不亮,再尝试接3.3V或GND。

3.2 电路连接图与接线表

硬件连接非常简单,本质上就是把屏幕和USB口接到Teensy 4.1对应的引脚上。下图是核心的连接示意图,你可以根据这个在面包板上搭建。

此处为文字描述连接图,实际项目中可配图) 想象一下,Teensy 4.1开发板水平放置。我们将屏幕和USB口连接到其右侧的引脚排针上。

Teensy 4.1 引脚 连接至 功能说明
3.3V 显示屏 VCC 为屏幕提供3.3V电源。绝对不要接错到5V!
GND 显示屏 GND, USB口 GND 共地。
PIN 7 显示屏 CS (Chip Select) 片选信号,低电平有效。
PIN 8 显示屏 RST (Reset) 复位信号,低电平复位。
PIN 20 显示屏 DC (Data/Command) 数据/命令选择线。
PIN 21 显示屏 MOSI (Master Out Slave In) SPI数据线,主设备输出。
PIN 14 显示屏 SCK (Serial Clock) SPI时钟线。
BL引脚 根据屏幕型号接 3.3V 或 GND 背光控制。先悬空测试,不亮再试接3.3V或GND。
5V 仅连接 USB口的 VCC (红) 重要:只给USB口供电!Teensy引脚不兼容5V!
GND USB口的 GND (黑) 共地。
D+ (Pin 24) USB口的 D+ (绿) USB数据线+。
D- (Pin 25) USB口的 D- (白) USB数据线-。

接线核心要点

  1. 电源隔离:确保屏幕的VCC只接Teensy的3.3V。USB口的5V红线只接Teensy的5V引脚千万不要把USB口的5V误接到屏幕或Teensy的任何数据引脚上,那会烧毁芯片。
  2. SPI引脚:Teensy 4.1有多个SPI接口,我们使用的是默认的SPI(MOSI=21, SCK=14)。代码中也是这么定义的,不要接错到其他SPI引脚(如11,13)。
  3. USB Host:Teensy 4.1的USB Host功能是通过特定的D+和D-引脚(24和25)实现的,必须接对。

3.3 焊接与组装注意事项

如果你打算做一个永久性的设备,而不是在面包板上测试,那么焊接是必要的步骤。

  1. 焊接顺序:建议先焊接USB母座和屏幕的排针到一块洞洞板或定制PCB上,然后再用杜邦线或导线连接到Teensy的排母上。Teensy本身可以先不焊死,插在排母里,方便后续调试和更新固件。
  2. 防短路检查:焊接完成后,务必用万用表的蜂鸣档仔细检查相邻引脚、电源与地之间是否有短路。这是避免上电“放烟花”的最关键一步。
  3. 机械固定:考虑为屏幕和Teensy设计或3D打印一个外壳。这不仅美观,更能保护电路,防止引脚意外短路。一个带按钮的开关键也是个不错的附加功能。
  4. 上电前最后确认:对照接线表,再肉眼检查三遍。特别是5V线是否只接到了USB口,以及屏幕VCC是否接的是3.3V

4. 软件环境搭建与固件烧录

4.1 安装Arduino IDE与Teensyduino插件

Midbar的固件是基于Arduino框架编写的,所以我们需要Arduino IDE作为开发环境,并为其添加Teensy 4.1的支持。

  1. 下载Arduino IDE:前往Arduino官网下载最新稳定版的IDE。安装过程很简单,一路下一步即可。
  2. 下载并安装Teensyduino:这是PJRC官方提供的插件,包含了Teensy系列板子的核心库、编译器链和烧录工具。
    • 访问PJRC的下载页面:https://www.pjrc.com/teensy/td_download.html
    • 运行下载好的Teensyduino安装程序。它会自动检测你电脑上已安装的Arduino IDE路径。
    • 在组件选择页面,务必勾选“Teensy 4.1”。下方的库可以全选安装,或者至少确保安装了“USBHost_t36”(用于USB键盘支持)和“SD”(用于SD卡读写)。
    • 完成安装。

安装完成后,打开Arduino IDE,在“工具” -> “开发板”菜单中,你应该能看到“Teensy 4.1”的选项了。

4.2 获取与准备Midbar固件

Midbar的源代码是开源的,你可以从两个地方获取:

  • SourceForge(推荐)https://sourceforge.net/projects/midbar/ 这里提供的是精简版,只包含Teensy 4.1 V3.0的固件和密钥生成工具,下载速度快(约3.4 MB)。
  • GitHubhttps://github.com/Northstrix/Midbar 这里是完整的仓库,包含所有历史版本、额外代码、图片和图表,但体积巨大(约323 MB)。除非你想研究其他版本,否则下载SourceForge的包就够了。

下载并解压后,你会看到类似Teensy 4.1 Version/V3.0/这样的目录结构。里面有几个关键文件夹:

  • Clear_EEPROM/:用于清空EEPROM的固件。
  • Firmware/:主固件源代码。
  • Untested RNG/:一个未经验证真随机性的密钥生成工具(gen.exe,仅Windows)。

4.3 安装必要的第三方库

Midbar的显示部分依赖Adafruit的图形库。你需要手动安装它们。有两种方法:

方法一(推荐,管理方便)

  1. 打开Arduino IDE。
  2. 点击“项目” -> “加载库” -> “管理库...”。
  3. 在库管理器中搜索“Adafruit GFX”,找到并安装“Adafruit GFX Library”。
  4. 同样地,搜索并安装“Adafruit ST7735”和“Adafruit BusIO”。 IDE会自动处理依赖关系。

方法二(手动安装)

  1. 从GitHub下载库的ZIP包:
    • Adafruit-GFX-Library: https://github.com/adafruit/Adafruit-GFX-Library
    • Adafruit-ST7735-Library: https://github.com/adafruit/Adafruit-ST7735-Library
    • Adafruit_BusIO: https://github.com/adafruit/Adafruit_BusIO
  2. 在Arduino IDE中,点击“项目” -> “加载库” -> “添加.ZIP库...”,然后分别选择你下载的三个ZIP文件。

安装完成后,重启Arduino IDE以确保库被正确加载。

5. 固件配置、密钥生成与首次启动

5.1 清空EEPROM

在第一次使用Midbar之前,必须清空Teensy的EEPROM。因为固件会读取EEPROM中的特定区域来判断是否已初始化。如果里面残留着旧数据,可能导致程序行为异常或无法启动。

  1. 在Arduino IDE中,打开Clear_EEPROM文件夹下的.ino文件。
  2. 在“工具”菜单中,确保“开发板”选为“Teensy 4.1”,“USB类型”暂时保持默认即可。
  3. 点击上传按钮(向右的箭头)。程序编译完成后,Teensy Loader会自动弹出。
  4. 按下Teensy 4.1板上的白色小按钮(Program按钮),等待程序烧录完成。
  5. 烧录完成后,程序会自动运行一次,完成EEPROM的清零。你可以通过串口监视器(波特率9600)看到“EEPROM Cleared”的提示。

5.2 生成并替换加密密钥

这是整个项目安全性的最关键一步! Midbar固件中预置的密钥只是示例。如果你不替换成自己生成的密钥,那么任何拥有相同固件的人都能解密你的数据。密钥生成必须使用可靠的随机源。

警告:项目提供的gen.exe工具作者明确声明未经过严格的随机性测试,无法保证其生成的密钥是密码学安全的。仅建议用于测试和学习目的。对于真实用途,你应该使用经过验证的随机数生成方法。

推荐的安全密钥生成方法

  1. 在Linux/macOS上:使用/dev/urandom。打开终端,输入:
    BASH
    head -c 64 /dev/urandom | xxd -p -c 64
    这会生成一个128个十六进制字符(64字节)的随机字符串。你可以多生成几次,拼接成所需长度。
  2. 使用密码学库:如果你会编程,用Python的os.urandom()secrets模块、OpenSSL命令行工具等生成随机字节,再转为十六进制。
  3. 专用硬件:使用真正的硬件随机数生成器(HRNG)。

假设你决定使用项目提供的gen.exe工具(理解其风险):

  1. 运行Untested RNG文件夹下的gen.exe
  2. 点击“Gen. keys for Midbar (Teensy 4.1) V3.0”按钮。界面背景变灰表示正在生成。
  3. 生成的密钥会显示在下方的大文本框中。请立即将这些密钥完整地复制并保存到一个安全的、离线的地方(例如用加密笔记软件记录,或打印出来物理保存)。一旦丢失,你将永远无法解密设备中的数据。

接下来,替换固件中的密钥:

  1. 用Arduino IDE打开Firmware文件夹下的Firmware.ino文件。
  2. 在代码开头部分,你会看到一系列byte数组的定义,例如byte first_key[32] = { ... };。这些就是预置的密钥。
  3. 仔细地用你刚刚生成并保存的密钥十六进制字符串,替换掉这些数组中的所有内容。确保格式正确,每个十六进制数前都有0x,并用逗号分隔。 例如:将 0x00, 0x01, ... 替换为你的 0xAB, 0xCD, ...
  4. 务必检查:替换后,数组的长度必须和原来完全一致。一个字符的错误都会导致加解密失败。

5.3 自定义其他参数(可选)

在替换密钥的附近,你还可以调整一些参数来个性化你的Midbar:

CPP
# define MAX_NUM_OF_RECS 999 // SD卡最大记录数,可根据需要调整
// EEPROM中登录信息的各字段最大字符数(总和必须为160)
# define MAX_NUM_OF_CHARS_FOR_USERNAME 52
# define MAX_NUM_OF_CHARS_FOR_PASSWORD 52
# define MAX_NUM_OF_CHARS_FOR_WEBSITE 56
// EEPROM中信用卡信息的各字段最大字符数(总和必须为96)
# define MAX_NUM_OF_CHARS_FOR_CARDHOLDER 39
...
uint16_t colors[4] = { 0xb81c, 0xfde0, 0x87a0, 0x041c }; // 界面颜色(紫、黄、绿、蓝)

你可以根据自己的喜好调整字段长度分配(但总和不能变)和界面主题色。颜色是16位的RGB565格式。

5.4 编译与上传主固件

  1. 在Arduino IDE的“工具” -> “USB类型”菜单中,必须选择“Serial + Keyboard + Mouse + Joystick”。这是为了让Teensy能够同时作为串口设备(用于调试)和USB键盘(用于自动输入密码)工作。
  2. 点击上传按钮。
  3. 在编译完成后,Teensy Loader再次弹出时,按下Teensy板上的Program按钮。
  4. 等待上传完成。现在,你的硬件密码保险箱已经就绪。

6. 系统操作指南与核心功能详解

将组装好的设备通过USB线连接到电脑(仅供电),连接好USB键盘,插入格式化为FAT32的Micro SD卡(如果需要使用扩展存储)。设备上电后,屏幕会显示“Midbar Teensy 4.1”和“Press Any Key”的锁屏界面。

6.1 初始化:设置主密码

按下键盘任意键后,系统会提示你设置一个主密码。这是整个设备的“总钥匙”。

  • 重要性:主密码用于派生加密和完整性验证的密钥。它不会被存储在任何地方。忘记主密码,意味着设备内的所有数据将永久无法解密。同时,没有正确的主密码,设备甚至无法解锁进入主菜单。
  • 设置建议:使用高强度、易记忆但他人难以猜测的密码或口令。避免使用生日、常见单词等。
  • 操作:用键盘输入你的主密码,然后按EnterEsc键确认。输入时屏幕可能显示*号或直接隐藏,这是正常的安全措施。

6.2 主菜单导航与基本操作

成功解锁后,你会进入主菜单。操作逻辑非常直观:

  • (下箭头):向下移动光标。
  • (上箭头):向上移动光标。
  • Enter (回车):进入选中的菜单或确认操作。
  • EscBackspace (退格):返回上一级菜单或取消当前操作。

主菜单通常包含:“Logins In EEPROM”(EEPROM中的登录信息)、“Logins On SD Card”(SD卡中的登录信息)、“Credit Cards”(信用卡信息,同样分EEPROM和SD卡)、“Encryption Algorithms”(加密算法工具)、“Other Options”(其他选项,如备份恢复)等。

6.3 EEPROM与SD卡记录管理实操

我们以“登录信息”为例,详解其完整的增、删、改、查流程。信用卡信息的操作逻辑完全相同。

1. 添加记录到EEPROM:

  • 路径:主菜单 -> Logins In EEPROM -> Add -> 选择空槽位 -> USB Keyboard
  • 随后依次输入:Username(用户名) -> Password(密码) -> Website(网站)。
  • 注意:EEPROM只有16个槽位,每个字段的长度受前面#define定义的限制。输入时会实时显示剩余字符数。

2. 从EEPROM查看记录:

  • 路径:Logins In EEPROM -> View -> 选择槽位。
  • 屏幕会分页显示用户名、密码和网站。密码默认是隐藏的(显示为*,这是一个基本的安全特性。

3. 使用“Type”功能自动输入: 这是Midbar最实用的功能之一。当你在电脑上需要登录某个网站时:

  • 在Midbar上导航到对应记录:Logins In EEPROM -> Type -> 选择槽位。
  • 此时,Midbar会模拟成一个USB键盘。将电脑的输入焦点放到浏览器密码框。
  • 在Midbar上按键,它会依次自动输入“网站URL”、“用户名”、“密码”,并自动在输入用户名后加入Tab键切换,在输入密码后加入Enter键提交(具体行为取决于固件实现)。
  • 优势:全程密码不显示在电脑屏幕上,避免了被截屏或远程桌面偷窥的风险。也无需手动敲打复杂密码。

4. 删除EEPROM记录:

  • 路径:Logins In EEPROM -> Delete -> 选择槽位 -> 确认。

SD卡的操作与上述流程几乎一致,区别在于:

  • 容量无限:在Add时,你可以选择任意一个“虚拟”槽位(如001, 002...),系统会在SD卡上创建对应的加密文件。
  • 独立完整性校验:每条记录都有自己的HMAC标签,安全性更高。
  • 编辑功能:SD卡记录支持Edit,可以修改特定字段(如只改密码)。EEPROM记录不支持编辑,只能删除后重新添加。
  • 打印到串口:在View SD卡记录时,多了一个选项可以将解密后的明文(谨慎使用!)输出到串口监视器,方便在无屏幕的极端情况下调试或查看。

6.4 加密算法工具箱的使用

主菜单中的“Encryption Algorithms”是一个独立的工具集,允许你直接使用Midbar内置的7种加密算法(包括那个四重加密链)对任意字符串进行加密和解密。这对于验证加密功能、或者临时加密一段文本非常有用。

加密字符串:

  1. 打开Arduino IDE的串口监视器(波特率通常为9600)。
  2. 路径:Encryption Algorithms -> 选择算法(如3DES+AES+Blowfish+Serpent(CBC)) -> Encrypt String -> 选择输入源(USB键盘或串口)。
  3. 输入你想加密的明文。加密后的密文(十六进制格式)会输出到串口监视器请及时保存,因为它不会显示在屏幕上。

解密字符串:

  1. 确保串口监视器已打开。
  2. 路径:Encryption Algorithms -> 选择之前加密时用的算法 -> Decrypt String -> 选择输出位置(屏幕或串口)。
  3. 根据提示,将之前保存的密文(十六进制字符串)粘贴到串口监视器的输入框,然后点击“发送”。
  4. 解密后的明文会显示在你选择的位置。

实操心得:串口通信的坑 在使用串口监视器粘贴密文时,确保没有多余的空格或换行符。有些串口工具会自动在末尾加换行,这会被当作输入的一部分,导致解密失败。最好在代码中或操作时,明确要求以特定字符(如#)作为结束符,或者使用“Raw Input”模式。

6.5 数据备份与恢复

这是一个非常重要的维护功能。

  • 备份EEPROM到SD卡:路径:Other Options -> Back Up Data From EEPROM -> SD Card。这会将EEPROM中所有加密数据打包成一个名为Midback的文件保存到SD卡根目录。定期执行此操作,可以防止因EEPROM物理损坏或固件错误导致的核心数据丢失。
  • 从SD卡恢复EEPROM:路径:Other Options -> Restore Data To EEPROM -> SD Card。这会读取SD卡上的Midback文件,并将其内容覆盖到EEPROM。注意:恢复操作会覆盖当前EEPROM中的所有数据!
  • 工厂重置:在Other Options菜单中可能还有“Factory Reset”选项。这会清空EEPROM和SD卡上Midbar创建的所有数据,包括备份文件,并将主密码重置。这是一个不可逆的核弹级操作,使用时务必三思。

7. 常见问题排查与深度优化建议

即使按照教程一步步来,你也可能会遇到一些问题。这里我总结了一些常见的坑和解决办法。

7.1 硬件连接与电源问题

问题现象 可能原因 排查步骤与解决方案
屏幕上电无任何显示 1. 电源未接通或接错。
2. 背光(BL)引脚未正确连接。
3. 屏幕损坏。
1. 用万用表检查Teensy的USB口是否有5V输入,3.3V引脚是否有输出。
2. 尝试将屏幕BL引脚接3.3V或GND。
3. 检查SPI引脚(CS, RST, DC, MOSI, SCK)是否连接牢固。
4. 尝试另一个已知好的屏幕。
屏幕显示乱码或花屏 1. SPI通信速率不匹配或干扰。
2. 电源噪声大。
3. 屏幕初始化代码有误。
1. 检查杜邦线是否过长(>20cm),尽量缩短。
2. 在VCC和GND之间靠近屏幕处并联一个10uF和0.1uF的电容滤波。
3. 确认代码中Adafruit_ST7735的构造函数引脚顺序与你的接线一致。
USB键盘无反应 1. USB口接线错误(D+, D-接反)。
2. USB口供电不足。
3. 固件中USB类型未设置正确。
1. 确认USB口的D+(绿)、D-(白)线是否分别接Teensy的24和25脚。
2. 尝试使用带外部供电的USB Hub连接键盘,或换一个功耗更小的键盘。
3. 务必确认Arduino IDE中“USB类型”设置为“Serial + Keyboard + Mouse + Joystick”。
Teensy无法被电脑识别或无法烧录 1. USB线问题(只能充电,无数据线)。
2. Teensy的Bootloader损坏。
1. 换一根确认可以传输数据的USB线。
2. 尝试短接Teensy背面的“Program”引脚(或通过按钮)强制进入Bootloader模式,再用Teensy Loader工具手动烧录。

7.2 软件与功能异常

问题现象 可能原因 排查步骤与解决方案
编译错误,提示库找不到 库未正确安装或路径错误。 1. 在Arduino IDE的“文件”->“首选项”中查看“项目文件夹位置”。确保库安装在正确的libraries子目录下。
2. 尝试通过库管理器重新安装Adafruit相关库。
程序上传后,设备反复重启或卡住 1. EEPROM未清空或内容混乱。
2. 密钥替换错误。
3. 堆栈溢出或内存不足。
1. 首先执行“清空EEPROM”步骤
2. 仔细核对替换的密钥数组,长度和格式必须完全匹配。一个字节错误就会导致解密失败,进而可能引发程序逻辑错误。
3. 尝试在代码中减少一些缓冲区大小或简化菜单,但V3.0版本通常内存充足。
SD卡无法识别或读写失败 1. SD卡未格式化为FAT32。
2. SD卡接触不良。
3. 文件系统损坏。
1. 使用电脑将SD卡格式化为FAT32(注意:大于32GB的卡Windows可能不提供FAT32选项,需用第三方工具)。
2. 重新插拔SD卡,确保完全插入Teensy卡槽。
3. 在电脑上使用chkdsk或磁盘工具修复SD卡。
“Type”功能输入错乱 键盘布局或输入速度问题。 1. 确保电脑的键盘布局(如美式、英式)与Midbar模拟输入时预期的布局一致。代码中可能默认是美式布局。
2. 在固件中,可以尝试在Keyboard.print()语句之间增加短暂的delay(),给电脑系统足够的时间处理按键事件。
完整性验证失败 1. 数据被篡改(极罕见)。
2. 存储介质(EEPROM/SD卡)出现位错误。
3. 加密/解密密钥不一致。
1. 如果发生在SD卡上,尝试将卡内文件备份后,重新格式化SD卡再恢复数据。
2. 如果发生在EEPROM上,尝试从备份恢复。如果没有备份,数据可能已损坏。
3. 最可能的原因:你修改了主密码,或者固件中的密钥被更改,但试图解密用旧密钥加密的数据。密钥必须始终保持一致。

7.3 安全强化与进阶优化建议

如果你不满足于基础功能,这里有一些可以深入探索的方向:

  1. 引入真正的硬件随机数生成器(HRNG):Teensy 4.1没有内置HRNG。你可以外接一个如ATECC608A的加密芯片,它不仅能提供高质量随机数,还能安全地存储密钥,实现真正的“密钥不出芯片”,安全性再上一个台阶。

  2. 增加物理防拆机制:在外壳内部增加一个轻触开关或簧片开关,当外壳被打开时,开关断开,触发程序立即擦除EEPROM中的敏感数据或使主密码失效。

  3. 实现双因子认证(2FA):可以结合一个外接的矩阵键盘或指纹模块,实现“密码+物理令牌”或“密码+指纹”的双重认证,才能解锁设备。

  4. 优化用户界面:目前的导航完全依赖键盘方向键。可以考虑增加一个旋转编码器或几个独立按键,让操作更符合直觉。也可以优化屏幕显示,比如使用更小的字体显示更多信息,或增加电池电量显示(如果改用电池供电)。

  5. 开发桌面端管理工具:通过串口通信,编写一个电脑端的图形化程序,用于批量导入/导出密码(当然是加密后的)、管理记录、更改设置等,提升易用性。

  6. 审计与简化加密链:从密码学工程角度,四重加密链增加了复杂性,但未必按比例增加安全性。你可以研究并测试,是否可以将加密链简化为AES-256-GCM(同时提供加密和完整性验证),在保证安全的同时提升性能和代码可维护性。

这个基于Teensy 4.1的硬件密码保险箱项目,从一个有趣的想法出发,融合了嵌入式硬件、密码学应用和实用主义的安全设计。它最大的魅力不在于使用了多么高深的技术,而在于提供了一种看得见、摸得着、完全受控的数据安全方案。从焊接第一根线,到生成自己的密钥,再到成功存储并自动输入第一个密码,整个过程充满了动手的乐趣和对安全原理的深入理解。希望这份详细的指南,能帮助你成功构建属于自己的那个数字秘密堡垒。