forked from denkhaus/go-bitshares
/
privatekey.go
135 lines (106 loc) · 2.8 KB
/
privatekey.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
package types
import (
"crypto/ecdsa"
"encoding/hex"
"fmt"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcutil/base58"
"github.com/denkhaus/bitshares/util"
"github.com/juju/errors"
)
var (
ErrInvalidCurve = fmt.Errorf("invalid elliptic curve")
ErrSharedKeyTooBig = fmt.Errorf("shared key params are too big")
ErrSharedKeyIsPointAtInfinity = fmt.Errorf("shared key is point at infinity")
)
type PrivateKeys []PrivateKey
type PrivateKey struct {
priv *btcec.PrivateKey
pub *PublicKey
raw []byte
}
func (p PrivateKey) Marshal(enc *util.TypeEncoder) error {
if err := enc.EncodeUVarint(uint64(len(p.raw))); err != nil {
return errors.Annotate(err, "encode length")
}
if err := enc.Encode(p.raw); err != nil {
return errors.Annotate(err, "encode raw")
}
return nil
}
func (p *PrivateKey) Unmarshal(dec *util.TypeDecoder) error {
var len uint64
if err := dec.DecodeUVarint(&len); err != nil {
return errors.Annotate(err, "decode length")
}
if err := dec.ReadBytes(&p.raw, len); err != nil {
return errors.Annotate(err, "decode raw")
}
wif := base58.Encode(p.raw)
k, err := NewPrivateKeyFromWif(wif)
if err != nil {
return errors.Annotate(err, "NewPrivateKeyFromWif")
}
p.priv = k.priv
p.pub = k.pub
return nil
}
func NewPrivateKeyFromWif(wifPrivateKey string) (*PrivateKey, error) {
w, err := btcutil.DecodeWIF(wifPrivateKey)
if err != nil {
return nil, errors.Annotate(err, "DecodeWIF")
}
priv := w.PrivKey
raw := base58.Decode(wifPrivateKey)
pub, err := NewPublicKey(priv.PubKey())
if err != nil {
return nil, errors.Annotate(err, "NewPublicKey")
}
k := PrivateKey{
priv: priv,
raw: raw,
pub: pub,
}
return &k, nil
}
func (p PrivateKey) PublicKey() *PublicKey {
return p.pub
}
func (p PrivateKey) ECPrivateKey() *btcec.PrivateKey {
return p.priv
}
func (p PrivateKey) ToECDSA() *ecdsa.PrivateKey {
return p.priv.ToECDSA()
}
func (p PrivateKey) Bytes() []byte {
return p.priv.Serialize()
}
func (p PrivateKey) ToHex() string {
return hex.EncodeToString(p.Bytes())
}
func (p PrivateKey) ToWIF() string {
return base58.Encode(p.raw)
}
func (p PrivateKey) SignCompact(hash []byte) (sig []byte, err error) {
sig, err = btcec.SignCompact(btcec.S256(), p.ECPrivateKey(), hash, true)
return
}
func (p PrivateKey) SharedSecret(pub *PublicKey, skLen, macLen int) (sk []byte, err error) {
puk := pub.ToECDSA()
pvk := p.priv
if pvk.PublicKey.Curve != puk.Curve {
return nil, ErrInvalidCurve
}
if skLen+macLen > pub.MaxSharedKeyLength() {
return nil, ErrSharedKeyTooBig
}
x, _ := puk.Curve.ScalarMult(puk.X, puk.Y, pvk.D.Bytes())
if x == nil {
return nil, ErrSharedKeyIsPointAtInfinity
}
sk = make([]byte, skLen+macLen)
skBytes := x.Bytes()
copy(sk[len(sk)-len(skBytes):], skBytes)
return sk, nil
}