Nostr ECDH Key Exchange with GoWith Nostr we can create a session key using Bob and Alice's key pairs. With ECDH (Elliptic Curve Diffie Hellman), Bob generates a scalar value of \(b\) and Alice generates a scalar value of \(a\). Bob computes \(b.G\) and Alice computes \(a.G\), and where \(G\) is the base point on the curve. Bob passes \(b.G\) to Alice, and Alice passes \(a.G\) to Bob. They then both compute \(a.b.G\) as a shared secret. |
Theory
With ECDH (Elliptic Curve Diffie Hellman), Bob generates a scalar value of \(b\) and Alice generates a scalar value of \(a\). Bob computes \(b.G\) and Alice computes \(a.G\), and where \(G\) is the base point on the curve. Bob passes \(b.G\) to Alice, and Alice passes \(a.G\) to Bob. They then both compute \(a.b.G\) as a shared secret:
Code
The following is some sample code:
package main import ( "fmt" "encoding/hex" "github.com/nbd-wtf/go-nostr" "github.com/btcsuite/btcd/btcec" ) func main() { alice_sk := nostr.GeneratePrivateKey() alice_pk,_ := nostr.GetPublicKey(alice_sk) bob_sk := nostr.GeneratePrivateKey() bob_pk,_ := nostr.GetPublicKey(bob_sk) alice_privKeyBytes, _ := hex.DecodeString(alice_sk) alice_privKey, _ := btcec.PrivKeyFromBytes(alice_privKeyBytes) // adding 02 to signal that this is a compressed public key (33 bytes) alice_pubKeyBytes, _ := hex.DecodeString("02" + alice_pk) alice_pubKey, _ := btcec.ParsePubKey(alice_pubKeyBytes) bob_privKeyBytes, _ := hex.DecodeString(bob_sk) bob_privKey, _ := btcec.PrivKeyFromBytes(bob_privKeyBytes) // adding 02 to signal that this is a compressed public key (33 bytes) bob_pubKeyBytes, _ := hex.DecodeString("02" + bob_pk) bob_pubKey, _ := btcec.ParsePubKey(bob_pubKeyBytes) alice_shared:=btcec.GenerateSharedSecret(alice_privKey, bob_pubKey) bob_shared:=btcec.GenerateSharedSecret(bob_privKey, alice_pubKey) fmt.Printf("Alice Private key %v\n",alice_sk) fmt.Printf("Alice Public key: %v\n", alice_pk) fmt.Printf("Bob Private key %v\n",bob_sk) fmt.Printf("Bob Public key: %v\n", bob_pk) fmt.Printf("\nShared: %x\n",alice_shared) fmt.Printf("Shared: %x\n",bob_shared) }
And a sample run:
Alice Private key ae4d94c07016dab00de554fc4c867e7622c928ebbae24ea7ad6ac2e3f1dc02a4 Alice Public key: 1a9ef62f504b55dc549e0047567edc1a57bcf40747791f14908db69fcfbf5510 Bob Private key a61f3ac1d56a3a04be8fabaa865e87cc7772aad47dfdcfe005b201dac1dda45b Bob Public key: ff15a1446838ce6f0603b1402c58c5e88fa2949a6ebd71903749bea5ac5d45c3 Shared: 5f844a7a18dc37cd08abbe0f2c2aad25b06e6d10eb4a46f88b8f5ac2265d3d9e Shared: 5f844a7a18dc37cd08abbe0f2c2aad25b06e6d10eb4a46f88b8f5ac2265d3d9e