基于Arduino的密码管理器设计与实现

在数字时代,密码安全是每个人都必须面对的问题。尽管努力使用复杂的密码,但仍然可能遭受安全威胁。本文将介绍一种基于Arduino的密码管理器,它不仅能够存储和管理多个密码,还能通过硬件模拟键盘输入,提高密码输入的安全性。

硬件选择

密码管理器的核心是Arduino Leonardo,它基于ATMega32U4微控制器,具有硬件USB功能。也可以选择Arduino Due或Yún,因为这些板子使用的控制器同样支持USB原生功能。其他Arduino型号则不适用,因为它们使用的是USB-串口转换芯片,无法模拟键盘或鼠标等USB设备。

为了实现键盘模拟功能,设备将不同网站的登录密码存储在微控制器的FLASH内存中,通过单次按键操作即可将密码输入到选定的密码框中。由于设备模拟键盘输入,因此该解决方案不受平台限制,可以在Windows、Linux、OS-X甚至手机和平板电脑上使用,无论操作系统如何。

用户界面使用了LCD键盘盾,可以在多个网站购买。例如,可以从eBay上的中国卖家那里购买。每个卖家可能有不同的版本,但它们的工作原理相同。盾牌配备了Hitachi HD44780U兼容的16x2字符LCD和5个按钮。LCD可以使用内置的LiquidCrystal库,无需额外的库。

软件编程

软件相对简单。启动时,设备会要求输入解锁键。解锁键是盾牌上的一系列按键操作,可以在草图中配置,可以使用任何组合和长度。但是只有四个按键被使用,因此如果真正想将其作为完整的密钥库,建议使用8个或更多的按键组合。

为了防止暴力破解,设备具有锁定计时器。当输入3个无效的解锁代码时,锁定计时器开始工作,需要等待30秒才能再次尝试输入代码。可以通过重置板子退出此状态,但由于Arduino引导程序的原因,至少需要5秒钟。

理论上,如果解锁码使用10个按键操作,那么总的组合数为4^10,即1,048,576。假设解锁码非常强大,需要尝试每一种组合。假设攻击者非常快,可以在1秒内尝试一种组合,但每3种组合就会锁定,那么每3种组合至少需要5秒,这意味着攻击者在理论上需要至少2,446,677秒来测试所有组合,即28天不眠不休。

如果成功解锁设备,可以使用上下按钮选择账户。按下选择键将存储的密码发送到计算机。

#include // 解锁键。U - 上,D - 下,L - 左,R - 右 char unlock[] = "UUDDLR"; // 密码描述 static char *desc[] = { "Facebook", "Gmail", "CodeProject" }; // 密码 static char *keys[] = { "Password1", "Password2", "Password3" }; // 密码和描述的数量 #define COUNT 3 int index = 0; #define UP 0 #define DOWN 1 #define SELECT 2 #define RIGHT 3 #define LEFT 4 // 初始化LiquidCrystal库。 LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // 等待按键并返回其标识符 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); } // 初始化控制器 void setup() { Keyboard.begin(); lcd.begin(16, 2); lcd.setCursor(0, 0); lcd.print("Arduino Keylock"); lcd.setCursor(0, 1); lcd.print("by Webmaster442"); delay(2000); Unlock(); } // 等待解锁码 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) { 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; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485