Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
87
pkg/security/encrypt.go
Normal file
87
pkg/security/encrypt.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package security
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type IEncryptor interface {
|
||||
EncryptChunk([]byte) []byte
|
||||
DecryptChunk([]byte) ([]byte, error)
|
||||
EncryptStringToBase64(string) string
|
||||
DecryptBase64ToString(string) (string, error)
|
||||
Close()
|
||||
}
|
||||
|
||||
type Encryptor struct {
|
||||
key []byte
|
||||
iv []byte
|
||||
gcm_encryptor cipher.AEAD
|
||||
block_auth []byte
|
||||
}
|
||||
|
||||
// NewEncryptor create new GCM - expects the key to be 32 bytes
|
||||
func NewEncryptor(encryption_key []byte, auth []byte, nonce []byte) (IEncryptor, []byte, error) {
|
||||
cypher, err := aes.NewCipher(encryption_key)
|
||||
if err != nil {
|
||||
return nil, nil, errors.WithStack(err)
|
||||
}
|
||||
gcm, err := cipher.NewGCM(cypher)
|
||||
if err != nil {
|
||||
return nil, nil, errors.WithStack(err)
|
||||
}
|
||||
if nonce != nil && len(nonce) != gcm.NonceSize() {
|
||||
return nil, nil, errors.Errorf("nonce is incorrect size %v", gcm.NonceSize())
|
||||
}
|
||||
if nonce == nil {
|
||||
nonce = make([]byte, gcm.NonceSize())
|
||||
_, err = io.ReadFull(rand.Reader, nonce)
|
||||
if err != nil {
|
||||
return nil, nil, errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
return &Encryptor{key: encryption_key, iv: nonce, gcm_encryptor: gcm, block_auth: auth}, nonce, nil
|
||||
}
|
||||
|
||||
// EncryptChunk takes a chunk and ecnrypts it using GCM
|
||||
func (s *Encryptor) EncryptChunk(chunk []byte) []byte {
|
||||
return s.gcm_encryptor.Seal(chunk[:0], s.iv, chunk, s.block_auth)
|
||||
}
|
||||
|
||||
// DecryptChunk takes a chunk and decrypts it using GCM
|
||||
func (s *Encryptor) DecryptChunk(chunk []byte) ([]byte, error) {
|
||||
data, err := s.gcm_encryptor.Open(chunk[:0], s.iv, chunk, s.block_auth)
|
||||
return data, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// EncryptStringToBase64 takes a string as input and encrypts it and encodes it for transportability
|
||||
func (s *Encryptor) EncryptStringToBase64(input string) string {
|
||||
data := s.EncryptChunk([]byte(input))
|
||||
return base64.RawStdEncoding.EncodeToString(data)
|
||||
}
|
||||
|
||||
// DecryptStringToBase64 takes a string as input and decodes it and decrypts it from transport
|
||||
func (s *Encryptor) DecryptBase64ToString(input string) (string, error) {
|
||||
decoded, err := base64.RawStdEncoding.DecodeString(input)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "request %s", input)
|
||||
}
|
||||
|
||||
decrypted, err := s.DecryptChunk(decoded)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(decrypted), nil
|
||||
}
|
||||
|
||||
func (s *Encryptor) Close() {
|
||||
s.gcm_encryptor = nil
|
||||
s.iv = nil
|
||||
s.key = nil
|
||||
}
|
||||
Reference in New Issue
Block a user