Skip to content

Commit d019eaf

Browse files
committed
multi: hide long-term private key behind interface
To be able to eventually extract the private keys out of the node itself into a hardware wallet or HSM, we need to abstract the ECDH operation against the long-term key behind an interface.
1 parent a601ae1 commit d019eaf

File tree

4 files changed

+15
-32
lines changed

4 files changed

+15
-32
lines changed

cmd/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,11 @@ func main() {
133133
}
134134

135135
privkey, _ := btcec.PrivKeyFromBytes(btcec.S256(), binKey)
136+
privKeyECDH := &sphinx.PrivKeyECDH{PrivKey: privkey}
136137
replayLog := sphinx.NewMemoryReplayLog()
137-
s := sphinx.NewRouter(privkey, &chaincfg.TestNet3Params, replayLog)
138+
s := sphinx.NewRouter(
139+
privKeyECDH, &chaincfg.TestNet3Params, replayLog,
140+
)
138141

139142
replayLog.Start()
140143
defer replayLog.Stop()

crypto.go

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -198,22 +198,7 @@ func (r *Router) generateSharedSecret(dhKey *btcec.PublicKey) (Hash256, error) {
198198
}
199199

200200
// Compute our shared secret.
201-
return generateSharedSecret(dhKey, r.onionKey)
202-
}
203-
204-
// generateSharedSecret generates the shared secret for a particular hop. The
205-
// shared secret is generated by taking the group element contained in the
206-
// mix-header, and performing an ECDH operation with the node's long term onion
207-
// key. We then take the _entire_ point generated by the ECDH operation,
208-
// serialize that using a compressed format, then feed the raw bytes through a
209-
// single SHA256 invocation. The resulting value is the shared secret.
210-
func generateSharedSecret(pub *btcec.PublicKey, priv *btcec.PrivateKey) (Hash256,
211-
error) {
212-
213-
s := &btcec.PublicKey{}
214-
s.X, s.Y = btcec.S256().ScalarMult(pub.X, pub.Y, priv.D.Bytes())
215-
216-
return sha256.Sum256(s.SerializeCompressed()), nil
201+
return r.onionKey.ECDH(dhKey)
217202
}
218203

219204
// onionEncrypt obfuscates the data with compliance with BOLT#4. As we use a

sphinx.go

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package sphinx
22

33
import (
44
"bytes"
5-
"crypto/ecdsa"
65
"crypto/hmac"
76
"crypto/sha256"
87
"fmt"
@@ -131,7 +130,8 @@ func generateSharedSecrets(paymentPath []*btcec.PublicKey,
131130
// Within the loop each new triplet will be computed recursively based
132131
// off of the blinding factor of the last hop.
133132
lastEphemeralPubKey := sessionKey.PubKey()
134-
sharedSecret, err := generateSharedSecret(paymentPath[0], sessionKey)
133+
sessionKeyECDH := &PrivKeyECDH{PrivKey: sessionKey}
134+
sharedSecret, err := sessionKeyECDH.ECDH(paymentPath[0])
135135
if err != nil {
136136
return nil, err
137137
}
@@ -488,14 +488,14 @@ type Router struct {
488488
nodeID [AddressSize]byte
489489
nodeAddr *btcutil.AddressPubKeyHash
490490

491-
onionKey *btcec.PrivateKey
491+
onionKey SingleKeyECDH
492492

493493
log ReplayLog
494494
}
495495

496496
// NewRouter creates a new instance of a Sphinx onion Router given the node's
497497
// currently advertised onion private key, and the target Bitcoin network.
498-
func NewRouter(nodeKey *btcec.PrivateKey, net *chaincfg.Params, log ReplayLog) *Router {
498+
func NewRouter(nodeKey SingleKeyECDH, net *chaincfg.Params, log ReplayLog) *Router {
499499
var nodeID [AddressSize]byte
500500
copy(nodeID[:], btcutil.Hash160(nodeKey.PubKey().SerializeCompressed()))
501501

@@ -505,15 +505,8 @@ func NewRouter(nodeKey *btcec.PrivateKey, net *chaincfg.Params, log ReplayLog) *
505505
return &Router{
506506
nodeID: nodeID,
507507
nodeAddr: nodeAddr,
508-
onionKey: &btcec.PrivateKey{
509-
PublicKey: ecdsa.PublicKey{
510-
Curve: btcec.S256(),
511-
X: nodeKey.X,
512-
Y: nodeKey.Y,
513-
},
514-
D: nodeKey.D,
515-
},
516-
log: log,
508+
onionKey: nodeKey,
509+
log: log,
517510
}
518511
}
519512

sphinx_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ func newTestRoute(numHops int) ([]*Router, *PaymentPath, *[]HopData, *OnionPacke
102102
}
103103

104104
nodes[i] = NewRouter(
105-
privKey, &chaincfg.MainNetParams, NewMemoryReplayLog(),
105+
&PrivKeyECDH{PrivKey: privKey}, &chaincfg.MainNetParams,
106+
NewMemoryReplayLog(),
106107
)
107108
}
108109

@@ -543,7 +544,8 @@ func newEOBRoute(numHops uint32,
543544
}
544545

545546
nodes[i] = NewRouter(
546-
privKey, &chaincfg.MainNetParams, NewMemoryReplayLog(),
547+
&PrivKeyECDH{PrivKey: privKey}, &chaincfg.MainNetParams,
548+
NewMemoryReplayLog(),
547549
)
548550
}
549551

0 commit comments

Comments
 (0)