【IPFS】`ipfs init` 時に指定できるアルゴリズム【指定可能な暗号鍵・署名鍵の種類】

> [IPFS](https://ja.wikipedia.org/wiki/InterPlanetary_File_System) を初期化する際、`ipfs init` で指定できる署名鍵の暗号アルゴリズムが知りたい。

つまり `--algorithm` オプションの値が知りたいのです。しかし、`ipfs init --help` を見ても、デフォルトは [ed25519](https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%89%E3%83%AF%E3%83%BC%E3%82%BA%E6%9B%B2%E7%B7%9A%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E7%BD%B2%E5%90%8D%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0#Ed25519) としか記載されていません。[「ipfs init algorithm」とググって](https://www.google.com/search?q=ipfs+init+algorithm)みても、「`ipfs init` で初期化します」程度の記載しかなかったので、自分のググラビリティとして。

## TL; DR <sub><sup>（今北産業）</sup></sub>

1. 指定可能な署名鍵のアルゴリズム:
    - `rsa`, `ed25519` の 2 種類（`go-ipfs` [v0.12.2](https://github.com/ipfs/go-ipfs/releases/tag/v0.12.2) 現在）。
1. `-a rsa`/`--algorithm rsa` の場合のみ `-b`/`--bits` オプションで鍵の長さが指定できる。
    - `-a rsa` は [2048 bit がデフォルト](https://github.com/ipfs/interface-go-ipfs-core/blob/master/options/key.go#L7)なため、**RSA を指定する場合は 4096 bit を指定した方が良い**のですが、速度が犠牲になります。
1. 速度・強度の面で、**無指定（デフォルト）の `ed25519` で十分**。
    - [ed25519 は、RSA のキーの長さが 3000 bit の強度と同等](https://ed25519.cr.yp.to/)です。

## TS; DR

IPFS の初期化で作成される秘密鍵・公開鍵を RSA の 4096 ビットで作成する例。

```shell-session
$ ipfs init -a rsa -b 4096
generating 4096-bit RSA keypair...done
peer identity: Qmd68mqs6RBm3T5MmEBehsfUSsT3VcpDCb456bbfKSHRg7
initializing IPFS node at /Users/admin/.ipfs
to get started, enter:

	ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme
```

`ipfs init ...` 時に指定するアルゴリズム名は、基本的に「データの署名」に使われます。ピア同士の通信で、データそのものを暗号化するために使われるわけではありません。

作成された公開鍵・秘密鍵のペアは、公開鍵が「ピアの識別 ID」（`peer ID`）として使われ、秘密鍵が「ピアの署名用」として使われます。

具体的には、`ipfs name publish ...` すると、自身のリポジトリに `add` されているファイルを署名し IPFS ネットワークに通知します。他のピアは、この署名を持ってどのピアが該当 CID を持っているか判断できます。`ipfs add` しただけでは、離れているピアからコンテンツが見つからないのは、署名して通知していないためです。

そのため、`ipfs init` には「署名」に特化した `Ed25519` 暗号を使うのがベストです。そして、特定のピアとだけシェアしたいデータは、別途 RSA 鍵で暗号化したファイルを IPFS を通してシェアするのが妥当です。

:::note info
<strong>2022 年現在、RSA の 4096 bit であれば十分強固である</strong>ものの、RSA 暗号方式は 40 年選手であるため、10 年選手である [EdDSA アルゴリズム](https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%89%E3%83%AF%E3%83%BC%E3%82%BA%E6%9B%B2%E7%B7%9A%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E7%BD%B2%E5%90%8D%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0) の <strong>`Ed25519` を使った署名の方がベター</strong>です。しかし、**相手も `Ed448` のアルゴリズムが使える場合は、`Ed448` がベスト**でしょう。とは言え、いずれを使う場合でも、近い将来スタンダードが変わることが決まっていることに留意します。

`ed25519` による署名は速く、強固なのですが、署名鍵作成時の内部のハッシュ関数に 20 年選手である [SHA-2](https://ja.wikipedia.org/wiki/SHA-2) の `SHA512` を利用しています。SHA-1 および SHA-2 のベースとなる[マークル・ダンガード構造](https://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction)の突破方法は [17 年前に論文で発表されている](https://www.iacr.org/archive/crypto2005/36210017/36210017.pdf)からです。これに耐性のある [SHA-3](https://ja.wikipedia.org/wiki/SHA-3) を内部のハッシュ関数に使っているのが [Ed448](https://datatracker.ietf.org/doc/html/rfc8080) で、`Ed25519` と同じ EdDSA に属します。とは言え、`Ed448` は `Ed25519` より強いとされるものの、実験的要素もあることから、事実上 `Ed25519` の方が[デファクト・スタンダード](https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%95%E3%82%A1%E3%82%AF%E3%83%88%E3%82%B9%E3%82%BF%E3%83%B3%E3%83%80%E3%83%BC%E3%83%89)となっています。 IPFS でも `Ed448` は実装されていません。

留意すべき点は、RSA、`Ed25519`、`Ed448` のいずれであっても、来たる[量子コンピューターの素因数分解能力](https://ja.wikipedia.org/wiki/%E9%87%8F%E5%AD%90%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF#1990%E5%B9%B4%E4%BB%A3)で崩れることが[分かっている](https://datatracker.ietf.org/doc/html/rfc7748#section-7)ため、<strong>近い将来、別の~~暗号アルゴリズム~~署名アルゴリズムに変わる</strong>ことがほぼ決まっていることです。逆に言えば、その時が来たら `Ed448` も変わるため、汎用性・速度・強度を加味すると `Ed25519` が落とし所です。（2022年5月現在）

【2022/07/28 追記】 現在 NIST が行っている、対量子コンピューターのアルゴリズム合戦 "[Post-Quantum Cryptography](https://csrc.nist.gov/Projects/post-quantum-cryptography/post-quantum-cryptography-standardization/round-3-submissions)" の 3 ラウンド目で、電子署名アルゴリズム部門のファイナリストに残った 3 つのうちの 1 つ [CRYSTALS-DILITHIUM](https://pq-crystals.org/dilithium/index.shtml) も[内部で SHA3 を使っていました](https://github.com/pq-crystals/dilithium/blob/9dddb2a0537734e749ec2c8d4f952cb90cd9e67b/ref/fips202.h#L7-L10)。[2024 年に結果が発表される](https://youtu.be/uE_Y1C4QPU8)らしいので、`ed25519` に続く新たなスタンダードが近いうちに決まりそうです。見逃せない！
:::

- 参考文献:
  - IPFSのソースコード: [github.com/ipfs/go-ipfs/config/init.go#L198-L227](https://github.com/ipfs/go-ipfs/blob/d18f1f7ea90288309de593f352e96b085d1b5437/config/init.go#L198-L227) | Commit ID d18f1f7 @ GitHub
  - [Ed25519](https://wiki.archlinux.jp/index.php/SSH_%E9%8D%B5#Ed25519) | SSH 鍵 @ archlinux.jp