github.com/decred/dcrlnd@v0.7.6/watchtower/wtmock/keyring.go (about) 1 package wtmock 2 3 import ( 4 "sync" 5 6 "github.com/decred/dcrd/dcrec/secp256k1/v4" 7 "github.com/decred/dcrlnd/keychain" 8 ) 9 10 // SecretKeyRing is a mock, in-memory implementation for deriving private keys. 11 type SecretKeyRing struct { 12 mu sync.Mutex 13 keys map[keychain.KeyLocator]*secp256k1.PrivateKey 14 } 15 16 // NewSecretKeyRing creates a new mock SecretKeyRing. 17 func NewSecretKeyRing() *SecretKeyRing { 18 return &SecretKeyRing{ 19 keys: make(map[keychain.KeyLocator]*secp256k1.PrivateKey), 20 } 21 } 22 23 // DeriveKey attempts to derive an arbitrary key specified by the passed 24 // KeyLocator. This may be used in several recovery scenarios, or when manually 25 // rotating something like our current default node key. 26 // 27 // NOTE: This is part of the wtclient.ECDHKeyRing interface. 28 func (m *SecretKeyRing) DeriveKey( 29 keyLoc keychain.KeyLocator) (keychain.KeyDescriptor, error) { 30 31 m.mu.Lock() 32 defer m.mu.Unlock() 33 34 if key, ok := m.keys[keyLoc]; ok { 35 return keychain.KeyDescriptor{ 36 KeyLocator: keyLoc, 37 PubKey: key.PubKey(), 38 }, nil 39 } 40 41 privKey, err := secp256k1.GeneratePrivateKey() 42 if err != nil { 43 return keychain.KeyDescriptor{}, err 44 } 45 46 m.keys[keyLoc] = privKey 47 48 return keychain.KeyDescriptor{ 49 KeyLocator: keyLoc, 50 PubKey: privKey.PubKey(), 51 }, nil 52 } 53 54 // ECDH performs a scalar multiplication (ECDH-like operation) between the 55 // target key descriptor and remote public key. The output returned will be the 56 // sha256 of the resulting shared point serialized in compressed format. If k is 57 // our private key, and P is the public key, we perform the following operation: 58 // 59 // sx := k*P 60 // s := sha256(sx.SerializeCompressed()) 61 // 62 // NOTE: This is part of the wtclient.ECDHKeyRing interface. 63 func (m *SecretKeyRing) ECDH(keyDesc keychain.KeyDescriptor, 64 pub *secp256k1.PublicKey) ([32]byte, error) { 65 66 _, err := m.DeriveKey(keyDesc.KeyLocator) 67 if err != nil { 68 return [32]byte{}, err 69 } 70 71 privKey := m.keys[keyDesc.KeyLocator] 72 ecdh := &keychain.PrivKeyECDH{PrivKey: privKey} 73 return ecdh.ECDH(pub) 74 }