-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnode.go
133 lines (106 loc) · 2.42 KB
/
node.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
package xnyss
import (
wotsp "github.com/Re0h/xnyss/wotsp256"
"crypto/sha256"
"crypto/rand"
"errors"
"bytes"
)
const nodeByteLen = 32 + 32 + 32 + 1
var (
ErrNodeInvalidInput = errors.New("input is not a valid node")
)
// Represents a node in the signature tree
type nyNode struct {
txid []byte
pubSeed []byte
privSeed []byte
confirms uint8
}
func loadNode(b []byte) (*nyNode, int, error) {
if len(b) < nodeByteLen {
return nil, 0, ErrNodeInvalidInput
}
return &nyNode{
privSeed: b[0:32],
pubSeed: b[32:64],
txid: b[64:96],
confirms: b[96],
}, nodeByteLen, nil
}
// Generates child nodes of the current node.
func (n *nyNode) childNodes(txid []byte) (children []*nyNode, err error) {
r := make([]byte, 64*Branches)
_, err = rand.Read(r)
if err != nil {
return
}
children = make([]*nyNode, Branches)
s := sha256.New()
offset := 0
for i := range children {
child := &nyNode{
txid: txid,
confirms: 0,
}
s.Write(n.privSeed)
s.Write(r[offset : offset+32])
child.privSeed = s.Sum(nil)
s.Reset()
s.Write(n.pubSeed)
s.Write(r[offset+32 : offset+64])
child.pubSeed = s.Sum(nil)
children[i] = child
offset += 64
}
return
}
func (n *nyNode) genPubKey() []byte {
return wotsp.GenPublicKey(n.privSeed, n.pubSeed, &wotsp.Address{})
}
func (n *nyNode) sign(msg, txid []byte, ots bool) (sig *Signature, childNodes []*nyNode, err error) {
childNodes, err = n.childNodes(txid)
if err != nil {
err = errors.New("failed to create child nodes " + err.Error())
return
}
childHashes := make([][]byte, len(childNodes))
// Write message to be signed
s:= sha256.New()
// Calculate the child nodes' public key hashes if required
if !ots {
for i := range childNodes {
pubKey := childNodes[i].genPubKey()
s.Write(pubKey)
childHashes[i] = s.Sum(nil)
s.Reset()
}
}
s.Write(msg)
for i := range childNodes {
s.Write(childHashes[i])
}
sigBytes := wotsp.Sign(s.Sum(nil), n.privSeed, n.pubSeed, &wotsp.Address{})
sig = &Signature{
PubSeed: n.pubSeed,
Message: msg,
SigBytes: sigBytes,
}
if !ots { // If we use a one-time key, we want sig.ChildHashes to be nil
sig.ChildHashes = childHashes
}
return
}
func (n *nyNode) bytes() []byte {
buf := &bytes.Buffer{}
buf.Write(n.privSeed)
buf.Write(n.pubSeed)
buf.Write(n.txid)
buf.WriteByte(n.confirms)
return buf.Bytes()
}
func (n *nyNode) wipe() {
for i := range n.privSeed {
n.privSeed[i] = 0
}
}