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  }