做了一个用于登录 SSH 的 USB Key,成本低至 9.9 元

2022-01-26 22:47:01 +08:00
 44670
由于直接用密码不方便并且不安全,相信很多人都会配置使用公私钥来登录 SSH 主机。
然而,直接在电脑里存储私钥文件实际上是非常不安全的:电脑上任何一个能读取用户目录的软件都有可能偷走私钥然后做坏事。
比较可信赖的方式是做一个专门的 USB Key 设备,实现 SSH 登录时用到的公私钥认证算法,这样一来电脑上就不会存储私钥了。
YubiKey 支持 SSH 登录,但是除了价格问题以外,另一个问题是 YubiKey 对 SSH 登录的支持不是原生的,在 Windows 下需要依赖 Windows Crypto API/SmartCard API 这些黑箱,其它平台上也需要 OpenPGP 这样的软件套一至多层实现,配置起来可能会很复杂并且总觉得不够可靠。

所以我觉得有必要自己做一个专门用于登录 SSH 的 USB Key ,并且尽量简化功能和降低成本。

基于以下几点原因,最后选择了 ESP32/ESP32-C3 芯片:
1. ESP32 系列自带安全启动、存储加密功能,一定程度上可以防止硬件上的秘密被物理读取。
2. 价格非常便宜,目前淘宝上卖得最多的一家 ESP32-C3 开发板只需 9.9 元(限购 10 件)。
3. 有 WiFi/BLE 功能,未来或许可以做成无线的。

已经在 ESP32 开发板上测试通过,几乎所有的 ESP32/ESP32-C3 开发板都可以直接使用。

也在计划做自己的硬件,打算提供一个带灯的按钮,用户按下物理按钮可以确认登录操作。

PC 端用 Go 实现了一个 ssh-agent ,可以转发 SSH 身份认证请求到设备端、由设备端完成签名操作。

特点:
1. 设备端只专注 ed25519 签名一件事情,代码<1K LOC (不含第三方库),容易审计。
2. 私钥完全在设备端产生,不会传递到外部,不依赖 Windows Crypto API/SmartCard API 之类的黑箱。
3. 私钥通过 SHA256 算法,结合设备端存储的随机种子+用户密码产生。设备本身不存储 /验证某个特定的用户密码,用户每次输入不同的密码即可以直接使用不同的 ed25519 公私钥对。
4. 使用外部的独立 USB 转串口芯片,避免软件 USB 协议栈的潜在漏洞影响设备的安全性。
5. 可以通过单一的 Go 写的工具,实现设备的初始化、ssh-agent 等全部功能,不需要安装额外的软件。

使用方法:
1. 安装 ESP-IDF 环境、构建 44Key 项目后刷入任意一个 ESP32/ESP32-C3 开发板里。
2. 运行 44KeyTool -port COMx -format ,初始化设备。需要在键盘上随便输入些字符,用于给设备端生成随机种子提供一部分熵。(在设备管理器里确认具体的串口号,替换 COMx )
3. 运行 44KeyTool -port COMx ,输入自己的密码后,即可开启 ssh-agent ,此时终端会显示输出公钥。
4. 把公钥添加到目标服务器的~/.ssh/authorized_keys ,下次就可以直接用 USB Key 登录啦。

项目地址:
硬件(准备中): https://oshwhub.com/44670/miniusbkey
固件: https://github.com/44670/44Key
PC 端软件: https://github.com/44670/44KeyTool

目前是一个可以在 Windows 上工作的原型,实现了 SSH 认证所需的全部功能,不过安全启动和存储加密还没默认启用。

欢迎提供各种想法!
10679 次点击
所在节点    分享创造
103 条回复
44670
2022-01-27 12:58:54 +08:00
@ysc3839 PL2303 是真的垃圾,厂商自己在上传 Windows Update 的驱动里下毒淘汰旧芯片,也没人管管。

以后再也不会用这家公司的产品。
adoal
2022-01-27 13:21:21 +08:00
@44670 但是看 C3 的 spec 里的说法,它的 CDC uart 好像是芯片内置的,而且是单一的 CDC 功能,所以可能并不是 SDK 里的软件实现
44670
2022-01-27 13:26:40 +08:00
@adoal C3 有两个 USB 硬件(不过只能同时使用一个),一个是硬件 USB JTAG+CDC ,另一个是给软件协议栈用的。

第一版硬件我用的是自带的 USBCDC ,然而它的问题非常多,在很多情况下都有可能把上位机或者下位机陷入死锁的状态。

那个 USB CDC 是用一个 FIFO 和 MCU 通信的,然而那个 FIFO 不管是空了还是满了都会把上下两端堵死。

所以下一版硬件我还是换成了外挂芯片的方案(这大概也是淘宝上的 ESP32-C3 开发板、包括乐鑫官方的,都用了独立 USB-UART 芯片的原因)。
44670
2022-01-27 13:27:07 +08:00
@44670 说错了,C3 只有一个 USB CDC ,S3 有两个。
lucifer9
2022-01-27 14:09:21 +08:00
@44670 #38 几周或者一个月输入一次还行吧,还省得长时间不用自己都忘了
lingex
2022-01-27 14:20:47 +08:00
XC6206 额定 200mA,
C3 WiFi 发送时最大要求 350mA, 未来扩展可能不太够哦
iamwho
2022-01-27 14:25:34 +08:00
把 ssh key 存入 keepass ,成本低至 0 元。
44670
2022-01-27 14:30:02 +08:00
@lingex 好像是的!有好用的 LDO 推荐么?

@iamwho 这个好像和之前提到的加 passphase 存储私钥没有区别。
xuboying
2022-01-27 14:44:26 +08:00
这个思路很 cool!
但是如果只是用来做 sshkey 认证,和已经使用了 2FA 的 ssh 认证相比,是不是并没有提高太多安全性?
有没有别的地方可以应用这个技术?
lingex
2022-01-27 14:54:27 +08:00
@44670 #48 可以换 SPX3819 500mA
hihanley
2022-01-27 15:00:06 +08:00
持续关注
leavic
2022-01-27 15:02:46 +08:00
我不用这类玩意的原因是不能备份,一旦硬件损坏极其操蛋。
44670
2022-01-27 15:18:34 +08:00
@lingex 目前暂且换成了 JLC 可以贴片的 AMS1117 ,
sipex 的怎么样,容易坏么?
44670
2022-01-27 15:20:17 +08:00
@xuboying 我也是第一次看到 ssh 也可以用 2FA ,但是感觉这样有点多余并且似乎没有解决问题(仍然是 Secret 明文存储在设备上,不过变成了多个)
starqoq
2022-01-27 15:26:19 +08:00
而且你买到的 CH343P 绝大部分是山寨的。没错,山寨芯片,只能用旧版驱动,一更新驱动就不工作了。
lingex
2022-01-27 15:30:35 +08:00
@44670 #53 我用来给双核的 ESP32 供电,用了 4~5 片,还没碰到过坏的。
agagega
2022-01-27 15:32:46 +08:00
比较合理的验证方式是硬件 Key+二次验证( Windows Hello/Touch ID )
44670
2022-01-27 15:36:19 +08:00
@agagega 可以在设备上做一个按钮,对登录操作进行二次确认。

@starqoq 有山寨的是 CH340 、CH343P 是最近新出的芯片。
dreampet
2022-01-27 15:37:40 +08:00
还有一个方案:
使用 ESP-8266 模块(比如,ESP8266-12F 价格 6 元), 然后通过软件协议栈( https://github.com/cnlohr/espusb)模拟 USB HID 协议,直接免驱使用
xuboying
2022-01-27 15:38:48 +08:00
@44670 #54 你启发了我考虑使用 TPM2.0 作为 sshkey 存储。https://donjon.ledger.com/ssh-with-tpm/

不管大家的需求如何,还是很赞赏你的思路,在程序员眼里感觉搞硬件很牛!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/830808

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX