Friday, August 15, 2014

Arduino Leonardo powered password keychain

Welcome to my inaugural blog-post. Recently, I've become infatuated with automating everything in my life. It all started when I discovered Insteon a few years back and proceeded to install their devices throughout the house. My coworkers laugh when they see me check my thermostat or adjust a lighting scene from my phone, but those types of behaviors are becoming increasingly normal now that the Nest, Hue, and even Comcast are pushing into home automation.

My desire to create automated systems led me to the world of Arduino and other microcontrollers. The fun of making your own hardware to go along with software is thrilling to me.

I started with an Arduino Uno, built a few circuits, automated a couple things, and even made my own Arduino on a breadboard. I got into the smaller Arduino boards and clones. Eventually I started to check out the other boards in the Arduino world, which led me on to the Leonardo.

The Leonardo, as compared to the Uno has the ability to act as a keyboard and/or mouse. This has the benefit of being able to send commands from the Leonardo. I immediately saw the benefit in being able to automate my computer, a way to create a macro-like system that I could make portable.

The Leonardo's USB port provides the power and the computer link, so all I need is a case to hold the board, some momentary switches, and a couple of LEDs so I can monitor what's going on.

The major caveat here is that the password, commands, whatever you send from the Leonardo are sent as plain text, as if you were typing at a keyboard. They are not encrypted or otherwise obscured. If someone opens a command line or text editor, they can hit the button and see in clear text your password. For my purposes, as the fob will never be off my person, I wasn't concerned.

After a trip to Ax-Man Surplus (the best place to go for odds and ends, including a wide selection of dirt cheap switches, project boxes, etc.), I raided my supply of plastic boxes, and assembled a desktop password entering machine.

I miniaturized this so that I could take it with me. One advantage of my password in a keychain is that you can create a very complicated password, for example use an RSA key, and adapt it for each site/program/network. For example, at work I can hit my password device, which enters the RSA key and add a number or word that's easier to remember than the corporately mandated password polices that make your password impossible to remember (and then require changing it every fifteen minutes).

Here's my design, my sketch, and some pics of my project:

This is the schematic for a breadboard setup password (or more correctly keyboard emulating) system.

The push buttons are momentary and send the digital inputs to ground. The LEDs are just to monitor the system. I have the red set to be always on, as in "red means ready". The blue is to show that the command is being sent, and remains on during the wait period in my program. So it tells me that I can't hit another button quite yet.

The circuit is pretty dang simple, and even the sketch is pretty basic. The challenge comes in miniaturizing it so that you can carry it with you.

This is my first, desktop ready setup. At about 6 inches wide by 4x4 inches, it definitely isn't pocket-ready. But it did prove the design works, and that I actually will use it.

I had an OKW Minitec enclosure that I wanted to use, as it had a USB passthrough port and keychain loop.

I forgot to take some "before" pictures, but found that a generic "Pro Micro" Arduino clone (which uses the ATmega32u4 as the Leonardo does), with a micro usb adapter fit perfectly.

After cutting down a blank circuit board to fit, I started to assemble to wiring. The case provides ample room, so I could leave enough wire to let me pull it apart as I worked.


As you can see from my mangled up board, this was used in a previous project. My desoldering skills aren't all that great, but they get the job done. Besides, as long as it works it doesn't need to be pretty.

For buttons I wanted something low profile, so putting screw base switches like in my desk-side box was out of the question. I tore into some old remotes to experiment with reusing them. The circuit boards of old IR remotes are excellent sources for IR emitting LEDs and for our purposes here, are an even better source of conductive pad membrane switches.

The pad of buttons you'll find in most remotes is easily cut and each button has a small conductive pad on the bottom. So when the button is depressed, it will connect any two circuits underneath. After experimenting with making my own traces out of wire and solder I discovered that even this was too tall. It interfered with the proper "pop" down and up of the button. I did find that soldering wires through the perfboard and cutting them just flush with the "top" side (that is to say the side on which the buttons will lie) gives enough wire to make the connection. However, I'd recently read about conductive paint and thought that might give a more reliable connection.

Here's my board after being coated with conductive paint in little traces that are to lie under my buttons.

I later added my solder points on the underside of the board and added some more paint into the wired area to ensure a solid connection.

One bit of advice, use a heat gun or a hairdryer on the paint. It says it'll dry in ten minutes, but it didn't. The hairdryer dried it in about a minute, and the label says it makes it stronger. So here's hoping it'll hold up to some abuse.


 I drilled holes for the membrane buttons and inserted them. They didn't want to stay in place, so I attempted to super glue them, but the glue didn't want to hold. So they are held in place by the pressure of the circuit underneath, which works OK. It doesn't end up giving me the fit and finish I want, as the case has a curve to it. So the bottom button (furthest on the left in the bottom picture) is exactly what I was aiming for, the remainder of the buttons slowly start to recess into the case. It doesn't affect the operation, and someday I'm sure I'll figure something out. The perfboard I used is too rigid, so maybe a perfboard that has some elasticity, or cutting some relief joints into it is called for. I'll update the blog if I ever get around to that.

Fully assembled. I took it to the bench grinder and sawed down those dome LEDs so they are now flush with the case. They are plenty bright, so I took a permanent marker to them, so they look just like the buttons, sit flush with the case, and provide a good amount of light to monitor the device by

Here it is plugged in for the first time! The beauty of using a single port for power and communication (both up and down stream) is no wires. I plug it in, and download my sketch to it and can begin using it right away.

You can see how the buttons have recessed (especially the one with the power symbol on it) into the case, as I discussed above.


And here it is, fully operational, transmitting a keystroke(s). The loop on the far right is going to help me put it on a lanyard or a key ring. It's a bit large overall for a pocket, but not prohibitively so.

 I also made one (forgetting to take any pictures whatsoever of my process) out of a slightly smaller keyfob case I had, but this one didn't have room for the full size USB adapter. So it needs it's own cable, but is smaller and much more pocketable.



 Here they are side by side:


Now for the sketch. For your first test, since if you mess this up it'll just continually enter text (into the command line or Arduino IDE), I HIGHLY RECOMMEND changing the delay to something like 10 seconds (add a zero, I use a 1 second delay). This will give you enough time between key commands being sent so you can make sure it's working properly. On my desktop box I go a step further and use a "master" switch by running all of the switch ground leads through a toggle switch. In this way, the master toggle needs to be "on" for me to be able to send the other switches to ground and thus send the commands. It just adds a layer of security, but keep in mind that these commands/passwords are being sent in the clear.

Here's the code to get this working:

"
char* password = "password";                   //place your chosen password within the quotes
char* aptget = "sudo apt-get update && sudo apt-get dist-upgrade -y";          //I use this string to help speed up my server updates

const int buttonPin = 2;                            //These can be changed to whichever pin you want to use
const int buttonPin1 = 3;
const int buttonPin2 = 4;
//const int buttonpin3 = 5;                        //I left this button in for future expansion, so commented it out as it's unused
const int ledPin = 9;                                 //This is your status led, the other one constantly receives power

void setup()
{
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
  //pinMode(buttonPin3, INPUT_PULLUP);
  Keyboard.begin();
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  if (! digitalRead(buttonPin))
  {
    Keyboard.print(password);                   //send the password string from abov
    Keyboard.press(0xB0);                        //sends an enter key press, inputting the password
    Keyboard.release(0xB0);                     //releases the enter key
    digitalWrite(ledPin, HIGH);                //turns on our blue LED
    delay(1000);                                        //waits, so that the computer isn't sent multiple key presses
    digitalWrite(ledPin, LOW);                //turns off the blue LED
  }
  if (! digitalRead(buttonPin1))
  {
    Keyboard.print(aptget);
    Keyboard.press(0xB0);
    Keyboard.release(0xB0);
    digitalWrite(ledPin, HIGH);
    delay(1000);
    digitalWrite(ledPin, LOW);
  }
    if (! digitalRead(buttonPin2))
  {
    digitalWrite(ledPin, HIGH);                             //Turns the blue LED on
    Keyboard.press(0xCA);                                    //Presses the F9 key
    Keyboard.release(0xCA);                                 //Releases the F9 key
    delay(1000);                                                     //delay before the next command is sent, to allow the program time to respond
    Keyboard.print("autossh -X server");               //Enters the string on the command line
    Keyboard.press(0xB0);                                    //Presses enter
    Keyboard.release(0xB0);                                 //Releases enter
    delay(1000);                                                     //Allows the program time to process before we start the next tab
    Keyboard.press(0xCA);
    Keyboard.release(0xCA);
    delay(1000);
    Keyboard.print("autossh -X vboxserver");
    Keyboard.press(0xB0);
    Keyboard.release(0xB0);
    delay(1000);
    Keyboard.press(0xCA);
    Keyboard.release(0xCA);
    delay(1000);
    Keyboard.print("autossh -X torrentbox");
    Keyboard.press(0xB0);
    Keyboard.release(0xB0);
    delay(1000);
    Keyboard.press(0xCA);
    Keyboard.release(0xCA);
    delay(1000);
    Keyboard.print("autossh -X plexserver");
    Keyboard.press(0xB0);
    Keyboard.release(0xB0);
    delay(1000);
    Keyboard.press(0xCA);
    Keyboard.release(0xCA);
    delay(1000);
    Keyboard.print("autossh -X livingroom");
    Keyboard.press(0xB0);
    Keyboard.release(0xB0);
    delay(1000);
    Keyboard.press(0xCA);
    Keyboard.release(0xCA);
    delay(1000);
    Keyboard.print("autossh -X raspi");
    Keyboard.press(0xB0);
    Keyboard.release(0xB0);
    delay(1000);
    digitalWrite(ledPin, LOW);
  }
}
"

- Button 0 sends my chosen password and then presses the enter key.
- Button 1 sends the apt-get update and dist-update commands, so I can quickly move from window to window in my terminal emulator to update all my servers.
- Button 2 shows a much more complicated series of commands. This one, one initiated in my terminal emulator of choice begins opening new tabs, enters the command to ssh into the server, and goes down the line.
- Button 3 is left open for now on my project, but if you read through the code you should be able to add a function to it fairly easily.

I am bad about commenting my code, so I hope it's easy enough to understand.

No comments:

Post a Comment

Search This Blog