-
-
Notifications
You must be signed in to change notification settings - Fork 17
/
v4_keys.go
226 lines (184 loc) · 7.04 KB
/
v4_keys.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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
package paseto
import (
"crypto/ed25519"
"aidanwoods.dev/go-paseto/v2/internal/encoding"
"aidanwoods.dev/go-paseto/v2/internal/hashing"
"aidanwoods.dev/go-paseto/v2/internal/random"
t "aidanwoods.dev/go-result"
)
// V4AsymmetricPublicKey v4 public public key
type V4AsymmetricPublicKey struct {
material ed25519.PublicKey
}
// NewV4AsymmetricPublicKeyFromHex Construct a v4 public key from hex
func NewV4AsymmetricPublicKeyFromHex(hexEncoded string) (V4AsymmetricPublicKey, error) {
var publicKey []byte
if err := encoding.HexDecode(hexEncoded).Ok(&publicKey); err != nil {
// even though we return error, return a random key here rather than
// a nil key
return NewV4AsymmetricSecretKey().Public(), err
}
return NewV4AsymmetricPublicKeyFromBytes(publicKey)
}
// NewV4AsymmetricPublicKeyFromBytes Construct a v4 public key from bytes
func NewV4AsymmetricPublicKeyFromBytes(publicKey []byte) (V4AsymmetricPublicKey, error) {
if len(publicKey) != 32 {
// even though we return error, return a random key here rather than
// a nil key
return NewV4AsymmetricSecretKey().Public(), errorKeyLength(32, len(publicKey))
}
return V4AsymmetricPublicKey{publicKey}, nil
}
// NewV4AsymmetricPublicKeyFromEd25519 Construct a v2 public key from a standard Go object
func NewV4AsymmetricPublicKeyFromEd25519(publicKey ed25519.PublicKey) (V4AsymmetricPublicKey, error) {
return NewV4AsymmetricPublicKeyFromBytes([]byte(publicKey))
}
// ExportHex export a V4AsymmetricPublicKey to hex for storage
func (k V4AsymmetricPublicKey) ExportHex() string {
return encoding.HexEncode(k.ExportBytes())
}
// ExportBytes export a V4AsymmetricPublicKey to raw byte array
func (k V4AsymmetricPublicKey) ExportBytes() []byte {
return k.material
}
// V4AsymmetricSecretKey v4 public private key
type V4AsymmetricSecretKey struct {
material ed25519.PrivateKey
}
// Public returns the corresponding public key for a secret key
func (k V4AsymmetricSecretKey) Public() V4AsymmetricPublicKey {
return V4AsymmetricPublicKey{
material: t.Cast[ed25519.PublicKey](k.material.Public()).
Expect("should produce ed25519 public key"),
}
}
// ExportHex export a V4AsymmetricSecretKey to hex for storage
func (k V4AsymmetricSecretKey) ExportHex() string {
return encoding.HexEncode(k.ExportBytes())
}
// ExportBytes export a V4AsymmetricSecretKey to raw byte array
func (k V4AsymmetricSecretKey) ExportBytes() []byte {
return k.material
}
// ExportSeedHex export a V4AsymmetricSecretKey's seed to hex for storage
func (k V4AsymmetricSecretKey) ExportSeedHex() string {
return encoding.HexEncode(k.material.Seed())
}
// NewV4AsymmetricSecretKey generate a new secret key for use with asymmetric
// cryptography. Don't forget to export the public key for sharing, DO NOT share
// this secret key.
func NewV4AsymmetricSecretKey() V4AsymmetricSecretKey {
return V4AsymmetricSecretKey{
material: t.NewTupleResult(ed25519.GenerateKey(nil)).
Expect("CSPRNG should succeed").
Second,
}
}
// NewV4AsymmetricSecretKeyFromHex creates a secret key from hex
func NewV4AsymmetricSecretKeyFromHex(hexEncoded string) (V4AsymmetricSecretKey, error) {
var privateKey []byte
if err := encoding.HexDecode(hexEncoded).Ok(&privateKey); err != nil {
// even though we return error, return a random key here rather than
// a nil key
return NewV4AsymmetricSecretKey(), err
}
return NewV4AsymmetricSecretKeyFromBytes(privateKey)
}
func isEd25519KeyPairMalformed(privateKey []byte) bool {
seed := privateKey[:32]
pubKeyFromGiven := t.Cast[ed25519.PublicKey](ed25519.PrivateKey(privateKey).Public()).
Expect("should return ed25519 public key")
pubKeyFromSeed := t.Cast[ed25519.PublicKey](ed25519.NewKeyFromSeed(seed).Public()).
Expect("should return ed25519 public key")
return !pubKeyFromGiven.Equal(pubKeyFromSeed)
}
// NewV4AsymmetricSecretKeyFromBytes creates a secret key from bytes
func NewV4AsymmetricSecretKeyFromBytes(privateKey []byte) (V4AsymmetricSecretKey, error) {
if len(privateKey) != 64 {
// even though we return error, return a random key here rather than
// a nil key
return NewV4AsymmetricSecretKey(), errorKeyLength(64, len(privateKey))
}
if isEd25519KeyPairMalformed(privateKey) {
// even though we return error, return a random key here rather than
// a nil key
// This should catch poorly formed private keys (ones that do not embed
// a public key which corresponds to their private portion)
return NewV4AsymmetricSecretKey(), errorKeyInvalid
}
return V4AsymmetricSecretKey{privateKey}, nil
}
// NewV4AsymmetricSecretKeyFromEd25519 creates a secret key from a standard Go object
func NewV4AsymmetricSecretKeyFromEd25519(privateKey ed25519.PrivateKey) (V4AsymmetricSecretKey, error) {
return NewV4AsymmetricSecretKeyFromBytes([]byte(privateKey))
}
// NewV4AsymmetricSecretKeyFromSeed creates a secret key from a seed (hex)
func NewV4AsymmetricSecretKeyFromSeed(hexEncoded string) (V4AsymmetricSecretKey, error) {
var seedBytes []byte
if err := encoding.HexDecode(hexEncoded).Ok(&seedBytes); err != nil {
// even though we return error, return a random key here rather than
// a nil key
return NewV4AsymmetricSecretKey(), err
}
if len(seedBytes) != 32 {
// even though we return error, return a random key here rather than
// a nil key
return NewV4AsymmetricSecretKey(), errorSeedLength(32, len(seedBytes))
}
return V4AsymmetricSecretKey{ed25519.NewKeyFromSeed(seedBytes)}, nil
}
// V4SymmetricKey v4 local symmetric key
type V4SymmetricKey struct {
material [32]byte
}
// NewV4SymmetricKey generates a new symmetric key for encryption
func NewV4SymmetricKey() V4SymmetricKey {
var material [32]byte
random.FillBytes(material[:])
return V4SymmetricKey{material}
}
// ExportHex exports the key as hex for storage
func (k V4SymmetricKey) ExportHex() string {
return encoding.HexEncode(k.ExportBytes())
}
// ExportBytes exports the key as raw byte array
func (k V4SymmetricKey) ExportBytes() []byte {
return k.material[:]
}
// V4SymmetricKeyFromHex constructs a key from hex
func V4SymmetricKeyFromHex(hexEncoded string) (V4SymmetricKey, error) {
var bytes []byte
if err := encoding.HexDecode(hexEncoded).Ok(&bytes); err != nil {
// even though we return error, return a random key here rather than
// a nil key
return NewV4SymmetricKey(), err
}
return V4SymmetricKeyFromBytes(bytes)
}
// V4SymmetricKeyFromBytes constructs a key from bytes
func V4SymmetricKeyFromBytes(bytes []byte) (V4SymmetricKey, error) {
if len(bytes) != 32 {
// even though we return error, return a random key here rather than
// a nil key
return NewV4SymmetricKey(), errorKeyLength(32, len(bytes))
}
var material [32]byte
copy(material[:], bytes)
return V4SymmetricKey{material}, nil
}
func (k V4SymmetricKey) split(nonce [32]byte) (encKey [32]byte, authkey [32]byte, nonce2 [24]byte) {
var tmp [56]byte
hashing.GenericHash(
append([]byte("paseto-encryption-key"), nonce[:]...),
tmp[:],
k.material[:],
)
copy(encKey[:], tmp[0:32])
copy(nonce2[:], tmp[32:56])
hashing.GenericHash(
append([]byte("paseto-auth-key-for-aead"), nonce[:]...),
authkey[:],
k.material[:],
)
return encKey, authkey, nonce2
}