暗号の基本⚓︎
ここでは、NEMの技術を支える基本的な暗号技術の概念を解説します。
ハッシュ⚓︎
- ハッシュ
- 暗号学的ハッシュは、任意のサイズの入力データを固定長の文字列に変換する数学関数 _(ハッシュ関数)_によって生成される文字列のことです。
Keccak や RIPEMD-160 など、複数の関数が存在しますが、いずれも次の共通する特性を持っています。
- 決定性:同じ入力からは常に同じハッシュを生成します。
- 衝突耐性:異なる入力から同じハッシュを作ることは極めて困難です。
- 不可逆性:ハッシュから元の入力データを復元することはできません。
これらの特性により、データの完全性や、真正性の検証、そしてブロックチェーンにおける ブロック の連結が保証されます。
NEM は、鍵導出、アドレス生成、署名、ブロックハッシュに Keccak-256、Keccak-512、RIPEMD-160 を使用します。
NEM は SHA-3 ではなく Keccak を使用します
NEM は SHA-3 として最終決定される前の Keccak を採用しました。 2つのアルゴリズムは異なるパディングを使用するため、同じ入力に対して異なる出力を生成します。 そのため、標準の SHA-3 ライブラリでは NEM の署名を検証したり、NEM のアドレスを再生成することができません。 代わりに、Bouncy Castle などの Keccak 実装が必要です。
NEM の Java ソースコードではヘルパーメソッド名に sha3_256 と sha3_512 を使用していますが、内部ではどちらも Keccak-* を呼び出します。
sha3_ 接頭辞は歴史的なものであり、最終版の SHA-3 仕様を指すものではありません。
キー⚓︎
- 秘密鍵
- 非常に長い数値であり、厳重に秘匿すべき情報です。値そのものに意味はなく、第三者に推測されることは想定されていません。 通常はランダムに生成され、同じキーが偶然に生成されることはほぼありません。
NEM の秘密鍵は 32 バイト長で、通常は64文字の16進文字列で表されます。
- 公開鍵
秘密鍵 に対応する公開識別子として機能する長い数値です。広く共有できますが、秘密鍵を明かすことなく その保有を証明するために利用されます。
秘密鍵から数学的に導出されますが、現在の技術では逆算して秘密鍵を求めることは実質的に不可能です。
NEM の公開鍵は 32 バイト長で、通常は64文字の16進文字列で表されます。
NEM は次の2箇所でキーペアを使用します。
- メインキー
- すべての アカウント に紐付く キーペア です。 秘密鍵はアカウントの所有者を識別し、資金の送金やトランザクションのアナウンスを含む、アカウントの完全な制御権を付与します。
- リモートキー
- すべての リモートハーベスティング アカウントに関連付けられた キーペア です。 アカウントの メインキー を公開せずに、ノードがメインキーに紐付くアカウントに代わってハーベストできるようにします。
キーの安全性
いずれのキーペアでも 秘密鍵 は常に秘密に保つ必要があります。
ただし、秘密鍵が漏えいした場合の深刻度は、その鍵の用途によって異なります。
| キーの種類 | 重大度 | 影響 |
|---|---|---|
| メインキー | 🔴 高 | アカウント内の資産が流出する可能性があります。 |
| リモートキー | 🟠 中 | 委任元アカウントの資金には影響しません。攻撃者が多数のリモートキーを集めると、相当なハーベスティング能力を得て、ブロックチェーンに追加されるブロックに影響を与える可能性があります。別のリモートアカウントをリンクすれば簡単に取り消せます。 |
NEM では、秘密鍵と公開鍵の両方が256ビット(32バイト)の整数です。 公開鍵は 楕円曲線暗号 により、 Ed25519 を使用して取得されます。Ed25519 は ツイステッド・エドワーズ曲線 上で定義されています。
署名⚓︎
署名はアカウントの 秘密鍵 を使って文書を処理することで生成されます。 そのため、対応する公開鍵を使えば誰でも署名が文書と一致することを検証できますが、同一の署名を作成できるのは秘密鍵の所有者だけです。
NEM のすべてのトランザクションには署名が付与されますが、必要な署名はトランザクションの種類と参加者によって異なります。 たとえば、単一所有者のアカウントから別のアカウントへ資産を送る場合、送信元アカウントの秘密鍵の署名だけが必要です。
一方、マルチシグアカウント から資産を送る場合は、マルチシグのしきい値を満たすだけの連署人の承認が必要です。 したがって、有効とみなされる前に複数の署名を集める必要があります。
NEM の署名は512ビット(64バイト)長で、Ed25519 アルゴリズムを使用します。 SHA-512 に依存する標準の Ed25519 とは異なり、NEM は Keccak-512 ハッシュ関数を使用します(NEM は SHA-3 ではなく Keccak を使用します を参照)。
アドレス⚓︎
公開鍵と秘密鍵はいずれも印刷や共有が難しいバイナリデータですが、アドレスは英数字のみで構成されます。
さらに、NEM の鍵には 32 バイトのバイナリデータ、つまり64文字の16進文字が必要です。 一方、アドレスは40文字だけで済み、長さと実用性のバランスを保っています。
NEM では、公開鍵から次の手順でアドレスを取得します。
- 公開鍵に Keccak-256 を適用し、32バイトのハッシュを生成します。
- その結果に RIPEMD-160 を適用し、20バイトのハッシュを生成します。
-
次を連結して25バイトの 生アドレス を生成します。
-
生アドレスを Base32エンコード して40文字の エンコード済みアドレス を生成します。
大文字と数字だけを使用するため、エンコード済みアドレスが最も一般的な共有方法です。
例:
NBHK6WHL5TGBMCLVW4RSFMRO4ZYXCJFRAVO2B4FU -
読みやすくするため、任意で6文字ごとにハイフンを追加し、46文字の 見やすいアドレス にできます。
例:
NBHK6W-HL5TGB-MCLVW4-RSFMRO-4ZYXCJ-FRAVO2-B4FU
アドレスは使用されて初めて追跡されます
NEM がアドレスとそれに対応する公開鍵を追跡し始めるのは、それらがトランザクションに初めて登場した時点です。
バニティアドレス⚓︎
通常、キー及びそれに対応する アドレス はランダムに生成されますが、特定のパターンやプレフィックスを含む バニティアドレス を作ることもできます。
これは、条件を満たすアドレスが生成されるまで キーペア を繰り返し生成する手法です。 求める文字列が複雑になるほど、より多くの時間と計算が必要となります。
バニティアドレスはブランド名や個人の識別などに便利ですが、セキュリティ上の利点はありません。