# 暗号鍵

XRP Ledgerでは、[トランザクション](transaction-basics.html)による一連の具体的なアクションの実行が承認されていることを、デジタル署名によって証明します。署名されたトランザクションのみがネットワークに送信され、検証済みレジャーに含まれます。 <!-- STYLE_OVERRIDE: is authorized to -->

すべてのデジタル署名は、トランザクションの送信側アカウントに関連付けられている暗号鍵ペアに基づいています。キーペアはXRP Ledgerでサポートされている[暗号化署名アルゴリズム](#署名アルゴリズム)を使用して生成できます。キーペアの生成に使用されたアルゴリズムの種類にかかわらず、キーペアは[マスターキーペア](#マスターキーペア)、[レギュラーキーペア](#レギュラーキーペア)、または[署名者リスト](multi-signing.html)のメンバーとして使用できます。

**警告:** 秘密鍵のセキュリティを適切に維持することが重要です。デジタル署名は、あなたがトランザクション送信する権限を有していることをXRP Ledgerに対して検証できる唯一の手段であり、レジャーに提出されたトランザクションの取り消しや無効化を行う権限を有する管理者は存在しません。お使いのXRP Ledgerアカウントの秘密鍵があなた以外の何者かに知られた場合、その人物はあなたと同様にデジタル署名を作成し、トランザクションを承認することができます。

## キーの生成

[`wallet_propose`](wallet_propose.html)メソッドを使用してキーペアを生成します。以下は、`wallet_propose`の応答例です。

```
{
  "result": {
    "account_id": "rDGnaDqJczDAjrKHKdhGRJh2G7zJfZhj5q",
    "key_type": "secp256k1",
    "master_key": "COON WARN AWE LUCK TILE WIRE ELI SNUG TO COVE SHAM NAT",
    "master_seed": "sstV9YX8k7yTRzxkRFAHmX7EVqMfX",
    "master_seed_hex": "559EDD35041D3C11F9BBCED912F4DE6A",
    "public_key": "aBQXEw1vZD3guCX3rHL8qy8ooDomdFuxZcWrbRZKZjdDkUoUjGVS",
    "public_key_hex": "0351BDFB30E7924993C625687AE6127034C4A5EBA78A01E9C58B0C46E04E3A4948"
  },
  "status": "success",
  "type": "response"
}
```

この応答には、キーペア（さまざまなフォーマットのシードと公開鍵）と`account_id`が含まれています。

**シード**

_シード_ 値は、アカウントの実際の秘密鍵（および公開鍵）を[導出する](#鍵導出)ために使用されるコンパクトな値です。`master_key`、`master_seed`、および`master_seed_hex`はすべて、同じシード値を表しますが、フォーマットが異なります。これらのいずれのフォーマットも、[`rippled` API](rippled-api.html)や[その他のXRPLソフトウェア](software-ecosystem.html)で[トランザクションに署名](transaction-basics.html#トランザクションへの署名とトランザクションの送信)するときに使用することができます。キーの先頭に`master_`が付いていますが、このシードが表すキーが必ずしもアカウントのマスターキーであるとは限りません。キーペアは、レギュラーキーだけでなく、マルチ署名のリストのメンバーとしても使用できます。

シード値はアカウントのその他のあらゆる情報の基盤であるため、慎重に保護する必要があります。アドレスのシード値を知っている人なら誰でも、事実上そのアドレスを完全に制御できます。

**秘密鍵**

`wallet_propose`応答には、秘密鍵（ _プライベートキー_ とも呼ばれます）の値が明示的に示されていません。トランザクションに署名できるソフトウェアであれば、シード値から[秘密鍵を導出](#鍵導出)可能であると考えられます。

**公開鍵**

`public_key`と`public_key_hex`はいずれも、同一値の公開鍵を表します。公開鍵は、鍵導出の一環として秘密鍵から導出されます。公開鍵を使用すると、トランザクション署名の真正性を検証できますが、それ以上の署名を作成することはできません。

**account_id**

`account_id`は[公開鍵から生成され](accounts.html#アドレスのエンコード)、アカウントがXRP Ledgerに作成される*可能性*を示します。`account_id`が存在していても、`account_id`が最初の XRPでの支払いを受領するまでは、実際のアカウントはXRP Ledgerに存在しません。さらに`account_id`は、資金を供給するトランザクションを受領して、アカウントが作成されるまでは、トランザクションを送信することができません。

ただし、（資金供給されたアカウントのない）`account_id`は、既存の別のアカウントのトランザクションを承認する際に[レギュラーキー](#レギュラーキーペア)または[署名者リストのメンバー](multi-signing.html)として使用できます。

資金供給されたアカウントを作成してレジャーに保管するには、`account_id`が、[必要準備金](reserves.html)を満たすのに十分なXRPを供給する[`Payment`トランザクションを受領する](payment.html#アカウントの作成)必要があります。

`wallet_propose`応答についての詳細は、[`wallet_propose`](wallet_propose.html)を参照してください。

生成されたキーペアは、[マスターキーペア](#マスターキーペア)、[レギュラーキーペア](#レギュラーキーペア)、または[署名者リストメンバー](multi-signing.html)のいずれかとして使用できます。

**キータイプ**

`key_type`フィールドは、このキーペアの生成に使用された[暗号化署名アルゴリズム](#署名アルゴリズム)を示します。[wallet_proposeメソッド][]を使用したキーペアの生成を要求するときに、`key_type`を指定できます。


## マスターキーペア

マスターキーペアは秘密鍵と公開鍵で構成されます。マスターキーペアの秘密鍵は、レギュラーキーペアで署名できるすべてのトランザクションに署名できるほか、以下の操作の実行に使用できる唯一の鍵でもあります。

* [マスター公開鍵を無効にする](accountset.html)。

* [凍結](freezes.html#no-freeze)機能を永久に放棄する。

* トランザクションコストが0の[Key Resetトランザクション](transaction-cost.html#key-resetトランザクション)を送信する。

アカウントのマスターキーペアは、マスターキーペアによるトランザクションへの署名が承認されているアカウントの`account_id`と同じ[`wallet_propose`](wallet_propose.html)応答にて生成されます。マスターキーペアは同じ応答内で生成されるため、アドレスに[固有に関連付け](accounts.html#アドレスのエンコード)られています。このアドレスは、公開鍵から導出されます。

これは、同様に`wallet_propose`メソッドを使用して生成されても、レギュラーキーペアとしてアカウントに明示的に割り当てられる必要があるレギュラーキーペアとは対照的です。レギュラーキーペアは明示的に割り当てられるため、トランザクションの署名が承認されているアカウントのアドレスには固有に関連付けられません。詳細は、[レギュラーキーペア](#レギュラーキーペア)を参照してください。

**注意:** マスターキーペアは変更できませんが、無効にできます。つまり、マスターシードまたは秘密鍵が漏えいした場合は、変更するのではなく、[無効にする](accountset.html)必要があります。

マスターキーペアは変更できないため、漏えいが発生した場合には無効化せざるを得ません。[マスターキーペアをオフラインで保管](offline-account-setup.html)し、代わりにアカウントのトランザクションの署名用にレギュラーキーペアを設定することを強くお勧めします。

マスターキーペアをオフラインで保管する際には、不正使用者がアクセスできる場所にマスター秘密鍵を保管しないようにします。たとえば、インターネットに一切接続されない物理的に隔離されたマシンに保管したり、紙に記入して安全な場所に保管します。一般的には、インターネットと相互にやり取りをするコンピュータプログラムがアクセスできる範囲内には保管しません。マスターキーペアは、緊急時（漏えいの恐れがある場合や実際に漏えいが発生した場合にレギュラーキーペアを変更するなど）に限り、最も信頼できるデバイスでのみ使用することが理想的です。


## レギュラーキーペア

XRP Ledgerでは、アカウントのマスターキーペアをオフラインで保管し、その後のトランザクションには _レギュラーキーペア_ と呼ばれるセカンダリキーペアで署名することができます。レギュラーキーペアのシードまたは秘密鍵が漏えいした場合は、キーペアを削除または交換できます。その際に、アカウントのキーペア以外の設定を変更する必要はありません。これにより、アカウントの設定や他のアカウントとの関係を再設定する手間が省けます。レギュラーキーペアを積極的にローテーションすることも可能です。（アカウントのアドレスに固有に関連付けられているアカウントのマスターキーペアでは、このような操作は実行できません。）

レギュラーキーペアとして使用するキーペアは、[`wallet_propose`](wallet_propose.html)メソッドを使用して生成します。ただし、サポートするアカウントの`account_id`と同時に生成され、それに固有に関連付けられている[マスターキーペア](#マスターキーペア)とは異なり、レギュラーキーペアと、このキーペアがトランザクションの署名に使用されるアカウントとの関係を明示的に作成する必要があります。レギュラーキーペアをアカウントに割り当てるには、[`SetRegularKey`](setregularkey.html)メソッドを使用します。

レギュラーキーペアの割り当てに関するチュートリアルについては、[レギュラーキーペアの割り当て](assign-a-regular-key-pair.html)を参照してください。

レギュラーキーペアを割り当てたアカウントには、次の2つのキーペアが関連付けられることになります。

* アカウントの`account_id`に固有に関連付けられるマスターキーペア。オフラインで保管します。
* アカウントに明示的に割り当てられ、アカウントのトランザクションの署名に使用されるレギュラーキーペア。

レギュラーキーペアをアカウントに割り当てて、[マスターキーペア](#マスターキーペア)で署名されるトランザクションを除く、すべてのトランザクションの署名にそのレギュラーキーペアを使用できます。

レギュラーキーペアはいつでも削除または変更できます。つまり、レギュラーキーペアの秘密鍵が漏えいした（ただしマスターキーペアの秘密鍵の漏えいは発生していない）場合、レギュラーキーペアを削除または変更するだけでアカウントの制御を取り戻すことができます。

レギュラーキーペアの変更または削除のチュートリアルについては、[レギュラーキーペアの割り当て](assign-a-regular-key-pair.html)を参照してください。


## 署名アルゴリズム

暗号鍵ペアは常に特定の署名アルゴリズムに関連付けられています。署名アルゴリズムは、秘密鍵と公開鍵の間の数学的関係を定義します。暗号化署名アルゴリズムには、現在の暗号技術では、秘密鍵を使用して対応する公開鍵を「簡単に」計算できるものの、公開鍵から対応する秘密鍵を計算することは実質的に不可能であるという特性があります。

XRP Ledgerでは次の暗号化署名アルゴリズムがサポートされています。

| キータイプ | アルゴリズム | 説明 |
|-------------|-----------|---|
| `secp256k1` | 楕円曲線[secp256k1](https://en.bitcoin.it/wiki/Secp256k1)を使用する[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) | これはBitcoinで使用されているスキームです。XRP Ledgerではデフォルトでこのキータイプが使用されます。 |
| `ed25519` | 楕円曲線[Ed25519](https://ed25519.cr.yp.to/)を使用する[EdDSA](https://tools.ietf.org/html/rfc8032) | パフォーマンスに優れ、その他の便利な特性を備えた新しいアルゴリズムです。Ed25519公開鍵はsecp256k1鍵よりも1バイト短いため、`rippled`ではEd25519公開鍵の先頭に`0xED`バイトが追加されます。これにより、両方の公開鍵タイプは33バイトになります。 |

[wallet_proposeメソッド][]を使用してキーペアを生成するときには、キーの生成に使用する暗号化署名アルゴリズムを選択するため`key_type`を指定できます。デフォルト以外のキータイプを生成した場合は、トランザクションに署名する際に`key_type`も指定する必要があります。

XRP Ledgerでは、サポートされているさまざまなタイプのキーペアは、マスターキーペア、レギュラーキーペア、署名者リストメンバーとして互換的に使用できます。[アドレス生成](accounts.html#アドレスのエンコード)プロセスは、secp256k1キーペアとEd25519キーペアでは同一です。

**注記:** 現時点では、Ed25519キーで[Payment Channelクレーム](use-payment-channels.html)に署名することはできません。これはバグです。

### 将来のアルゴリズム

今後、暗号技術の発展に対応するため、XRP Ledgerには新しい暗号化署名アルゴリズムが必要になるでしょう。例えば、[Shorのアルゴリズム](https://en.wikipedia.org/wiki/Shor's_algorithm)（または類似のアルゴリズム）を使用する量子コンピューターの実用化が間近となり、楕円曲線暗号が解読される可能性が生じた場合、XRP Ledger開発者は容易に解読できない暗号化署名アルゴリズムを追加できます。2019年半ばの時点で、確実な第一選択肢となる「耐量子」署名アルゴリズムはなく、量子コンピューターはまだ脅威となるほど実用的ではないため、現時点では特定のアルゴリズムを追加する予定はありません。<!-- STYLE_OVERRIDE: will -->


## 鍵導出

キーペアを導出するプロセスは、署名アルゴリズムによって異なります。いずれの場合も、キーは長さが16バイト（128ビット）の _シード_ 値から生成されます。シード値は完全にランダムにする（推奨）か、[SHA-512ハッシュ][ハッシュ]を取得して最初の16バイトを保持することで特定のパスフレーズから導出することができます（[SHA-512ハーフ][]と同様ですが、出力の256ビットではなく128ビットのみを保持します）。

### サンプルコード

ここで説明する鍵導出プロセスは、さまざまなプログラミング言語で複数の場所に実装されています。

- C++: `rippled`コードベース:
  - [シード定義](https://github.com/ripple/rippled/blob/develop/src/ripple/protocol/Seed.h)
  - [汎用キー & Ed25519鍵導出](https://github.com/ripple/rippled/blob/develop/src/ripple/protocol/impl/SecretKey.cpp)
  - [secp256k1鍵導出](https://github.com/ripple/rippled/blob/develop/src/ripple/crypto/impl/GenerateDeterministicKey.cpp)
- Python 3: [このリポジトリのコードサンプルセクション]({{target.github_forkurl}}/blob/{{target.github_branch}}/content/_code-samples/key-derivation/key_derivation.py)。
- JavaScript: [`ripple-keypairs`](https://github.com/ripple/ripple-keypairs/)パッケージ。

### Ed25519鍵導出
[[ソース]](https://github.com/ripple/rippled/blob/fc7ecd672a3b9748bfea52ce65996e324553c05f/src/ripple/protocol/impl/SecretKey.cpp#L203 "Source")

[![パスフレーズ → シード → 秘密鍵 → プレフィクス + 公開鍵](img/key-derivation-ed25519.ja.png)](img/key-derivation-ed25519.ja.png)

1. シード値の[SHA-512ハーフ][]を計算します。32バイトの秘密鍵が導出されます。

   **ヒント:** 32バイトの数値はすべて、有効なEd25519秘密鍵です。ただし、秘密鍵として使用する上で安全なのは、十分ランダムに選択された数値のみです。

2. Ed25519公開鍵を計算するには、[Ed25519](https://ed25519.cr.yp.to/software.html)の標準公開鍵を導出して、32バイトの公開鍵を導出します。

   **注意:** 暗号化アルゴリズムの場合と同様に、可能な場合は必ず、公的に監査された既知の標準実装を使用します。例えば、[OpenSSL](https://www.openssl.org/)には、コア関数であるEd25519やsecp256k1が実装されています。

3. Ed25519公開鍵を示すには、32バイトの公開鍵の前にシングルバイトのプレフィクス`0xED`を付加し、33バイトにします。

   トランザクションに署名するコードを実装している場合は、プレフィクス`0xED`を削除し、実際の署名プロセスに32バイトキーを使用します。

4. アカウントの公開鍵を[base58][]にシリアル化する場合は、アカウントの公開鍵プレフィクス`0x23`を使用します。

   バリデータの一時キーにEd25519を使用することはできません。

### secp256k1鍵導出

[[ソース]](https://github.com/ripple/rippled/blob/develop/src/ripple/crypto/impl/GenerateDeterministicKey.cpp "Source")

[![パスフレーズ → シード → ルートキーペア → 仲介銀行（機関）キーペア → マスターキーペア](img/key-derivation-secp256k1.ja.png)](img/key-derivation-secp256k1.ja.png)

XRP Ledgerアカウントキーでのsecp256k1鍵導出に、Ed25519鍵導出よりも多くの手順が含まれる理由は次のとおりです。

- 32バイトの数値がすべて、有効なsecp256k1秘密鍵であるとは限りません。
- XRP Ledgerのリファレンス実装には、単一のシード値からキーペアのファミリーを導出するための、未使用の不完全なフレームワークがあります。

シード値からXRP Ledgerのsecp256k1アカウントキーペアを導出する手順は次のとおりです。

1. 次のように、シード値から「ルートキーペア」を計算します。

   1. 以下を順番に連結して、合計20バイトにします。

      - シード値（16バイト）
      - 「ルートシーケンス」値（4バイト）。ビッグエンディアンの符号なし整数。ルートシーケンスの開始値として0を使用します。

   2. 連結された（シード+ルートシーケンス）値の[SHA-512ハーフ][]を計算します。

   3. 結果が有効なsecp265k1秘密鍵でない場合は、ルートシーケンスを1増やして最初からやり直します。[[ソース]](https://github.com/ripple/rippled/blob/fc7ecd672a3b9748bfea52ce65996e324553c05f/src/ripple/crypto/impl/GenerateDeterministicKey.cpp#L103 "Source")

      有効なsecp256k1鍵は0であってはならず、 _secp256k1グループ_ の数値順よりも低くなければなりません。secp256k1グループの順序は、定数`0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141`です。

   4. 有効なsecp256k1秘密鍵を使用して、secp256k1曲線で標準ECDSA公開鍵を導出し、ルート公開鍵を導出します。（暗号化アルゴリズムの場合と同様に、可能な場合は必ず、公的に監査された既知の標準実装を使用します。例えば、[OpenSSL](https://www.openssl.org/)には、コア関数であるEd25519およびsecp256k1が実装されています。）

   **ヒント:** バリデータではこのルートキーペアを使用します。バリデータのキーペアを計算する場合は、ここで停止できます。この2つのタイプの公開鍵を区別するには、バリデータの公開鍵の[base58][]シリアル化でプレフィクス`0x1c`を使用します。

2. ルート公開鍵を33バイトの圧縮形式に変換します。

   ECDSA公開鍵の非圧縮形式は、32バイト整数のペア（X座標とY座標）で構成されます。圧縮形式は、X座標と1バイトのプレフィクスのみで構成されます。Y座標が偶数の場合は`0x02`、Y座標が奇数の場合は`0x03`です。

   非圧縮形式の公開鍵を圧縮形式に変換するには、`openssl`コマンドラインツールを使用します。例えば、非圧縮の公開鍵がファイル`ec-pub.pem`にある場合は、次のような圧縮形式を出力できます。

        $ openssl ec -in ec-pub.pem -pubin -text -noout -conv_form compressed

3. 次のように、圧縮されたルート公開鍵から「仲介銀行（機関）キーペア」を導出します。

   1. 以下を順番に連結して、合計40バイトにします。
      - 圧縮されたルート公開鍵（33バイト）
      - `0x00000000000000000000000000000000` (4バイトのゼロ)（この値は、同じファミリーの異なるメンバーの導出に使用することを目的としていましたが、実際には値0のみが使用されます。）
      - 「キーシーケンス」値（4バイト）。ビッグエンディアンの符号なし整数。キーシーケンスの開始値として0を使用します。

   2. 連結された値の[SHA-512ハーフ][]を計算します。

   3. 結果が有効なsecp265k1秘密鍵でない場合は、キーシーケンスを1増やし、アカウントの仲介銀行（機関）キーペアの導出をやり直します。

   4. 有効なsecp256k1秘密鍵を使用して、secp256k1曲線で標準ECDSA公開鍵を導出し、仲介銀行（機関）公開鍵を導出します。（暗号化アルゴリズムの場合と同様に、可能な場合は必ず、公的に監査された既知の標準実装を使用します。例えば、[OpenSSL](https://www.openssl.org/)には、コア関数であるEd25519およびsecp256k1が実装されています。）

4. 仲介銀行（機関）公開鍵をルート公開鍵に追加して、マスター公開鍵ペアを導出します。同様に、仲介銀行（機関）秘密鍵をルート秘密鍵に追加して秘密鍵を導出します。

   - ECDSA秘密鍵は非常に大きな整数値であるため、secp256k1グループ順序を法として2つの秘密鍵を合計することで、2つの秘密鍵の合計を計算できます。

   - ECDSA公開鍵は楕円曲線上の点であるため、楕円曲線の数値を使用して点の合計値を計算する必要があります。

5. 以前と同様に、マスター公開鍵を33バイトの圧縮形式に変換します。

6. アカウントの公開鍵を[base58][]形式にシリアル化する場合は、アカウントの公開鍵プレフィクス`0x23`を使用します。

   アカウントの公開鍵からそのアドレスに変換するための情報とサンプルコードについては、[アドレスのエンコード](accounts.html#アドレスのエンコード)を参照してください。


## 関連項目

- **コンセプト:**
  - [発行アドレスと運用アドレス](issuing-and-operational-addresses.html)
- **チュートリアル:**
  - [レギュラーキーペアの割り当て](assign-a-regular-key-pair.html)
  - [レギュラーキーペアの変更または削除](change-or-remove-a-regular-key-pair.html)
- **リファレンス:**
  - [SetRegularKeyトランザクション][]
  - [AccountRootレジャーオブジェクト](accountroot.html)
  - [wallet_proposeメソッド][]
  - [account_infoメソッド][]

<!--{# common link defs #}-->
{% include '_snippets/rippled-api-links.md' %}			
{% include '_snippets/tx-type-links.md' %}			
{% include '_snippets/rippled_versions.md' %}
