-
Notifications
You must be signed in to change notification settings - Fork 5
/
master_key.go
124 lines (104 loc) · 2.56 KB
/
master_key.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
package eth2deposit
import (
"crypto/elliptic"
"crypto/sha256"
"fmt"
"math/big"
"runtime"
hmac "github.com/RockX-SG/eth2deposit/hmac"
"github.com/awnumar/memguard"
"github.com/btcsuite/btcd/btcec/v2"
)
const (
SeedLength = 32
encTemplate = "rockx.com/key_derive/%v"
)
var (
one = new(big.Int).SetInt64(1)
)
// MasterKey defines an enclaved master key for offering online service
type MasterKey struct {
enclave *memguard.Enclave
curve elliptic.Curve
N *big.Int
}
// NewMasterKey creates an encalved key
func NewMasterKey(seed [SeedLength]byte) *MasterKey {
mk := new(MasterKey)
mk.enclave = memguard.NewEnclave(seed[:])
mk.curve = btcec.S256()
mk.N = new(big.Int).Sub(mk.curve.Params().N, one)
return mk
}
// DeriveChild derives crypto-strong child key
//
// Approach:
//
// For Each Level of Subkey Generation:
// secret := hmac(rockx.com/eth/key_id/%v(string), parentKey)
// pubkey := p256.ScalaBaseMult(secret)
// childKey := hash(pubkey)
func (mkey *MasterKey) DeriveChild(path string) (*memguard.LockedBuffer, error) {
defer runtime.GC()
nodes, err := _path_to_nodes(path)
if err != nil {
return nil, err
}
// open master key in enclave
b, err := mkey.enclave.Open()
if err != nil {
return nil, err
}
// recursively locate to subkey
subkey := b
for k := range nodes {
subkey, err = mkey._derive_child(subkey, nodes[k])
if err != nil {
return nil, err
}
}
return subkey, nil
}
// derive the n-th child of parent key
func (mkey *MasterKey) _derive_child(parentKey *memguard.LockedBuffer, id uint32) (*memguard.LockedBuffer, error) {
defer parentKey.Destroy()
// path string
message := fmt.Sprintf(encTemplate, id)
// hmac-sha256
mac := hmac.New(sha256.New, parentKey.Bytes())
mac.Write([]byte(message))
sum := mac.Sum(nil)
defer mac.Reset()
defer mac.Wipe()
defer wipeSlice(sum)
// generate private key
k := new(big.Int).SetBytes(sum[:])
k.Mod(k, mkey.N)
k.Add(k, one)
defer wipeBig(k)
// private key to public key
kBytes := k.Bytes()
defer wipeSlice(kBytes)
X, Y := mkey.curve.ScalarBaseMult(kBytes)
// hash(pub)
h := sha256.New()
defer h.Reset()
tmpX := make([]byte, 32)
X.FillBytes(tmpX)
h.Write(tmpX)
defer wipeBig(X)
defer wipeSlice(tmpX)
tmpY := make([]byte, 32)
Y.FillBytes(tmpY)
h.Write(tmpY)
defer wipeBig(Y)
defer wipeSlice(tmpY)
// generate child key
pkSum := h.Sum(nil)
defer wipeSlice(pkSum)
derivedKey := new(big.Int).SetBytes(pkSum)
derivedKey.Mod(derivedKey, mkey.N)
derivedKey.Add(derivedKey, one)
defer wipeBig(derivedKey)
return memguard.NewBufferFromBytes(derivedKey.Bytes()), nil
}