Python暗号化ライブラリを用いて仮想通貨ウォレットのセキュリティを強化する!!

 近頃、仮想通貨の盛り上がりと同時に個人ウォレットに対するハッキング事件が散見されます。

直近ではGoogleアカウントが乗っ取られクラウド上に保管していた秘密鍵を窃取され、仮想通貨資産を失うという痛ましい事件が発生していました。

筆者はクラウド上は流石にセキュリティ的に怖いな、という思いがありそういう保管方法はしていませんが、外付けSSDにtxtファイルのまま保管している状態なのでPCにマルウェアなど仕組まれてしまえば盗まれる可能性は全然あります。

一見するとただの通話アプリにマルウェアが仕組まれていて遠隔操作ハッキングされたというケースもあります。

上記のケースからクラウドだろうとローカルだろうと秘密鍵そのまま保管することは想像以上にリスクの高い状態であることが理解できるかと思います。

セキュリティ意識の高い方はハードウェアウォレットを利用したり、マルチシグ機能を活用したり、仮想通貨取引専用のPCを用意する等方法ありますがコストと手間がかかります。

そこで筆者は考えました、手間を増やさずにクラウドやローカル環境にウォレットの秘密鍵を保管するにはどうすれば良いか。

秘密鍵を対称暗号方式で暗号化&復号化できるようにすれば良いのでは、と。


対称暗号方式とは

 簡潔にまとめると下記のような特徴を持っています。
  • 同じ鍵を使ってデータを「暗号化(ロック)」と「復号(アンロック)」する方式です。
  • 送信者と受信者が同じ鍵を共有している必要があります。

  • 処理が高速で、大量のデータの暗号化に向いています。

  • 鍵の管理・共有が難点(盗まれたら安全でなくなる)。

「これじゃあ、管理するパスワードが更に増えるだけじゃん」と一見思われるかもしれません。一理ありますが、鍵に用いるパスワードは憶えやすいフレーズで良いのです。(パスワード単体を知られたとしてもそれが秘密鍵を復号化する鍵と認識されなければ問題ない)

パスワードに関してはクラウドに残すこともローカルに残す必要はなく、忘れそうだったらPCの近くに付箋を貼りメモしておけば良いのです。(秘密鍵を手書きするよりは楽ですよね)

つまり、対称暗号方式を取り入れることで秘密鍵を使途不明の文字列データに変換してクラウドまたはローカルストレージに置くことができ、憶えやすいパスワードを自身の脳内にだけ残しておけばあまり手間をかけることなくセキュリティ的に強固な布陣にできると考えたということです。(とはいってもpasswordリストに載っているような単純なパスワードはよくないです)

対称暗号方式をPythonで実装する

ここからは筆者が作成した対称暗号化&復号化ツールの解説になります。Python(3.6以降)の環境構築ができている必要があります。スクリプトは下記のGithubリンクにあります。

筆者のスクリプトが信用できない場合はChatGPTやClaude等のAIにコードをコピペして解説してもらうのも良いでしょう。

「Don't Trust, Verify」 は仮想通貨という戦場を生き残る上で重要な思想です。

本スクリプトの重要な部分(キー生成、暗号化、復号化)について下記の通りです。

追記(5/26):※下記の解説は旧バージョンのスクリプトの解説となります。現行バージョンはセキュリティ強化のためキー生成プロセスにArgon2を用いており、暗号化プロセスにAES-256-CBC+HMACという構成になっています。

1. キーの生成プロセス _generate_key_from_password関数

パスワード + Salt → PBKDF2(10万回反復) → 暗号化キー

  • Saltを用いることで同一のパスワードであっても出力されるキーはランダムになります。
  • PBKDF2によるパスワードベースの暗号化キーを生成します。
  • 10万回のイテレーションによりブルートフォース攻撃を困難にしています。

2. 暗号化プロセス encrypt_text関数
  1. Salt生成:os.urandom(16)で暗号学的に安全なランダム値を生成します。
  2. キー生成:入力したパスワードとSaltを元に一意のキーを作成します。
  3. 暗号化:Fernetアルゴリズムで平文を暗号化します。
  4. データ結合:Saltと暗号文を結合し暗号文の完成です。
※Saltを暗号文の先頭に付加することで、復号時にSaltを復元できます。


3. 復号化プロセス decrypt_data関数
  1. データ分離:暗号化データからSalt(最初の16バイト)を抽出します。
  2. キー再生成:入力したパスワードとSaltから暗号化時と同じキーを再生成します。
  3. 復号化:Fernetアルゴリズムで暗号文を復号します。

ウォレットの秘密鍵を暗号化&復号化してみよう

本スクリプトの詳細についてはREADME.mdを読めば利用できるように記載はしてありますが、ここではダミーウォレットの秘密鍵を例に基本的な利用方法を解説していきます。

ウォレットを作成する際にニーモニックフレーズや秘密鍵をtxtファイルで保存される方は多いと思います(筆者もそうです)、そのファイルを暗号化&復号化してみましょう。ファイル名を"rabby_secret.txt" と仮定します。保存されている内容はシードフレーズ、秘密鍵のどちらでも良いです。今回は下記のように仮定します。

シードフレーズ:
road light welcome broccoli rug pen blue rough remind mail june camera

秘密鍵:7aa978816d798814eef3310490f79eb51fa51804b71aad54b371f67ce9c51d2c

暗号化の手順

まずはファイルを暗号化してみましょう。ファイルの中身を暗号化するコマンドは下記の通り(pythonスクリプトと秘密鍵ファイルが同一のディレクトリにある場合の書き方になります、パス指定はできます。)
$ python crypto_cli.py encrypt -f rabby_secret.txt

すると、パスワード入力が求められるので入力します。
$ 暗号化用パスワードを入力してください: 
$ パスワードを再入力してください: 

手順に成功すると下記のプロンプトが出力され、ファイル名.encrypted という形式で元の秘密鍵ファイルと同じディレクトリに保存されます。
$ ファイル暗号化完了: rabby_secret.txt -> rabby_secret.txt.encrypted

ちなみに暗号化されたファイルの中身は下図のようになってます。テキストファイルの内容が跡形もなく消えてます。この状態なら中身を見られたところで何の問題もありませんね。

復号化の手順

次に復号化してみましょう。コマンドは下記の通りです。
$ python crypto_cli.py decrypt -f rabby_secret.txt.encrypted

次に暗号化時に入力したパスワードを入力します。
$ 復号化用パスワードを入力してください: 

パスワードが合致すれば下記のプロンプトが出力されます。
  $ 復号化されたファイル: road light welcome broccoli rug pen blue rough remind
  mail june camera

これでパスワードベースによるファイルの暗号化&復号化ができるようになりました!

最後に

筆者が仮想通貨に参入した2017年からビットコインの価格はおおよそ40倍に上昇し、大手企業や各国政府の注目を集める資産となりました。

しかし、ハッキングやGox、保管によるリスクはどうでしょうか、これらの危険性は当時からほとんど変わっていないどころかビットコインの資産価値向上につれて取引所のハッキングだけでなく、個人を狙ったハッキング手法の多様化、高度化したことでむしろ高まっているように感じます。(筆者も数年前に当時の全財産約67SOLをフィッシング詐欺で失った経験があります。)

そこで筆者なりに個人でできる対策はないかと考えたのが今回の秘密鍵暗号化でした。本記事が少しでもハッキング対策の一助になれば幸いです。

コメント