1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Golang】ECDH 公開鍵から DH 鍵交換で共通鍵を作成する(ディフィー・ヘルマン鍵共有)

Last updated at Posted at 2023-04-03

Go 言語(以下 golang)で、お互いの公開鍵から共通鍵暗号用の共通の秘密鍵を作成したい

つまり「相手の公開鍵」と「私の秘密鍵」をゴニョゴニョして作成された鍵が、相手も「私の公開鍵」と「相手の秘密鍵」でゴニョゴニョして作成された鍵と同じであれば、2 人の「共通の秘密鍵」として利用できるということです。

GPG(GnuPG)でも作成できる鍵で、GitHub に登録できるアルゴリズム(RSA, ElGamal, DSA, ECDH, ECDSA, EdDSA)のうち、 ECDH(楕円曲線ディフィー・ヘルマン鍵共有)を Golang で利用したい。ついでに Golang で ECDH の鍵ペアも作成したい。

ここでは、相手の公開鍵は安全な方法で取得していると仮定します。

というのも、DH 鍵交換であっても中間者攻撃はありえるからです。例えば、取得した相手の鍵の URL が攻撃者に乗っ取られており、相手も、自分も実は攻撃者と共通秘密鍵を作っていたというケースです。

「本当に相手の鍵であるか」は、直面して(物理接触で)公開鍵を事前に交換しておくのが理想です。しかし、オンラインの場合は、複数のソースから総合的に判断することが重要です。CA を利用したり、公開鍵を OpenPGP のキーサーバーGitHub に登録 しておき、KeyoxideKeybase などの活用も検討すると良いでしょう。

TL; DR (今北産業)

Alice と Bob の事前合意
import "crypto/ecdh"

// Alice と Bob が事前に合意した共通パラメーター。この例では NIST P384 の
// 曲線を使用する、とする。
// 選択肢は: P256, P384, P521, X25519
// (悩んだら X25519 が良い。文末の「P521 vs X25519?」参照)
paramCommon := ecdh.P384()
各々の公開鍵暗号ペア鍵作成
import "crypto/rand"

// --------------------------------------------------------------
//  Alice の公開鍵暗号のペア鍵作成
// --------------------------------------------------------------
alicePrivKey, err := paramCommon.GenerateKey(rand.Reader)
panicOnErr(err)

fmt.Printf("Alice Priv: %x\n", alicePrivKey.Bytes())

alicePubKey := alicePrivKey.PublicKey()
fmt.Printf("Alice Pub: %x\n", alicePubKey.Bytes())

// --------------------------------------------------------------
//  Bob の公開鍵暗号のペア鍵作成
// --------------------------------------------------------------
bobPrivKey, err := paramCommon.GenerateKey(rand.Reader)
panicOnErr(err)

fmt.Printf("Bob Priv: %x\n", bobPrivKey.Bytes())

bobPubKey := bobPrivKey.PublicKey()
fmt.Printf("Bob Pub: %x\n", bobPubKey.Bytes())

// 作成例 (作成するごとに変わる):
// Alice Priv: 0fd7557d2dfd4dedc0b659ac8416333f97900cb1dab53720a66c7adea2b36f88e5a3f3eef490f9b48e66a7d8112c6f3d
// Alice Pub: 044806f4f84614189cc049e282696661516309f75ef20fbaf0cebd2fd4fc2bc2b3f19a25f550a2baefc350861ba470e0fee36478986571e46ba98862a7b2c55b904fc97079b899ec1195052f309d693598ea1ec13d53a6540b8ce640403f6a899d
// Bob Priv: 1ab739460d9e9b18fa5f5494c7667d4f929bb50e79144a6e5dc9549134fe7e1b4ac3eb0af926ab957c019ec16ba1be08
// Bob Pub: 04b742944773613e81b8b84c940e0a6b70d5b1ce9f453311a289bddff8812ed463fed7d246c5915bf777f209a2057ad27afe2dd2cd149d52f499bad1f085f92c590c5004878cdc621056010906b5e3ebf8b7fe3da3a46efee8bd1c09c44d7cf345
各々の共通秘密鍵の生成
// Alice が、自分の秘密鍵と相手(Bob)の公開鍵で 2 者間の共通秘密鍵(aliceSecret)
// を作成。
aliceSecret, err := alicePrivKey.ECDH(bobPubKey)
panicOnErr(err)
fmt.Printf("Alice's Shared Secret: %x\n", aliceSecret)

// Bob が、自分の秘密鍵と相手(Alice)の公開鍵で 2 者間の共通秘密鍵(aliceSecret)
// を作成。
bobSecret, err := bobPrivKey.ECDH(alicePubKey)
panicOnErr(err)
fmt.Printf("Bob's Shared Secret  : %x\n", bobSecret)

// 作成例:
// Alice's Shared Secret: f2d46357b7deab81ea3c068e8c3430ab03f3851c6e6dd7790e26e831bcae73b307d69950e22b5677205aafcdc13c138b
// Bob's Shared Secret  : f2d46357b7deab81ea3c068e8c3430ab03f3851c6e6dd7790e26e831bcae73b307d69950e22b5677205aafcdc13c138b

P521 vs X25519?

ECDH の鍵交換には X25519 を選ぶべし

上記「Alice と Bob の事前合意」で、パラーメータの選択肢にある P256 や P384 などの数値は、内部の計算で使われる素数(メルセンヌ素数)を定めたものです。

  • P256 = $2^{256} – 2^{244} + 2^{192} + 2^{96} – 1$
  • P384 = $2^{384} – 2^{128} – 2^{96} + 2^{32} – 1$
  • P521 = $2^{521} – 1$
  • X25519 = $2^{255} - 19$

そして "crypto/ecdh" のパッケージは、以下の仕様を元に実装されています。

上記の、仕様の制定者と制定年に注目ください。前者の FIPS 186-3 は 2009 年に制定されたものの、2013 年に後続の FIPS-186 シリーズ(Digital Signature Standard, デジタル署名標準)にバトンを渡しました。

2024/03 現在、FIPS 186-5(2023/02 制定)が最新なのですが、そこでは Ed25519 がデジタル署名アルゴリズムとして選ばれています。

Golang では Go v1.13 移行から "crypto/ed25519" パッケージで標準実装されていますが、あくまでもデジタル署名を行うためのパッケージに特化しているので、鍵共有の関数は持っていません。

では、同じ 25519 を持つ Ed25519 を使ったものが ECDH の X25519 なのかと言うと 25519 の数値が同じだけで別ものです。

X25519Ed25519 の共通点と違い

  • 共通点
    • どちらも Curve25519 と呼ばれる楕円曲線を利用している
  • 違い
    • 用途
      • X25519: ECDH の鍵交換プロトコルに準拠させた Curve25519 を使った実装。つまり、DH 鍵交換用
      • Ed25519: EdDSA のデジタル署名アルゴリズムのうち Curve25519 を使った実装。つまり、デジタル署名用
    • 制定者

以上から、特別な事情がない限り、これから DH 鍵交換を "crypto/ecdh" のパッケージで利用する場合は X25519 一択ということになります。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?