LoginSignup
6
6

More than 1 year has passed since last update.

Raspberry Pi Picoを使ってパスコード自動入力機を作る【前編】

Last updated at Posted at 2022-03-23

はじめに (作ろうと思ったきっかけ)

大学のWebサービスのログインパスコードをブラウザで自動生成した結果、非常に長く覚えらづらいパスコードが出来てしまいました。(それ自体は良いこと。)

ところが、自分の端末で入力するときはブラウザによる自動入力があるのでいいものの、学内のパソコンでログインするとき、いちいち手打ちする必要がありました
これがめちゃくちゃ面倒くさい。

てなわけで、自作キーボードの要領でパスコード自動入力機を作れないか構想していました。

Raspberry Pi Pico を選んだ理由

最初は自作キーボードといえばの、Pro Micro を使おうかとも思いましたが、主にマイコンの値段が高いことなどを理由にやめました。
(それのためだけに使うのはコスパ的に見合わないという意味)

そこで目をつけたのが Raspberry Pi Pico (以下、ラズパイピコ) です。
ラズパイピコ自体は発売直後に手に入れていたのですが、使用用途が思いつかず、ずっと寝かしていました。

最近になり、ラズパイピコがHIDデバイス(ヒューマンインターフェースデバイス)として認識させることが出来ることを知りました。
すなわち、ラズパイピコをキーボードとしてパソコンに認識させることが出来るのです。

これは使うしか無い!!

と、思い製作を始めました。

実行環境の選定

ラズパイピコのプログラミングにどのファームウェア(言語)を用いるかについてです。
今回の候補となったファームウェアについてまとめたいと思います。

ファームウェア 言語系 メリット デメリット
C/C++ C/C++ 高速かつ安定 プログラミングが超面倒
MicroPython Python お手軽かつ公式で安心 HIDのライブラリが無い
CircuitPython Python お手軽でありながら発展的 公式環境ではない
Arduino C系 Arduinoライブラリの資産を活かせる 初期設定がちょい面倒

C/C++

まず、C/C++について、プログラム記述方法が非常に複雑かつ面倒で、挫折してしまいました。
コンパイルするので高速かつ安定して動作するので良いのですが、今回は断念。

MicroPython

続いてMicroPythonについて、当初は公式サポートのあるこの環境を用いようとしていました。
ところが、調べをすすめるうちにHIDのライブラリが無いことがわかり、やむなく使用を断念。
ただ、調査という意味でLチカやシリアル通信、ディスプレイ描画などのチュートリアルは行いました。

CircuitPython

そこで代替手段として発見したのが、CircuitPythonです。
軽く調べたところ、このCircuitPythonというのはAdafruit社がMicroPythonを発展させたものとのことです。
そして、こちらのCircuitPython環境下であれば、HIDのライブラリがあります!
よって、今回はこの環境を採用です。

実環境調査

ラズパイピコが2台手元にあったので、以下の写真のようにブレッドボード上にならべて、MicroPythonCircuitPythonの両方を試してみました。

MicroPythonでSSD1306のチュートリアル
IMG_4934.jpg

CircuitPythonでHIDデバイスの実装
IMG_4935.jpg

Arduino

最後にArduino環境についてですが、未だ情報が少ないことや、初期設定が少し手間だということから今回はパスしました。
それ以外にも、この間までM5Stackシリーズの製品をArduinoを使ってプログラミングしまくっていたため、ちょっと飽きたというのもあります(笑)。

これとか↓

これとかも↓

コード

では実際にコードを書いていきます。
パスコードは仮のものとしてABCDEfghij01234としています。
まずは全体像から。

code.py

import usb_hid
from time import sleep
import digitalio
from board import *

from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode

keyboard = Keyboard(usb_hid.devices)

led = digitalio.DigitalInOut(GP25)
led.direction = digitalio.Direction.OUTPUT

#パスコード(例) : ABCDEfghij01234

pass_list = [4,5,6,7,8,9,10,11,12,13,39,30,31,32,33]
big_or_small = [1,1,1,1,1,0,0,0,0,0,0,0,0,0,0]

led.value = True
sleep(2.5)
led.value = False

for i in range(len(pass_list)):
    if big_or_small[i]==1:
        keyboard.press(225)
        sleep(0.01)
    keyboard.send(pass_list[i])
    sleep(0.01)
    keyboard.release(225)

led.value = True
sleep(5)
led.value = False

それでは、コードの説明をしていきます。

ライブラリ

導入したライブラリは全部で6つありますが、前半の4つと、後半の2つに分けられます。

前半の4つ

import usb_hid
from time import sleep
import digitalio
from board import *

これらはCircuitPythonの標準ライブラリです。上から順番に、

  • USB経由でHID認識させるもの
  • スリープ(待機)させるもの
  • GPIOを制御するもの
  • ボードの定義を参照するもの

です。特に設定等なく、記述するだけで利用できます。

後半の2つ

from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode

問題はこれらのライブラリについてです。
これらのライブラリは、ラズパイピコ内のライブラリ格納フォルダ(libという名前のフォルダ)に、ライブラリファイルをコピーしておかなければなりません。

CircuitPythonで利用可能なライブラリは、以下のサイトよりダウンロード出来ます。
CircuitPython Libraries

スクリーンショット 2022-03-04 223511.png

上の画像のように、adafruit-circuitpython-bundle-7.x-mpy-20220304というzipファイルをダウンロードします。
(バージョンは問いません。)

フォルダを展開すると、まずはrequirementsフォルダを開いて、インポートしたいライブラリを探してください。
ライブラリのフォルダを開くと、requirements.txtというテキストファイルがあります。
これを参考に、インポートすべきライブラリを確認します。

ひとつ上の階層に戻り、libフォルダを開き、インポートしたいライブラリを探します。
探したら、それをコピーした後、ラズパイピコ本体のlibフォルダにペーストします。

今回の場合は、adafruit_hidフォルダをそのままコピーすればオッケーです。

これで、ライブラリを利用できます。

定義

keyboard = Keyboard(usb_hid.devices)

led = digitalio.DigitalInOut(GP25)
led.direction = digitalio.Direction.OUTPUT

#パスコード(例) : ABCDEfghij01234

pass_list = [4,5,6,7,8,9,10,11,12,13,39,30,31,32,33]
big_or_small = [1,1,1,1,1,0,0,0,0,0,0,0,0,0,0]

キーボードとLEDの定義

1行目はキーボードの定義
3行目はLEDピンのピン番号の定義
4行目はLEDピンをアウトプットに定義
という流れです。

パスコードをキーコードに変換して変数に保存

adafruit_hid.keyboard.Keyboard Reference

↑のサイトにアクセスし、打ちたいパスコードの文字を1字ずつキーコードに変換していきます。

例えば最初の文字のAを打ちたいとするならば、A = 4 の記述より、pass_listの最初に4を入れます。
ただし、このままだと通常のキーボードと同様に小文字が入力されます。
すなわち、Shiftキーを押して大文字を入力する必要があります。
そこで、big_or_smallという、大文字・小文字を判別するためのリストを用意し、大文字なら1を、小文字なら0を入れることとします。

メインタスク

led.value = True
sleep(2.5)
led.value = False

for i in range(len(pass_list)):
    if big_or_small[i]==1:
        keyboard.press(225)
        sleep(0.01)
    keyboard.send(pass_list[i])
    sleep(0.01)
    keyboard.release(225)

led.value = True
sleep(5)
led.value = False

プログラムの流れとしては、

  1. LEDを点灯する (キー操作準備体制の表示)
  2. 2.5秒待機 (ホスト側に認識してもらうための待機)
  3. LEDを消灯
  4. for文で全文字を入力する
  5. 大文字か小文字かの判定
  6. 大文字ならShiftキー押下(keyboard.press(225))
  7. リストよりキーコードを取り出し、キー送信
  8. Shiftキー押下を解除
  9. LEDを点灯し、実行終了を知らせる
  10. 5秒待機した後、消灯

といった感じです。

実行風景

課題点

セキュリティ面が弱い

例えば誰かに無断で使われてしまった場合、モロにパスワードが流出します。
またCircuitPythonの場合、パソコンにストレージとしても認識されるため、ソースコードが丸見えです。

これらの点から、セキュリティ的にはあまりよろしくない状況です。

スタイリッシュじゃない

このパスワード打ち込みのためだけにラズパイピコをパソコンとMicroUSBケーブルを使ってつなげるというのは、正直スマートでは無いと感じます。
そもそも、今回のプロダクトにおいてGPIOピンは一切必要ないので、もっと小さくて良いのです

解決策

そこで、こんな物を発見しました。

5056-00.jpg

5056-03.jpg

こちらは、Adafruit Trinkey QT2040 - RP2040 USB Key with Stemma QT というもので、Adafruit社が製作しているRP2040搭載ボードです。

すなわち、今回のラズパイピコでの開発を、そのまま移植出来る(はず)なのです。

これなら、小型化でき、なおかつパソコンとの接続に必要なケーブルも要りません!

セキュリティ面についても解決策が出来たので、

次回、こちらのボードを使ってデバイスを完成させたいと思います。

後編の記事はこちら

参考サイト

Adafruit CircuitPython API Reference

Adafruit HID Library

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6