こんにちは。AndGoのハードウェア担当の片山です。

突然ですが,日本の小学校の教室には写真のようなロッカーがあります。実は皆さんの暗号資産はこのようなロッカーの中に入っているのと同じです。鍵がかけられていないので,資産が入っている場所さえわかれば簡単に盗み出すことができてしまいます。

え!?っと思った方も多いでしょうが,小学校のロッカーとの違いはロッカーの個数です。小学校のロッカーは30個程度しかないので,全数探索することができてしまいます。一方でビットコインの場合はロッカーの個数が2の256乗個あります。10進数で77桁の数字となります。もし世界の全人類が貴方のビットコインが入っているロッカーを探そうとした場合に,全員が1ナノ秒に1回調べても宇宙の年齢の10000000000000000000000000000000000000000倍かかりますので,探すことは不可能です。このロッカー一つ一つに割り当てられているのが秘密鍵であり,ビットコインアドレスは秘密鍵から生成されています。

もし秘密鍵が完全に無作為に作られていれば,貴方のビットコインを盗み出すことは事実上不可能ですが,もし秘密鍵に規則性があったらどうでしょうか?

秘密鍵は256bitの情報ですので,硬貨を256回投げて表なら1,裏なら0のように決めていくこともできます(実際にそのように決めることも可能でしょう!)。もしここで,表が出る確率が高かったらどうでしょうか。極端な話ですが,ほとんど256回に1回しか裏がでない硬貨を使っていたとしたら,秘密鍵はほとんど1になりますので,秘密鍵の特定は非常に簡単になります。

皆さんの秘密鍵はどのように生成されているのでしょうか?

プログラミングをされたことがある方なら乱数を使ったことがあると思います。乱数は無作為な数値のことです。C言語の場合は,下記のようなプログラムで乱数を生成することができます。ただし,このプログラムでは実行する度に毎回同じ乱数が表示されてしまいます。

#include <stdio.h>
#include <stdlib.h>
int main(void) {
for (int i = 0; i < 10; ++i) {
printf("%ld, ", random());
}
}
$ ./a.out
1804289383, 846930886, 1681692777, 1714636915, 1957747793, 424238335, 719885386, 1649760492, 596516649, 1189641421,
$ ./a.out
1804289383, 846930886, 1681692777, 1714636915, 1957747793, 424238335, 719885386, 1649760492, 596516649, 1189641421,
$ ./a.out
1804289383, 846930886, 1681692777, 1714636915, 1957747793, 424238335, 719885386, 1649760492, 596516649, 1189641421,

これは,ある計算式をつかって乱数を生成する,疑似乱数という仕組みを使っているからです。実際にはシードというパラメータを現在時刻等を使って決めているので,もう少しまともな乱数になります。それでも,秘密鍵をつくった時刻が分かってしまうと,秘密鍵をある程度推測出来てしまうことになります。

そこで,高いセキュリティを要する用途の場合には擬似乱数ではなく乱数生成器を使います。先日よりご紹介しているSTMicroelectronicsのマイコンにはリング・オシレーターとよばれる仕組みで乱数を発生しています。基本的なリング・オシレーターは奇数個のNOTゲートでできています(▷が3つある図を御覧ください)。NOTゲートとは入力されたデジタル信号を反転させて出力します。入力が1であれば出力が0,入力が0であれば出力は1になります。これを3つ並べてみます。仮に1つ目のNOTゲートの入力が0だったとします。出力は1になります。2つ目のNOTゲートに1が入力され,0を出力します。さらに3つ目のNOTゲートは0が入力され,1が出力されます。この信号は1つ目のNOTゲートに戻ってきますが,1つ目のNOTゲートの入力は0のはずで矛盾します。したがってこの回路は非常に不安定な回路となり,ノイズ等の条件で0になるか1になるかが決まってきます。このリング・オシレーターに乱数の偏りの調整や健全性を自己チェックする仕組みを経由してマイコン内部で乱数を取得することが出来ます。もちろんTrezorでもこの仕組が使われています。

ところで最近,私もUmbrelのブームに周回遅れで乗ってみました。UmbrelはRaspberry Pi上で動作するビットコイン・ライトニングノードです。実はRaspberry Piにも乱数発生器が搭載されています。Raspberry Piに(Umbrelではなく)Raspberry Pi OS(https://www.raspberrypi.org/software/))をインストールすると下記のコマンドで乱数が発生できますのでご興味のある方はお試しください。

$ dd if=/dev/random bs=1 count=256 | od -t x100000
00 e3 ab 66 29 9d 13 52 3d e9 2a 2c c3 a4 23 ce e2
0000020 c4 46 f5 f5 be 03 c1 26 d1 6b d2 6f 8e 0b 4a bc
0000040 91 e6 78 c1 e8 02 4a 6c e1 e8 da 7d 69 c1 9a b3
0000060 a8 ce ba ce 8d 8f d9 d8 9a 23 52 fc 6b b7 e4 6e
0000100 8b f7 be 68 8e 91 11 73 0e ba 5d b3 cf 15 98 96
0000120 7e a6 2f f6 c0 bc f1 c1 5e 9e df 56 95 50 17 ad
0000140 6c 0f 49 ae 78 6c c6 ea bc 0a 7b 59 59 bd d5 18
0000160 af 9b c8 63 50 dd f4 56 09 bc 7d 05 4f a3 4a e9
0000200 65 f2 e6 ab fd af 8f 5c b0 ec f4 a7 f9 ec a9 82
0000220 da 6d bf 58 25 73 74 48 e8 e7 53 99 3b be 23 67
0000240 a7 41 1a a7 66 5c 55 e7 49 c8 7f bf 36 9f d5 f3
0000260 73 95 3b c1 12 16 4c ae 60 60 63 63 f6 c6 72 38
0000300 ad 06 d2 42 bd 89 c3 71 b6 64 63 7a 19 5e fb dc
0000320 6c 9f 2b 2f 25 d4 4a 55 12 36 8b b5 6d 0a 1f e6
0000340 34 49 78 02 81 16 3d a3 8d a2 31 b7 87 f2 a9 67
0000360 86 17 91 c2 79 23 8b d8 18 80 13 70 d5 3b 31 a8
0000400
256+0 records in
256+0 records out
256 bytes copied, 0.00788394 s, 32.5 kB/s