こぼれネット

ECDHを簡易プログラムで試してみた件

ECDHの検証プログラム

package main

import (
	"crypto/ecdh"
	"crypto/rand"
	"crypto/sha256"
	"fmt"
)

// 公開鍵(生バイト)と派生鍵をやり取りするためのチャネル
var (
	pubACh = make(chan []byte, 1)
	pubBCh = make(chan []byte, 1)
	keyACh = make(chan [32]byte, 1)
	keyBCh = make(chan [32]byte, 1)
)

// A側:独立に曲線・鍵ペアを生成し、公開鍵(バイト)のみ送受して共有鍵を導出
func oneSession_A() (aKey, bKey [32]byte) {
	curveA := ecdh.X25519() // A側で独立に曲線取得
	apriv, _ := curveA.GenerateKey(rand.Reader)
	apub := apriv.PublicKey()

	// 自分の公開鍵を送信、相手の公開鍵(バイト)を受信
	pubACh <- apub.Bytes()
	bPubBytes := <-pubBCh

	// 受信したバイト列から相手公開鍵を復元
	bpub, _ := curveA.NewPublicKey(bPubBytes)

	// 共有値 → SHA-256 で AES-256 鍵に派生
	sharedA, _ := apriv.ECDH(bpub)
	aKey = sha256.Sum256(sharedA)

	// 自分の派生鍵を通知・相手の派生鍵を受領(一致検証用)
	keyACh <- aKey
	bKey = <-keyBCh
	return
}

// B側:Aと同様に完全独立
func oneSession_B() (aKey, bKey [32]byte) {
	curveB := ecdh.X25519() // B側で独立に曲線取得
	bpriv, _ := curveB.GenerateKey(rand.Reader)
	bpub := bpriv.PublicKey()

	// 相手(A)の公開鍵(バイト)を受信し、自分の公開鍵(バイト)を送信
	aPubBytes := <-pubACh
	pubBCh <- bpub.Bytes()

	// 受信したバイト列から相手公開鍵を復元
	apub, _ := curveB.NewPublicKey(aPubBytes)

	// 共有値 → SHA-256 で AES-256 鍵に派生
	sharedB, _ := bpriv.ECDH(apub)
	derivedB := sha256.Sum256(sharedB)

	// Aの派生鍵を受領し、自分の派生鍵を送信
	aFromA := <-keyACh
	keyBCh <- derivedB

	// 戻り値整形:aKey=自分の派生鍵、bKey=相手の派生鍵
	aKey = derivedB
	bKey = aFromA
	return
}

func main() {
	doneA := make(chan struct{})
	doneB := make(chan struct{})

	var aA, bA, aB, bB [32]byte

	go func() { aA, bA = oneSession_A(); close(doneA) }()
	go func() { aB, bB = oneSession_B(); close(doneB) }()

	<-doneA
	<-doneB

	fmt.Printf("A側 自分鍵: %x\n", aA)
	fmt.Printf("A側 相手鍵: %x\n", bA)
	fmt.Printf("B側 自分鍵: %x\n", aB)
	fmt.Printf("B側 相手鍵: %x\n", bB)

	fmt.Println("一致?", aA == bA && aB == bB && aA == aB && bA == bB)
}
モバイルバージョンを終了