Random USB password manager using digispark

The code for this project was on my Github, but since making it I have replaced it with a more advanced version using an ESP32 module. The ESP has more input pins allowing for more buttons (more complex codes), and is faster (the bootloader is triggered by a button rather than a delay). It also has more memory allowing it to be used for other functions within the same small device.

The ‘digispark’ is a small cheap development board based on an ATTiny85 microprocessor. It includes all the hardware for connection directly to USB, is USB powered, and comes ready flashed with a bootloader that allows programming via avrdude over the USB connection leaving about 8kB of program memory for use. There are libraries available to have the device act as most common USB profiles including HID devices like keyboards, mice, gamepads etc.

We can use the digispark as a keyboard device to type directly into a computer as computers will trust any device plugged in that announces itself as a keyboard. The digispark has 6 input digital input pins, however pin 1 is connected to the on board LED (can be disconnected), and pins 3 and 4 are connected to the USB lines so cannot be used at the same time as USB, leaving us only 3 pins for digital inputs. With a few diodes we can multiplex 6 buttons to the three inputs to make a keypad.

If we want to generate a random character we can use the arduino libraries pseudo random(max,min) function, this will give us a random number between limits (for example for printable ascii characters we could use in passwords we can use 33 and 126). The pseudo random number sequence is initialised by calling randomSeed(seed) with an unsigned long value, commonly a source of randomness is used like an analog read from an unconnected pin but in this case if we can choose a repeatable number then each time we run we will get the same ‘random’ sequence, so by providing known inputs to randomSeed() we can generate sequences of pseudo random ascii characters to be used as passwords and recall them by providing the same seed.

Using a 6 key keypad gives us 6^n different possible codes (where ‘n’ represents the number of digits in the code). So a 4 digit code would give us 1296 possible codes, 5 digits gives us 7776, and 6 gives us 46656 possible. As the random seed is an unsigned long value (2^32) we multiply the inputted code value by an amount to spread the seed value across the full range of possible seeds.

If we just use the number generated from the code then it would be easy to create a wordlist to brute force the generated passwords (even using 6 digit codes the wordlist would only need to be 46656 words), so we can also add some offset to move the seed to a slightly different number – this offset value would need to be added at compile time rather than included in the source to protect it, and could also be changed for different devices to give different passwords for the same codes. Even with the offset we could generate a wordlist for each random seed (there are 2^32 possible seeds). The actual pseudo random sequence used by the arduino libraries is about 2^31 numbers long ( just over 2 billion numbers), so we can increase the complexity further by adding another variable to be set at compile time which will offset where in the sequence we start to generate ascii codes, making brute forcing effectively useless as long as we generate long enough passwords.

(The device is still vulnerable if it’s physically accessed – the code can be read from the chip or the chip can be forced to output all it’s codes by building a circuit to press every key combination in turn).

The device can be plugged in to any USB port and when a password needs to be entered we just type in the code and the device sends the keypresses to the computer and types it for us, we don’t need to remember the complicated passwords only the simple 5 or 6 digit codes, and we can use a different code for different things – each code will always generate its own unique ascii string.