使用 Arduino Leonardo 构建的密码保险箱






4.95/5 (15投票s)
如何使用现成组件构建一个简单的硬件密码保险箱和登录系统。
引言
最近我的网站被黑了,原因是我的愚蠢。我以为我使用了安全的密码,但显然不是。这件事让我重新思考我的密码管理策略,我想出了一个非常简单的
基于Arduino的密码管理器。
由于各种原因,它并非一个完整的、商业化的、万无一失的解决方案。它更像是一个概念验证。
硬件
硬件的核心是Arduino Leonardo。Leonardo基于ATMega U32微控制器,具有硬件USB功能。可以选择使用Arduino Due或Yún,因为这些板上的控制器也具有USB功能。
其他Arduino型号不适用。虽然每个Arduino都通过USB编程,但只有上述型号才原生支持USB。在像Uno这样的板上,使用特殊的USB-串口转换芯片,因此它无法模拟键盘或鼠标之类的USB设备。
这里的关键点是键盘模拟。该设备将各种网站的登录密码存储在微控制器的FLASH内存中,只需一键即可将密钥输入到选定的密码框中。该设备就像一个键盘,它会非常快速地将密码字母输入到选定的密码框中。
由于该设备充当键盘,因此该解决方案真正做到了平台无关。它可以在Windows、Linux、OS-X甚至手机和平板电脑上使用,而不管操作系统如何。
对于用户界面,我使用了一个LCD按键面板。它可以从各种网站订购。我从eBay上的中国卖家那里买的。例如,你可以在此处购买:http://www.dfrobot.com/index.php?route=product/product&product_id=51
每个卖家都有自己的版本,因此面板的外观可能会有所不同,但它们的工作方式都相同。
该面板具有与Hitachi HD44780U兼容的16x2字符LCD和5个按钮。LCD可以使用内置的LiquidCrystal库,这很好,因为不需要额外的库。
该面板的另一个优点是按钮。它们只使用一个模拟输入,因为它们像分压器一样连接。
使用代码
软件非常简单。启动时,设备会要求你输入解锁密钥。解锁密钥是面板上的一系列按键序列。它可以在代码中配置,你可以使用任何组合和任何长度。但是只使用了四个按键,因此如果你真的想将其用作一个万无一失的关键保管库,那么我建议使用8次或更多次的按键。
为了预防措施,为了使暴力攻击更加困难,它具有锁定计时器。当输入3个无效的解锁代码时,将启动锁定计时器。它会让你等待30秒,然后才能再次尝试输入代码。你可以通过复位电路板来退出此状态,但这至少需要5秒钟,因为Arduino引导加载程序的原因。
理论上,如果你的解锁代码使用10次按键,那么组合总数为410,即1,048,576。现在,让我们假设你的锁定代码非常强大,因此要破解它,我们必须尝试每个组合。让我们还假设攻击者非常快,可以在1秒内尝试一个组合,但每3个组合他都会被锁定,所以每3个组合至少需要5秒,这意味着理论上他可以在7秒内尝试3个组合。这意味着攻击者至少需要2,446,677秒才能测试所有组合,这相当于28天不眠不休。总之,这意味着如果你的设备被盗,你将有足够的时间更换你的重要密码。
如果成功解锁设备,则可以使用向上和向下按钮选择帐户。按下选择键会将存储的密码发送到计算机。
#include <LiquidCrystal.h> //Unlock key. U - Up, D - Down, L - Left, R - Right char unlock[] = "UUDDLR"; //password descriptions //static storage means it's stored in flash instead of ram static char *desc[] = { "Facebook", "Gmail", "CodeProject" }; //passwords static char *keys[] = { "Password1", "Password2", "Password3" }; //number of passwords and descriptions #define COUNT 3 //----------------------------------------------------------------- int index = 0; #define UP 0 #define DOWN 1 #define SELECT 2 #define RIGHT 3 #define LEFT 4 //Initialize LiquidCrystal lib. LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //waits for a key press and returns it's identifier int ReadKey() { int x = 1023; do { x = analogRead (0); if (x < 60) return RIGHT; else if (x < 200) return UP; else if (x < 400) return DOWN; else if (x < 600) return LEFT; else if (x < 800) return SELECT; } while (x > 800); } //initialize controller void setup() { Keyboard.begin(); lcd.begin(16, 2); //16 chars in 2 rows lcd.setCursor(0, 0); lcd.print("Arduino Keylock"); lcd.setCursor(0, 1); lcd.print("by Webmaster442"); delay(2000); Unlock(); } //Wait for lock code //Blocks further execution void Unlock() { int len = strlen(unlock); char c; int good, bad, i, count, repeat; count = 0; while (1) { c = '-'; good = 0; bad = 0; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Enter unlock key:"); lcd.setCursor(0, 1); i = 0; repeat = 1; while (repeat) { int key = ReadKey(); delay(200); switch (key) { case UP: c = 'U'; break; case DOWN: c = 'D'; break; case LEFT: c = 'L'; break; case RIGHT: c = 'R'; break; case SELECT: repeat = 0; break; } if (unlock[i] == c) ++good; else if (repeat != 0) ++bad; lcd.print(c); ++i; if (i > len) break; } if ((good == len) && (bad == 0)) return; else { ++count; if (count > 2) { //lockdown mode for (int i = 30; i >= 0; i--) { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Stop guessing!"); lcd.setCursor(0, 1); lcd.print("Wait "); lcd.print(i); lcd.print(" Seconds"); delay(1000); } count = 0; } } } } void loop() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Key: "); lcd.setCursor(0, 1); lcd.print(desc[index]); int key = ReadKey(); delay(200); switch (key) { case UP: --index; if (index < 0) index = COUNT - 1; break; case DOWN: ++index; if (index > (COUNT - 1)) index = 0; break; case SELECT: Keyboard.print(keys[index]); lcd.print(" - OK"); delay(1000); break; } }
进一步改进的可能性
该项目可以通过多种方式进行扩展。最重要的改进是使其防篡改。一个好的开始是找到一个适合组件的外壳,一旦放置好,就用双组分环氧树脂填充电子元件。可以选择使用热熔胶,但我并不推荐,因为加热后它会变成液体。
另一种改进的可能性是添加串行SRAM内存用于密码存储。我推荐SRAM,因为你可以实现额外的防篡改机制。例如,一个开关,当有人试图拆卸你的设备时被激活。然后,该开关将SRAM与备用电池断开连接,因此RAM中包含的密码将被销毁。
为了使此功能正常工作,可以制作一个计算机程序,这将使管理密码和帐户变得简单。
一个安全漏洞
此解决方案存在问题。它容易受到软件键盘记录器的攻击,因为它充当键盘。这个问题可以通过不同的密码传输解决方案来解决,但这需要在计算机上使用特殊的软件。
历史
- 2015-04-15:初始版本