65.9K
CodeProject 正在变化。 阅读更多。
Home

再也不用输入密码了(持续的传奇)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (13投票s)

2018年6月24日

CPOL

15分钟阅读

viewsIcon

21169

downloadIcon

168

制作这个由Arduino驱动的设备,它集成了触摸屏和蓝牙,您将再也不必输入密码。

引言

这是我的展示文章,希望您喜欢并从中获得信息。

首先,我知道我的极端标题(永不输入密码)让很多人觉得夸张。但这就是它的乐趣所在。翻白眼 | :rolleyes:

而且,它真的不仅仅是夸张。一点也不。如果您真的制作了这个设备,您确实再也不必输入密码了。您也不必再记忆密码或凭空编造密码。稍后会详述。

首先,成品设备的照片

首先,让我向您展示我正在使用的Arduino驱动设备,这样我就再也不必输入密码了。

我知道!它很漂亮,不是吗?所有那些美妙的电线!(仅数据线就有8根。呼……)形式遵循功能,您知道的,这个东西确实效果很好。它确实解决了我的问题。

它做什么?

  • 它将通过蓝牙接收您的密码,并将其输入到您的计算机中(用于解锁屏幕或登录)。
  • 它允许您输入设置的PIN码,然后它将您的密码输入到您的计算机中(用于解锁屏幕或登录)。
  • 由于该设备被计算机简单地视为一个键盘,因此无需在计算机上安装任何驱动程序。这太神奇了。这也意味着您可以在Linux、Mac或Windows上使用它,而无需进行任何更改。只需将其插入USB端口即可。

在YouTube上观看它的实际演示

我创建了两个YouTube视频来展示该设备如何解锁我的计算机。

解决CTRL-ALT-DEL以显示登录

我甚至解决了计算机处于“屏幕保护程序”状态的挑战,此时尚未显示登录文本框。该设备可以将**CTRL-ALT-DEL**发送到您的系统以显示登录。如果您使用的是蓝牙,那么在您走到计算机旁时就可以解锁您的计算机。

我讨厌密码:我相信您也一样

这一切的开始是因为我讨厌密码。我真的讨厌。我讨厌记住它们。我讨厌编造它们。我讨厌在小设备(手机等)上只用拇指输入它们。如果我可以告诉您我和我妻子就某个银行账户的密码争论过多少次(“……不要再输错了,否则我们会被锁定的!!!”),您就会真正理解了。微笑 | :)

有一天,我注意到您可以对任何数据进行哈希处理。我在这里CP上写了一篇关于它的文章(销毁所有密码:再也不用记住密码[^]),该文章在一周内获得了超过250,000次观看(现在超过374K次)。哇!这是因为每个人都讨厌密码。但并非所有人都相信我的方法。没关系。我只是喜欢解决问题的方法让我思考一些有趣的想法。

必须在所有平台上可用

那时我决定为自己创建这个东西。没有比创建可用的原型并开始使用它更好的方法来测试一个想法了。但是,如果我要说服其他人使用它,那么**它必须在所有平台上可用**(Android、Windows、iOS、Web)。这花了我一段时间,但我做到了,并将其写成了一篇文章,并通过Github(和CP)将所有代码开源了。请参阅用户讨厌密码(我们都是用户):再也不用记住密码[^],这样您就可以获得Android、iOS、Web和/或WinForm代码。

我每天都使用它,但有一件事需要解决

我每天都使用它,而且一天多次。一旦您使用它,您就会想为什么以前要输入密码。但是,有一件事有点烦人。

如果我没有携带手机或其他运行C'YaPass的设备,我就无法解锁我的计算机(因为密码长达64个字符,我记不住)。

需要解决的烦人问题

如果我有手机,我只需运行Android C'YaPass,生成密码并通过蓝牙发送,我的计算机就会解锁。但这有点麻烦。当我坐到电脑前时,我不想掏出手机和所有那些繁琐的步骤*(WOTD)。

*冗长而复杂的程序

Arduino解决方案的梦想

由于我已经有了这个Arduino设备,它可以(通过蓝牙)为我输入密码,我知道我应该能够简单地添加一个数字键盘之类的东西,它允许我输入一个4或5位数的PIN码,然后设备会为我输入我的长密码,我的计算机就会解锁。

但是,我该怎么做呢?

我知道我可以添加一个数字键盘,但我想要更炫的东西,而且我想尝试使用触摸屏。我开始四处查看,发现您可以花大约16美元购买一个TFT 320x240触摸屏。

工作原理摘要

如果您观看了YouTube视频(上方),您就知道它基本上是如何工作的,但我还创建了一个图形概述,应该能让您快速了解我的设备的作用。

保存按钮:您需要一种方法将密码保存到设备中,以便它可以为您输入。我选择使用Arduino的EEPROM(电擦除可编程只读存储器)。一旦您保存了密码,当您输入正确的PIN码时,Arduino就会将该密码输入到您计算机的登录框中。

发送按钮:当您输入了有效的PIN码后,按下此按钮,Arduino将检查其是否有效,然后将之前存储在EEPROM中的密码输入到登录框中。

PIN码按钮:PIN码按钮允许您随时更改PIN码。当然,第一次使用C'YaPass键盘时,您需要设置值。按下按钮,输入您的4位PIN码,即可开始使用。

CAD按钮:CAD按钮会将**CTRL-ALT-DEL**序列发送到您的计算机,以显示登录文本框,或者如果您已经登录,它将锁定您的计算机。

组件列表

您需要四样主要的东西来构建和运行此项目

  1. Arduino Pro Micro - SparkFun的原始Pro Micro售价20美元,但您可以从Gikfun购买一个仅售7.98美元的克隆品(https://amzn.to/2Ki4kqr)。或者,您可以一次购买几个,价格会更便宜(购买5个@6美元/个https://amzn.to/2Im66VK)。
  2. 320x240 TFT **触摸屏**(https://amzn.to/2tpPKXp)- 一个非常好的触摸屏,并且得到了制造商的良好支持。
  3. HC-05蓝牙模块https://amzn.to/2lAbuf3
  4. USB电缆 - USB 2.0 A公头到Micro B(https://amzn.to/2tA48eX)- 因此您可以将C'YaPass键盘连接到计算机。设备的所有电源都来自您的USB端口。

如果您想制作像我一样的原型,您还需要

  1. 连接线 - 我买了这套非常漂亮的实心芯连接线,非常适合爱好制作:(https://amzn.to/2Ki9y5i
  2. 面包板 - 我购买了多套这样的(https://amzn.to/2Kf4tdX

现在,让我们谈谈我在开发此项目时发现的一些有趣的事情。

为什么使用Arduino Pro Micro?

我们使用的是Pro Micro板而不是Arduino Nano,因为Pro Micro(又名Leonardo)使用不同的ATmega微控制器:32u4,而不是ATmega328P(Nano、Uno和其他许多板子使用的)。

32u4有什么特别之处?

32u4支持Arduino IDE提供的键盘和鼠标库,并且硬件支持HID(人类接口设备)标准,因此当您将其连接到计算机时,计算机将立即将其识别为键盘和/或鼠标。这就是为什么让这个Arduino为您在计算机上输入如此容易的原因。

Arduino为您输入

这是按下屏幕上的[CAD]按钮时运行的代码。

if (b == 14){
     Keyboard.press(KEY_LEFT_CTRL);
     Keyboard.press(KEY_LEFT_ALT);
     Keyboard.write(KEY_DELETE);
     Keyboard.release(KEY_LEFT_ALT);
      Keyboard.release(KEY_LEFT_CTRL);
      Keyboard.write(KEY_RETURN);
   }

b变量简单地保存了按下的屏幕按钮的整数值。

Keyboard.press()Keyboard.release()Keyboard.write()方法都由Keyboard.h库提供,该库与32u4微控制器协同工作。

press()方法被计算机识别为就像在真实键盘上按下按键一样。像这样使用press()release()允许我们模拟按下和释放所有三个按键(**ctrl-alt-del**),然后write()方法发送一个<ENTER>(也称为回车)。

想象一下,您现在可以用它做多少事情!使用32u4微控制器非常容易。

触摸屏代码

现在,触摸屏代码非常直接。它由Elegoo(TFT触摸屏制造商)在其很棒的网站上提供。他们提供了一个不错的基本Arduino程序,可以处理按钮的绘制和按钮按下时的事件。

我采用了该代码并根据我的需求进行了修改。我还将代码分解为函数,以处理可重复的代码。如果您将本文的下载内容与Elegoo的代码^进行比较,您会发现我做了很多更改。

屏幕保护程序:我不确定TFT屏幕图像烧伤

如果您知道Arduino Sketch的设置方式,您会记得它们基本上会无限循环执行loop()方法。

如果loop()结束,那么Arduino程序也就结束了。这类似于旧的Windows SDK消息循环^,您的程序中的所有内容都在其中发生。

好的,在那个loop()中是绘制屏幕上的按钮和文本框的代码。然而,我想让屏幕在不使用时显示为空白。我认为这可以防止按钮图像烧坏屏幕(如果这是必需的,我不确定),而且我认为这样您就不必一直看到那个东西亮着。

我添加了一些代码,用于检查屏幕上次触摸是否已超过10秒,如果超过了,它将用黑色方框填充屏幕。但是,如果屏幕是黑色的,并且您触摸了它,那么屏幕应该为您绘制按钮。

if ((millis() - lastTimeTouched) > 10000){
    if (!needsRefresh){
      tft.fillScreen(BLACK);
      // main screen only needs redraw if the screen save has enabled
      needsRefresh=true;
    }
  }
  else{
    if (needsRefresh){
      DrawMainScreen();
      needsRefresh=false;
      // set the touched point to 0,0 so no button will be mapped
      // since we do not want a button press when the screen had been blank
      p.x = 0;
      p.y = 0;
    }
  }

millis()方法是一个Arduino库方法,它返回Arduino程序启动以来的毫秒数(unsigned int)。我只需在用户触摸屏幕时更新lastTimeTouchedunsigned int)。每当用户触摸屏幕超过10秒时,我就会调用tft库方法fillScreen()并用预定义的黑色值填充它。

我修复的一个bug

起初,代码会在每次循环时用黑色填充屏幕,因为我没有设置一个标志来表示它已经被填充过了。这使得触摸屏对新触摸的响应非常慢,无法再次绘制带有按钮的主屏幕,因此我添加了标志,现在它非常灵敏。

PIN码:存储在EEProm中

接下来我做的有趣的事情是允许用户创建自己的PIN码并将其存储在EEPROM中。提供的库很容易读写EEPROM。但是,您必须自己管理内存,这意味着决定要写入哪个地址以及要写入多少字节。

暂时为4位PIN

目前,我只做一个4位PIN。我将此4位PIN存储在EEPROM地址0(零)处。

哦,对了,EEPROM内存大约可以写入10,000次,所以非常适合这类事情。即使我们每天更改一次PIN码,我们也可以使用27年。此外,EEPROM的量有限,但有1024字节,这对我们来说绰绰有余。4位PIN码只需要4个字节。稍后您将看到我们还存储了您希望CYaPassKeyPad输入的密码到登录文本框,但那也只有64个字节(用于64个字符的密码)。

我只做一个4位PIN,并且我还没有(尚未)强制您验证旧PIN来更改为新PIN。我将尽快实现该代码并在完成时发布。

现在,当您单击**[PIN#]**按钮时,程序将读取您在键盘上输入的接下来的4位数字,并在顶部文本框中显示它们,然后将它们保存到字节数组中。当您输入第4位数字时,程序将自动清除文本框,并将数字写入EEPROM,从地址0开始。

这是处理数字按钮的代码。

if ((b >= 3) && (b < 14) && (b != 12)) {
          if (textfield_i < TEXT_LEN) {
            textfield[textfield_i] = buttonlabels[b][0];
            textfield_i++;
              textfield[textfield_i] = 0; // zero terminate
           if (isPinChanging){
             if (textfield_i-1 < 4){
              pinValue[textfield_i-1] = buttonlabels[b][0];
             }
             if (textfield_i >= 4){
              isPinDone = true;
              writePinToEEProm();
              ClearTextField();
             }
           }
          }
        }

当您按下**[PIN#]**按钮时,isPinChanging标志被设置为true。这意味着在loop()中的每次迭代中,当用户按下数字按钮时,该值将被保存在pinValue字节数组中,以便我们可以将其写入EEPROM。当用户按下第4位数字时,将运行以下代码将数据保存到EEPROM。

void writePinToEEProm(){
  if (isPinDone){
    for (int i = 0;i < 4;i++){
      EEPROM.write(i, pinValue[i]);
    }
    isPinDone = false;
  }
  isPinChanging = false;
}

我只需迭代从0到3的EEPRom地址,并为每个地址写入一个字节(数字键盘值)。

验证用户输入的正确PIN码

一旦PIN码设置好,之后当用户尝试使用PIN码解锁计算机时,程序将从EEPRom读取字节并与最终值进行比较,以确保PIN码正确。

以下方法获取用户在按下**[发送]**按钮之前输入的PIN码,然后读取EEPROM以确定它是否匹配,并向调用者返回一个布尔值,以告知它是否应该为用户输入密码并解锁计算机。

bool verifyPinValue(String pinAttempt){
  String pin = "";
  for (int i = 0; i<4;i++){
    byte value = EEPROM.read(i);
    pin+= (char)value;
  }
  if (pin == pinAttempt){
    return true;
  }
  else{
    return false;
  }
}

您可以看到我再次使用EEPROM.read()来迭代前4个字节。该值与用户的输入进行比较,并返回布尔值。

再一点:EEProm再次解决了问题

最后,在使用CYaPass键盘之前还需要完成另一件事。用户的密码也必须存储在EEPRom中,这样当用户输入正确的PIN码时,设备就可以将密码输入到Windows屏幕的登录框中。

现在,我需要允许用户将其密码存储在EEPRom中。首先,请注意存储在EEPRom中的此值将以明文形式存储,但目前我并不担心,因为这是一个物理设备。

我们必须考虑密码长度

由于您的密码可能长度不同,并且我们必须将字节数写入EEPROM,然后稍后将其读出,因此我们还必须将密码长度写入EEPROM。我们必须这样做,因为当我们检索密码时,我们需要知道何时停止从EEPROM读取字节。EEPROM内存可以初始化为任何值,因此无法知道内存中的内容是否是您想要的值。

我设置了两个#DEFINED

#define PASSWORD_LENGTH 100 // writing password size as a byte at RAM address 100
#define PASSWORD_BEGIN 101 // writing password as bytes begin at address 101

这样我就可以清晰地引用写入密码长度(地址100)和密码第一个字节写入EEProm的地址。

这样,稍后,如果您的密码有17个字符,我就会读取存储在地址100的值,然后知道我需要从地址101开始读取,然后仅读取第一个字节之后的接下来的16个字节。

这有点棘手,因为您必须自己完成所有工作,但我将其放入了一个易于调用的好函数中。

String readPwdFromEEProm(){
   byte pwdLength = EEPROM.read(PASSWORD_LENGTH);
   String pwd = "";
   for (byte i = 0; i<pwdLength;i++){
      pwd += (char)EEPROM.read(PASSWORD_BEGIN + i);
   }
   return pwd;
}

如何存储密码?

现在,我已经使其工作,您只需执行以下操作即可将密码存储在EEPROM中。

  1. 按下CYaPass键盘上的**[保存]**按钮。此时,程序正在等待来自蓝牙设备的数据输入。
  2. 运行Android CYaPass应用程序(与CYaPass键盘配对)并按应用程序中的发送按钮。
  3. CYaPass键盘将接收字节,并将其存储在EEPROM内存中。
  4. 它会在键盘上显示一个小的输出语句,说“Got Serial”。
  5. 再次按下**[保存]**按钮,表示您不再向设备发送要保存在EEPROM中的数据。

再一点

实际上还有另一种方法可以存储您想要的任何密码(而不是CYaPass应用程序生成的密码——尽管您仍然需要CYaPass Android应用程序)。

您只需在Android手机上输入密码,然后选择它并复制到剪贴板即可。

完成后,切换到CYaPass应用程序并按[发送]按钮(带向上箭头的圆圈)。执行此操作时,CYaPass会将剪贴板上的任何内容通过蓝牙发送。这将将其写入CYaPass键盘。

输入密码的终结?

您可能不认为这是输入密码的终结,但希望您同意这是朝着正确方向迈出的一步。我每天都在我的台式机上使用它,而且非常喜欢。

但是,希望您能看到,这篇文章不仅仅是关于销毁密码(尽管我确实想销毁所有密码)。它关于思考如何利用这些强大、小巧、廉价且功耗低的Arduino设备来做一些新事情。

也许您在这里看到的东西会激发您的想象力,并为您提供建造下一个伟大事物的动力。

继续学习,继续建造。

接线图

我忘记添加接线图了。它看起来有点复杂,但实际上很简单。只需按照下图进行连接,然后通过USB端口供电即可。

历史

  • 2018-06-24:首次发布
© . All rights reserved.