github.com/Axway/agent-sdk@v1.1.101/pkg/util/gcmencrypt.go (about)

     1  package util
     2  
     3  import (
     4  	"crypto/aes"
     5  	"crypto/cipher"
     6  	"crypto/rand"
     7  	"crypto/sha256"
     8  	"encoding/base64"
     9  	"io"
    10  )
    11  
    12  // gcmEncryption implements the Encryptor/Decryptor interface
    13  type gcmEncoder struct {
    14  	gcm cipher.AEAD
    15  }
    16  
    17  func newGCMEncoder(key []byte) (*gcmEncoder, error) {
    18  	block, err := aes.NewCipher(hashedKey(key))
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  
    23  	gcm, err := cipher.NewGCM(block)
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  	enc := &gcmEncoder{
    28  		gcm: gcm,
    29  	}
    30  	return enc, nil
    31  }
    32  
    33  func hashedKey(key []byte) []byte {
    34  	hash := sha256.New()
    35  	hash.Write(key)
    36  	return hash.Sum(nil)
    37  }
    38  
    39  // NewGCMEncryptor creates a struct to handle encryption based on the provided key.
    40  func NewGCMEncryptor(key []byte) (Encryptor, error) {
    41  	return newGCMEncoder(key)
    42  }
    43  
    44  // NewGCMDecryptor creates a struct to handle decryption based on the provided key.
    45  func NewGCMDecryptor(key []byte) (Decryptor, error) {
    46  	return newGCMEncoder(key)
    47  }
    48  
    49  // Encrypt encrypts string with a secret key and returns encrypted string.
    50  func (e *gcmEncoder) Encrypt(str string) (string, error) {
    51  	nonce := make([]byte, e.gcm.NonceSize())
    52  	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
    53  		return "", err
    54  	}
    55  	encrypted := e.gcm.Seal(nonce, nonce, []byte(str), nil)
    56  	return base64.URLEncoding.EncodeToString(encrypted), nil
    57  }
    58  
    59  // Decrypt decrypts encrypted string with a secret key and returns plain string.
    60  func (e *gcmEncoder) Decrypt(str string) (string, error) {
    61  	ed, err := base64.URLEncoding.DecodeString(str)
    62  	if err != nil {
    63  		return "", err
    64  	}
    65  
    66  	nonceSize := e.gcm.NonceSize()
    67  	if len(ed) < nonceSize {
    68  		return "", err
    69  	}
    70  
    71  	nonce, cipherText := ed[:nonceSize], ed[nonceSize:]
    72  	decrypted, err := e.gcm.Open(nil, nonce, cipherText, nil)
    73  	if err != nil {
    74  		return "", err
    75  	}
    76  
    77  	return string(decrypted), nil
    78  }