-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathkeyring.go
142 lines (117 loc) · 4.06 KB
/
keyring.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package lnmux
import (
"crypto/sha256"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/lightningnetwork/lnd/keychain"
)
// KeyRing is an implementation of both the KeyRing and SecretKeyRing
// interfaces backed by btcwallet's internal root waddrmgr. Internally, we'll
// be using a ScopedKeyManager to do all of our derivations, using the key
// scope and scope addr scehma defined above. Re-using the existing key scope
// construction means that all key derivation will be protected under the root
// seed of the wallet, making each derived key fully deterministic.
type KeyRing struct {
keychain.SecretKeyRing
pubKey *btcec.PublicKey
privKey *btcec.PrivateKey
}
// NewKeyRing creates a new implementation of the
// keychain.SecretKeyRing interface backed by btcwallet.
//
// NOTE: The passed waddrmgr.Manager MUST be unlocked in order for the keychain
// to function.
func NewKeyRing(key [32]byte) *KeyRing {
privKey, pubKey := btcec.PrivKeyFromBytes(key[:])
return &KeyRing{
pubKey: pubKey,
privKey: privKey,
}
}
func (b *KeyRing) DeriveNextKey(keyFam keychain.KeyFamily) (
keychain.KeyDescriptor, error) {
panic("not implemented")
}
// DeriveKey attempts to derive an arbitrary key specified by the passed
// KeyLocator. This may be used in several recovery scenarios, or when manually
// rotating something like our current default node key.
//
// NOTE: This is part of the keychain.KeyRing interface.
func (b *KeyRing) DeriveKey(keyLoc keychain.KeyLocator) (keychain.KeyDescriptor, error) {
var keyDesc keychain.KeyDescriptor
keyDesc.KeyLocator = keyLoc
keyDesc.PubKey = b.pubKey
return keyDesc, nil
}
// DerivePrivKey attempts to derive the private key that corresponds to the
// passed key descriptor.
//
// NOTE: This is part of the keychain.SecretKeyRing interface.
func (b *KeyRing) DerivePrivKey(keyDesc keychain.KeyDescriptor) (
*btcec.PrivateKey, error) {
return b.privKey, nil
}
// ECDH performs a scalar multiplication (ECDH-like operation) between the
// target key descriptor and remote public key. The output returned will be
// the sha256 of the resulting shared point serialized in compressed format. If
// k is our private key, and P is the public key, we perform the following
// operation:
//
// sx := k*P s := sha256(sx.SerializeCompressed())
//
// NOTE: This is part of the keychain.ECDHRing interface.
func (b *KeyRing) ECDH(keyDesc keychain.KeyDescriptor,
pub *btcec.PublicKey) ([32]byte, error) {
var (
pubJacobian btcec.JacobianPoint
s btcec.JacobianPoint
)
pub.AsJacobian(&pubJacobian)
btcec.ScalarMultNonConst(&b.privKey.Key, &pubJacobian, &s)
s.ToAffine()
sPubKey := btcec.NewPublicKey(&s.X, &s.Y)
h := sha256.Sum256(sPubKey.SerializeCompressed())
return h, nil
}
// SignMessage signs the given message, single or double SHA256 hashing it
// first, with the private key described in the key locator.
//
// NOTE: This is part of the keychain.MessageSignerRing interface.
func (b *KeyRing) SignMessage(keyLoc keychain.KeyLocator,
msg []byte, doubleHash bool) (*ecdsa.Signature, error) {
privKey, err := b.DerivePrivKey(keychain.KeyDescriptor{
KeyLocator: keyLoc,
})
if err != nil {
return nil, err
}
var digest []byte
if doubleHash {
digest = chainhash.DoubleHashB(msg)
} else {
digest = chainhash.HashB(msg)
}
return ecdsa.Sign(privKey, digest), nil
}
// SignMessageCompact signs the given message, single or double SHA256 hashing
// it first, with the private key described in the key locator and returns
// the signature in the compact, public key recoverable format.
//
// NOTE: This is part of the keychain.MessageSignerRing interface.
func (b *KeyRing) SignMessageCompact(keyLoc keychain.KeyLocator,
msg []byte, doubleHash bool) ([]byte, error) {
privKey, err := b.DerivePrivKey(keychain.KeyDescriptor{
KeyLocator: keyLoc,
})
if err != nil {
return nil, err
}
var digest []byte
if doubleHash {
digest = chainhash.DoubleHashB(msg)
} else {
digest = chainhash.HashB(msg)
}
return ecdsa.SignCompact(privKey, digest, true)
}