-
Notifications
You must be signed in to change notification settings - Fork 11
/
piecekey.go
186 lines (152 loc) · 5.38 KB
/
piecekey.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package storj
import (
"database/sql/driver"
"github.com/zeebo/errs"
"golang.org/x/crypto/ed25519"
"storj.io/common/sync2/race2"
)
// ErrPieceKey is used when something goes wrong with a piece key.
var ErrPieceKey = errs.Class("piece key")
// PiecePublicKey is the unique identifier for pieces.
type PiecePublicKey struct {
pub ed25519.PublicKey
}
// PiecePrivateKey is the unique identifier for pieces.
type PiecePrivateKey struct {
priv ed25519.PrivateKey
}
// NewPieceKey creates a piece key pair.
func NewPieceKey() (PiecePublicKey, PiecePrivateKey, error) {
pub, priv, err := ed25519.GenerateKey(nil)
return PiecePublicKey{pub}, PiecePrivateKey{priv}, ErrPieceKey.Wrap(err)
}
// PiecePublicKeyFromBytes converts bytes to a piece public key.
func PiecePublicKeyFromBytes(data []byte) (PiecePublicKey, error) {
if len(data) != ed25519.PublicKeySize {
return PiecePublicKey{}, ErrPieceKey.New("invalid public key length %v", len(data))
}
pub := make(ed25519.PublicKey, len(data))
copy(pub, data)
return PiecePublicKey{pub}, nil
}
// PiecePrivateKeyFromBytes converts bytes to a piece private key.
func PiecePrivateKeyFromBytes(data []byte) (PiecePrivateKey, error) {
if len(data) != ed25519.PrivateKeySize {
return PiecePrivateKey{}, ErrPieceKey.New("invalid private key length %v", len(data))
}
priv := make(ed25519.PrivateKey, len(data))
copy(priv, data)
return PiecePrivateKey{priv}, nil
}
// Sign signs the message with privateKey and returns a signature.
func (key PiecePrivateKey) Sign(data []byte) ([]byte, error) {
race2.ReadSlice(data)
if len(key.priv) != ed25519.PrivateKeySize {
return nil, ErrPieceKey.New("invalid private key length %v", len(key.priv))
}
return ed25519.Sign(key.priv, data), nil
}
// Verify reports whether signature is a valid signature of message by publicKey.
func (key PiecePublicKey) Verify(data, signature []byte) error {
race2.ReadSlice(data)
race2.ReadSlice(signature)
if len(key.pub) != ed25519.PublicKeySize {
return ErrPieceKey.New("invalid public key length %v", len(key.pub))
}
if !ed25519.Verify(key.pub, data, signature) {
return ErrPieceKey.New("invalid signature")
}
return nil
}
// Bytes returns bytes of the piece public key.
func (key PiecePublicKey) Bytes() []byte { return key.pub[:] }
// Bytes returns bytes of the piece private key.
func (key PiecePrivateKey) Bytes() []byte { return key.priv[:] }
// IsZero returns whether the key is empty.
func (key PiecePublicKey) IsZero() bool { return len(key.pub) == 0 }
// IsZero returns whether the key is empty.
func (key PiecePrivateKey) IsZero() bool { return len(key.priv) == 0 }
// Marshal serializes a piece public key.
func (key PiecePublicKey) Marshal() ([]byte, error) { return key.Bytes(), nil }
// Marshal serializes a piece private key.
func (key PiecePrivateKey) Marshal() ([]byte, error) { return key.Bytes(), nil }
// MarshalTo serializes a piece public key into the passed byte slice.
func (key *PiecePublicKey) MarshalTo(data []byte) (n int, err error) {
n = copy(data, key.Bytes())
return n, nil
}
// MarshalTo serializes a piece private key into the passed byte slice.
func (key *PiecePrivateKey) MarshalTo(data []byte) (n int, err error) {
n = copy(data, key.Bytes())
return n, nil
}
// Unmarshal deserializes a piece public key.
func (key *PiecePublicKey) Unmarshal(data []byte) error {
// allow empty keys
if len(data) == 0 {
key.pub = nil
return nil
}
var err error
*key, err = PiecePublicKeyFromBytes(data)
return err
}
// Unmarshal deserializes a piece private key.
func (key *PiecePrivateKey) Unmarshal(data []byte) error {
// allow empty keys
if len(data) == 0 {
key.priv = nil
return nil
}
if len(data) == 0 {
return nil
}
var err error
*key, err = PiecePrivateKeyFromBytes(data)
return err
}
// Size returns the length of a piece public key (implements gogo's custom type interface).
func (key *PiecePublicKey) Size() int { return len(key.pub) }
// Size returns the length of a piece private key (implements gogo's custom type interface).
func (key *PiecePrivateKey) Size() int { return len(key.priv) }
// Value set a PiecePublicKey to a database field.
func (key PiecePublicKey) Value() (driver.Value, error) {
return key.Bytes(), nil
}
// Value set a PiecePrivateKey to a database field.
func (key PiecePrivateKey) Value() (driver.Value, error) { return key.Bytes(), nil }
// Scan extracts a PiecePublicKey from a database field.
func (key *PiecePublicKey) Scan(src interface{}) (err error) {
b, ok := src.([]byte)
if !ok {
return ErrPieceKey.New("PiecePublicKey Scan expects []byte")
}
n, err := PiecePublicKeyFromBytes(b)
*key = n
return err
}
// Scan extracts a PiecePrivateKey from a database field.
func (key *PiecePrivateKey) Scan(src interface{}) (err error) {
b, ok := src.([]byte)
if !ok {
return ErrPieceKey.New("PiecePrivateKey Scan expects []byte")
}
n, err := PiecePrivateKeyFromBytes(b)
*key = n
return err
}
// MarshalText serializes a piece public key to a base32 string.
func (key *PiecePublicKey) MarshalText() ([]byte, error) {
text := base32Encoding.EncodeToString(key.Bytes())
return []byte(text), nil
}
// UnmarshalText deserializes a base32 string to a piece public key.
func (key *PiecePublicKey) UnmarshalText(data []byte) error {
bytes, err := base32Encoding.DecodeString(string(data))
if err != nil {
return err
}
return key.Unmarshal(bytes)
}