-
Notifications
You must be signed in to change notification settings - Fork 5
/
blskey.go
136 lines (109 loc) · 3 KB
/
blskey.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
package eth2deposit
import (
"crypto/sha256"
"encoding/binary"
"errors"
"io"
"math/big"
"golang.org/x/crypto/hkdf"
)
const (
K = 32
L = K * 255
)
var (
salt = sha256.Sum256([]byte("BLS-SIG-KEYGEN-SALT-"))
R, _ = new(big.Int).SetString("52435875175126190479447740508185965837690552500527637822603658699938581184513", 10)
)
func _flip_bits(in []byte) {
for i := 0; i < len(in); i++ {
in[i] = ^in[i]
}
}
func _IKM_to_lamport_SK(IKM []byte, salt []byte) ([][]byte, error) {
PRK := hkdf.Extract(sha256.New, []byte(IKM), []byte(salt))
okmReader := hkdf.Expand(sha256.New, PRK, nil)
var lamport_SK [][]byte
for i := 0; i < L/K; i++ {
chunk := make([]byte, K)
_, err := io.ReadFull(okmReader, chunk)
if err != nil {
return nil, err
}
lamport_SK = append(lamport_SK, chunk)
}
return lamport_SK, nil
}
func _parent_SK_to_lamport_PK(parent_SK *big.Int, index uint32) ([]byte, error) {
salt := make([]byte, 4)
binary.BigEndian.PutUint32(salt, index)
IKM := make([]byte, K)
parent_SK.FillBytes(IKM)
lamport_0, err := _IKM_to_lamport_SK(IKM, salt)
if err != nil {
return nil, err
}
_flip_bits(IKM)
lamport_1, err := _IKM_to_lamport_SK(IKM, salt)
if err != nil {
return nil, err
}
var lamport_PK []byte
for i := 0; i < len(lamport_0); i++ {
sum := sha256.Sum256(lamport_0[i])
lamport_PK = append(lamport_PK, sum[:]...)
}
for i := 0; i < len(lamport_1); i++ {
sum := sha256.Sum256(lamport_1[i])
lamport_PK = append(lamport_PK, sum[:]...)
}
compressed_lamport_PK := sha256.Sum256(lamport_PK)
return compressed_lamport_PK[:], nil
}
// 1. salt = "BLS-SIG-KEYGEN-SALT-"
// 2. SK = 0
// 3. while SK == 0:
// 4. salt = H(salt)
// 5. PRK = HKDF-Extract(salt, IKM || I2OSP(0, 1))
// 6. OKM = HKDF-Expand(PRK, key_info || I2OSP(L, 2), L)
// 7. SK = OS2IP(OKM) mod r
// 8. return SK
func _HKDF_mod_r(IKM []byte, key_info []byte) *big.Int {
L := 48
infoExtra := make([]byte, 2)
binary.BigEndian.PutUint16(infoExtra, uint16(L))
SK := new(big.Int)
for SK.BitLen() == 0 {
// PRK = HKDF-Extract(salt, IKM || I2OSP(0, 1))
ikm := make([]byte, len(IKM))
copy(ikm, IKM)
ikm = append(ikm, 0) // I20SP(0,1)
PRK := hkdf.Extract(sha256.New, ikm, salt[:])
// OKM = HKDF-Expand(PRK, key_info || I2OSP(L, 2), L)
info := make([]byte, len(key_info))
copy(info, key_info)
info = append(info, infoExtra...)
okmReader := hkdf.Expand(sha256.New, PRK, info)
OKM := make([]byte, L)
_, err := io.ReadFull(okmReader, OKM)
if err != nil {
panic(err)
}
SK = new(big.Int).SetBytes(OKM)
SK.Mod(SK, R)
}
return SK
}
func _derive_child_SK(parent_SK *big.Int, index uint32) (child_SK *big.Int, err error) {
compressed_lamport_PK, err := _parent_SK_to_lamport_PK(parent_SK, index)
if err != nil {
return nil, err
}
return _HKDF_mod_r(compressed_lamport_PK, nil), nil
}
func _derive_master_SK(seed []byte) (SK *big.Int, err error) {
if len(seed) < 32 {
return nil, errors.New("`len(seed)` should be greater than or equal to 32.")
}
return _HKDF_mod_r(seed, nil), nil
}