Bitcoinで使われる技術要素

# Bitcoinで使われる技術要素

ここでは、Bitcoinで使われている技術要素、Hash関連、Base58関連、ECDSA関連（秘密鍵、公開鍵）について簡単に説明したいと思います。
それぞれに、詳しく書いてあるリンクを貼っておきますので、詳しく知りたい方は、そちらを参照願います。

## 1.Hash

Bitcoinで主に使われているHashが、２つあります。
また、それらを組み合わせる事によって、HASH256、HASH160というHashを定義します。

### SHA256

アメリカ国家安全保障局 (NSA)よって設計されたHash
いろいろな言語で実装されています。
ここでは以下のような式で表す事にします。
結果は、256ビットなので、32バイトとなります。

```math
[hash] = SHA256([data])
```

詳しくは、WikipediaはRFCを参照ください。
- [SHA-2 wikipedia](https://ja.wikipedia.org/wiki/SHA-2)
- [RFC6234](https://tools.ietf.org/html/rfc6234)

### RIPEMD160

オープンな学術コミュニティによって開発された為、特許などの問題がないそうです。
SHA1と同等のパフォーマンスを発揮するそうです。
ここでは以下のような式で表す事にします。
結果は、160ビットなので、20バイトとなります。


```math
[hash] = RIPEMD160([data])
```

詳しくは、Wikipediaはspecificationを参照ください。
- [RIPEMD wikipedia](https://ja.wikipedia.org/wiki/RIPEMD)
- [The hash function RIPEMD-160](http://homes.esat.kuleuven.be/~bosselae/ripemd160.html)

Bitcoinでは、これら２つを組み合わせたHashが良く使われます。（一部SHA256を利用する場合もあります。）
ここでは、組み合わせたHashをHASH256とHASH160と定義します。

### HASH256

単純にSHA256を2回おこなったHash値となります。
ここでは以下のような式で表す事にします。
結果は、256ビットなので、32バイトとなります。

```math
[hash] = SHA256(SHA256([data]))
```

私のBitcoin関連の投稿では以下のように表します。

```math
[hash] = HASH256([data])
```

意味は、以下のとおりです。

```math
HASH256([data]) = SHA256(SHA256([data]))
```

### HASH160

最初にSHA256を行い、その結果をRIPEMD160したHash値となります。
ここでは以下のような式で表す事にします。
結果は、160ビットなので、20バイトとなります。

```math
[hash] = RIPEMD160(SHA256([data]))
```

私のBitcoin関連の投稿では以下のように表します。

```math
[hash] = HASH160([data])
```

意味は、以下のとおりです。

```math
HASH160([data]) = RIPEMD160(SHA256([data]))
```

## 2.Base58

### Base58

簡単に言うと、Base64の58文字版です。
Bitcoinで扱う文字列は、次のとおりです`123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`
数値、大文字小文字アルファベットから、「0（零）」「「I（大文字のアイ）」「O（大文字のオー）」「l（小文字のエル）」の58文字となっています。
計算は非常に単純で、まず対象のバイナリを数値にします。
それを58で割り、余りを該当する文字に、その商を次に割る対象とします。
商が0になるまで続けます。
先頭が00の場合、1をその分だけ付与します。

- [Base58 - Wikipedia](https://en.wikipedia.org/wiki/Base58)

例

```text
0x0fffc34b     = 268419915
268419915 / 58 = 4627929 ... 33(a)
  4627929 / 58 = 79791 ... 51(t)
    79791 / 58 = 1375 ... 41(i)
     1375 / 58 = 23 ... 41(i)
       23 / 58 = 0 ... 23(Q)

Qiita
```

```text
0x000fffc34b   = 268419915
268419915 / 58 = 4627929 ... 33(a)
  4627929 / 58 = 79791 ... 51(t)
    79791 / 58 = 1375 ... 41(i)
     1375 / 58 = 23 ... 41(i)
       23 / 58 = 0 ... 23(Q)

00分の1を付与
1Qiita
```

### Base58Check

Base58にチェック機能を付与したものです。
簡単に説明すると、`version+payload`を`HASH256`した値の先頭4byte(`checkcode`)を連結し、
それをBase58で表したものとなります。

- [Base58Check encoding - Bitcoin Wiki](https://en.bitcoin.it/wiki/Base58Check_encoding)

このBase58Checkは、Bitcoinのアドレスとして使われます。
`payload`は、`HASH160`した値なので20byteとなります。
`version`の値によって先頭の文字がある程度決まります。

| version | header symbol | use |
|:---:|:---:|---|
| 0x00 | 1 | Bitcoin pubkey hash |
| 0x05 | 3 | Bitcoin script hash |
| 0x6f | m / n | Bitcoin testnet pubkey hash |
| 0xc4 | 2 | Bitcoin testnet script hash |

例

```text
version:0x6f
payload:0x4da5a6284aedba6eecb14585233041c5952de733

HASH256(version+payload)=0x0cd9d1235644cdd6974de3033ab9f3c27abc6d1a5273b061576bed9125e5915a

checkcode:0x0cd9d123

version+payload+checkcodeをBase58文字列に変換

mnbWmKgU3QvNHWNWjwfyoUHnPKDvc9hqsp

```

## 3.ECDSA

ECDSAとは、Bitcoin上で使われる電子署名である、楕円曲線DSAです。

- [楕円曲線DSA - Wikipedia](https://ja.wikipedia.org/wiki/%E6%A5%95%E5%86%86%E6%9B%B2%E7%B7%9ADSA)

```math
y^2 = x^3 + ax + b
```

Bitcoinでは、`secp256k1`というパラメータを使います。
このパラメータでは、`a=0`、`b=7`としている為、楕円曲線の関数は以下のようになります。

```math
y^2 = x^3 + 7
```
この曲線状の点について、加算を定義します。

```math
P_C(x_3,y_3) = P_A(x_1,y_1) + P_B(x_2,y_2)
```

また、２倍算を定義します

```math
2P_A = P_A + P_A
```
これらを利用して、整数倍算を定義します。

```math
Q = dP \\
dは整数 \\
この時、結合法則が成り立ちます。　\\
d = a + b \\
d,a,b はいずれも整数\\
P_A = aP \\
P_B = bP \\
Q = dP = aP + bP = P_A + P_B \\
```

ECDSAの公開鍵と秘密鍵は、`secp256k1`で定義されている基点`G`を何回（秘密鍵）足したときの点`Q`（公開鍵）となります。

```math
Q = dG \\
秘密鍵:d \\
公開鍵:Q \\
```

これらを、剰余環で扱います。

```math
\begin{eqnarray*}
p &=& FFFFFFFF　FFFFFFFF　FFFFFFFF　FFFFFFFF　FFFFFFFF　FFFFFFFF　FFFFFFFE　FFFFFC2F \\
&=& 2^{256} - 2^{32} - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
\end{eqnarray*}
```

実際のところ、私も内容は理解しておりません。（汗）

### 秘密鍵

基点`G`を`d`回足した時の`d`が秘密鍵で、`32byte`の大きな数値です。

### 公開鍵

秘密鍵の回数分、基点`G`を足した、楕円曲線上の点`Q`

`04`から始まる場合は、x座標(`32byte`)、y座標(`32byte`)の`65byte`

x座標さえあればy座標は計算できるので

`02`又は`03`から始まる場合は、x座標(`32byte`)の`33byte`

の値となります。

`02`、`03`は、y座標が偶数か奇数かの違いです。

---