/
crypto.go
78 lines (63 loc) · 1.71 KB
/
crypto.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
// SPDX-FileCopyrightText: © 2020 Etebase Authors
// SPDX-License-Identifier: BSD-3-Clause
package crypto
import (
"math/rand"
"golang.org/x/crypto/argon2"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/ed25519"
)
func Rand(len int) []byte {
buf := make([]byte, len)
rand.Read(buf)
return buf
}
func DeriveKey(salt []byte, password string) []byte {
return argon2.IDKey(
[]byte(password),
salt,
1, 64*1024, 4, 32, // sensible values
)
}
func GenrateKeyPair(seed []byte) ([]byte, []byte) {
priv := ed25519.NewKeyFromSeed(seed)
return priv.Public().(ed25519.PublicKey), priv
}
func Sign(priv []byte, msg []byte) []byte {
return ed25519.Sign(priv, msg)
}
func resizeChachaKey(key []byte) []byte {
s := chacha20poly1305.KeySize
l := len(key)
if l >= s {
return key[:s]
}
newKey := make([]byte, s)
copy(newKey, key)
return newKey
}
func Encrypt(key []byte, msg []byte) ([]byte, error) {
key = resizeChachaKey(key)
aead, err := chacha20poly1305.NewX(key)
if err != nil {
return nil, err
}
// Select a random nonce, and leave capacity for the ciphertext.
nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(msg)+aead.Overhead())
if _, err := rand.Read(nonce); err != nil {
return nil, err
}
// Encrypt the message and append the ciphertext to the nonce.
return aead.Seal(nonce, nonce, msg, nil), nil
}
func Decrypt(key []byte, msg []byte) ([]byte, error) {
key = resizeChachaKey(key)
aead, err := chacha20poly1305.NewX(key)
if err != nil {
return nil, err
}
// Split the nonce and the cipher message
nonce, cipher := msg[:aead.NonceSize()], msg[aead.NonceSize():]
// Decrypt the message and check it wasn't tampered with.
return aead.Open(nil, nonce, cipher, nil)
}