[Bitcoin]自分でビットコインアドレスを作ってテスト送信してみた

ついに日本の取引所でも1ビットコイン(1BTC)が100万円を超えましたねー:grinning:
私も出会った頃にガッツリ保持していたら今頃 ”おくりびと” になってたのかぁ・・・、
なんて事を考えながら相変わらず社会人してます。

はい、今回はビットコインの基礎「ビットコインアドレス」について試したことを書きます。

## ビットコインアドレスとは
ビットコインは仮想通貨の一種で、実際のコインや紙幣などは存在しません。
代わりに「アドレス」と呼ばれるものを送り先として利用して、仮想通貨の所有権を譲渡・管理します。
AさんのアドレスからBさんのアドレスへ1BTCを送信する、という感じにコインの所有権を譲渡してお金のように管理するわけです。
そしてこのアドレスの正体は「**公開鍵と秘密鍵**」のペアなのです。

具体的には「楕円曲線暗号」という方式で生成された鍵のペアで、秘密鍵はビットコインの所有権を証明する唯一の手段なので、絶対に他人に盗まれたり渡してはいけません。
**万一、秘密鍵を紛失した場合はこれまで所有していたビットコインは永久に利用できなくなります。**
そのためアドレスの秘密鍵は二重三重のバックアップが推奨されています。

## ビットコインアドレスの生成手順
アドレスは公開鍵を利用して、以下の手順で生成します。

>
1.　公開鍵をSHA-256でハッシュ化する
2.　1のハッシュ値をRIPEMD-160でハッシュ化する（[RIPEMD-160とは](https://bitflyer.jp/ja-jp/glossary/ripemd160)）
3.　2のハッシュ値の前にVersion Prefixを付与する（[Version Prefix](https://en.bitcoin.it/wiki/List_of_address_prefixes)は通常00を設定）
4.　（Version Prefix + 2のハッシュ値）をSHA-256でハッシュ化する
5.　4のハッシュ値を更にSHA-256でハッシュ化する
6.　5で得られたハッシュ値の先頭4バイトをChecksumとし（Version Prefix + 2のハッシュ値）の末尾に付与する
7.　（Version Prefix + 2のハッシュ値 + Checksum）をBase58エンコードする

このようにして、ランダムなアドレスが生成されます。
ウーーン、文章だけで書くと分かりづらいですね、、但しここでは雰囲気だけ伝われば大丈夫です。

## ビットコインアドレスを生成する
最初にopensslを利用して、秘密鍵を作ります。
ビッットコインアドレスは「楕円曲線暗号」である必要があるため、「secp256k1」パラメータを付与した秘密鍵を作ります。

```bash:ターミナル
$ openssl ecparam -genkey -name secp256k1 -out privkey.pem
```

privkey.pemという秘密鍵が作られ、catで中身を確認できます。
「BEGIN EC PRIVATE KEY」と「END EC PRIVATE KEY」の間の文字が秘密鍵です。

次にprivkey.pemとペアの公開鍵を作り、その公開鍵から「ビットコインアドレスの生成手順」に則りアドレスを生成するのですが、アドレスの生成手順を自分で実装すると面倒なので、[bitcore-lib](https://github.com/bitpay/bitcore-lib)というJSのライブラリを利用します。

## bitcore-libを利用する
bitcore-libはnode.jsなので、nodeが利用できる環境が前提です。
このライブラリを利用する事で上記の「ビットコインアドレスの生成手順」を良しなにやってくれるはずです。
以下のコマンドでインストールします。

```bash:ターミナル
$ npm i bitcore-lib
```
次にインストールしたbitcore-libを利用して、先程の秘密鍵から公開鍵を生成してみます。
**（opensslで作成した秘密鍵を利用せずともbitcore-libだけで全て完結できますが、今回はお試しということで色々回りくどい事をしてます。予めご了承下さい）**

その前に、秘密鍵を利用しやすいように以下のコマンドで16進数表記で出力します。

```bash:ターミナル
$ openssl ec -in privkey.pem -outform DER | tail -c +8 | head -c 32 | xxd -p -c 32
```

次にJSファイルを作成してnodeで実行します。

```js:get-pubkey.js
var bitcore = require('bitcore-lib');
var network = 'livenet';//ここはlivenet固定で大丈夫
var privkey = '上記で出力した秘密鍵の16進数';
var privateKey = new bitcore.PrivateKey(privkey, network);
var publicKey = privateKey.toPublicKey();
console.log(publicKey.toString());
```
```bash:ターミナル
$ node get-pubkey.js
```
ターミナルに秘密鍵から生成した公開鍵が出力されるはずです。
次はこの公開鍵から、アドレスを生成します。

```js:get-bitcoin-adr.js
var bitcore = require('bitcore-lib');
var network = 'livenet';//ここはlivenet固定で大丈夫
var pubKey = '上記で出力した公開鍵';
var publicKey = new bitcore.PublicKey(pubKey, network);
var address = publicKey.toAddress();
console.log(address.toString());
```
```bash:ターミナル
$ node get-bitcoin-adr.js
```

いよいよビットコインアドレスが生成されました。
上記のget-bitcoin-adr.jsで出力された値がこれです。

> **1Cq1NmLviboV4WWBnJmvrYgsQzQgS47EXE**

つまり、これが新たに生成されたビットコインアドレスです。

## アドレスにビッットコインを送信してみる
それでは生成したアドレスに本当にビットコインが送れるのか、テスト送信してみます。
テスト送信はビットコインを取り扱う取引所[*Zaif*](https://zaif.jp/)を利用します。

*Zaif*へログインして、生成したアドレス宛てに「0.001BTC」を送信します。
（*Zaif*送金画面の一部）
![スクリーンショット 2017-11-26 23.09.40.png](https://qiita-image-store.s3.amazonaws.com/0/84601/94e5f599-4f94-8dea-0d41-d1de678c881c.png)

出金ボタンを押下して、処理が完了するまでしばらく待ちます。

## ビットコインの送信を確認する

本当にアドレスへビットコインが送信されたか、ブロックエクスプローラーというサービスで確認します。
最初は残高が「0」ですが、マイニングが完了するまでしばらく待ち、再度確認すると先ほど送信したビットコイン「0.001」が残高として確認できました。

![スクリーンショット 2017-11-26 23.23.37.png](https://qiita-image-store.s3.amazonaws.com/0/84601/10cd2b71-968e-04c5-e74d-22577fc6f2e8.png)

## さいごに
bitcore-libを利用すれば、簡単にビットコインアドレスが生成できます。
アドレスの生成だけでなく送信なども簡単に実装できるので、ビッットコインウォレットなんかも作れそうです。
くどいようですが、アドレスの生成に利用した秘密鍵は他人に教えたり、紛失したりしないよう厳重管理する必要があります（捨てアドレスなら別によいですが）。

### 参考にしたサイト - Special Thanks.

- [Qiita - ビットコインのアドレス生成の仕方](https://qiita.com/you21979@github/items/5d3bd71ae2107d03973a)

- [堅牢なスマートコントラクト開発のためのブロックチェーン［技術］入門](http://gihyo.jp/book/2017/978-4-7741-9353-3)

それでは、以上です。