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)
}