Cloak/internal/common/crypto.go

98 lines
2.0 KiB
Go
Raw Normal View History

2020-04-14 00:53:28 +00:00
package common
2018-10-07 17:09:45 +00:00
import (
2018-10-20 20:41:01 +00:00
"crypto/aes"
"crypto/cipher"
2020-02-01 23:46:46 +00:00
"crypto/rand"
2020-10-17 23:45:45 +00:00
"errors"
2020-04-09 21:11:12 +00:00
"io"
"math/big"
2019-08-19 22:23:41 +00:00
"time"
2020-02-01 23:46:46 +00:00
log "github.com/sirupsen/logrus"
2018-10-07 17:09:45 +00:00
)
2019-06-09 14:03:28 +00:00
func AESGCMEncrypt(nonce []byte, key []byte, plaintext []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
2020-10-17 23:45:45 +00:00
if len(nonce) != aesgcm.NonceSize() {
// check here so it doesn't panic
return nil, errors.New("incorrect nonce size")
}
2019-06-09 14:03:28 +00:00
return aesgcm.Seal(nil, nonce, plaintext, nil), nil
2018-10-20 20:41:01 +00:00
}
2019-06-09 14:03:28 +00:00
func AESGCMDecrypt(nonce []byte, key []byte, ciphertext []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
2020-10-17 23:45:45 +00:00
if len(nonce) != aesgcm.NonceSize() {
// check here so it doesn't panic
return nil, errors.New("incorrect nonce size")
}
2019-06-09 14:03:28 +00:00
plain, err := aesgcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return nil, err
}
return plain, nil
2018-10-20 20:41:01 +00:00
}
2020-02-01 23:46:46 +00:00
func CryptoRandRead(buf []byte) {
2020-04-09 21:11:12 +00:00
RandRead(rand.Reader, buf)
}
func backoff(f func() error) {
err := f()
2020-02-01 23:46:46 +00:00
if err == nil {
return
}
waitDur := [10]time.Duration{5 * time.Millisecond, 10 * time.Millisecond, 30 * time.Millisecond, 50 * time.Millisecond,
100 * time.Millisecond, 300 * time.Millisecond, 500 * time.Millisecond, 1 * time.Second,
3 * time.Second, 5 * time.Second}
for i := 0; i < 10; i++ {
log.Errorf("Failed to get random: %v. Retrying...", err)
err = f()
2020-02-01 23:46:46 +00:00
if err == nil {
return
}
2020-10-17 23:45:45 +00:00
time.Sleep(waitDur[i])
2020-02-01 23:46:46 +00:00
}
log.Fatal("Cannot get random after 10 retries")
}
func RandRead(randSource io.Reader, buf []byte) {
backoff(func() error {
_, err := randSource.Read(buf)
return err
})
}
func RandItem[T any](list []T) T {
return list[RandInt(len(list))]
}
func RandInt(n int) int {
s := new(int)
backoff(func() error {
size, err := rand.Int(rand.Reader, big.NewInt(int64(n)))
if err != nil {
return err
}
*s = int(size.Int64())
return nil
})
return *s
2020-02-01 23:46:46 +00:00
}