gitlab.com/beacon-software/gadget@v0.0.0-20181217202115-54565ea1ed5e/crypto/aes.go (about)

     1  package crypto
     2  
     3  import (
     4  	"crypto/aes"
     5  	"crypto/cipher"
     6  
     7  	"gitlab.com/beacon-software/gadget/errors"
     8  	"gitlab.com/beacon-software/gadget/generator"
     9  )
    10  
    11  // AES256KeySize for AWS256 Encryption
    12  const AES256KeySize = 32
    13  
    14  // IncompleteDataError  returned when an incomplete ciphertext is passed to decrypt.
    15  type IncompleteDataError struct{ trace []string }
    16  
    17  func (err *IncompleteDataError) Error() string {
    18  	return "ciphertext data was incomplete"
    19  }
    20  
    21  // Trace returns the stack trace for the error
    22  func (err *IncompleteDataError) Trace() []string {
    23  	return err.trace
    24  }
    25  
    26  // NewIncompleteDataError instantiates a IncompleteDataError with a stack trace
    27  func NewIncompleteDataError() errors.TracerError {
    28  	return &IncompleteDataError{trace: errors.GetStackTrace()}
    29  }
    30  
    31  // AESEncryption provides AES256 Encryption with GCM tampering detection.
    32  type AESEncryption struct {
    33  	key   []byte
    34  	block cipher.Block
    35  	gcm   cipher.AEAD
    36  }
    37  
    38  // NewAES using the passed key, if nil is passed a new key will be generated.
    39  func NewAES(key []byte) (Encryption, error) {
    40  	a := &AESEncryption{}
    41  	var err error
    42  	if nil == key || len(key) == 0 {
    43  		a.RotateKey()
    44  	} else {
    45  		err = a.SetKey(key)
    46  	}
    47  	return a, err
    48  }
    49  
    50  // GetType returns the cipher type this instance of encryption provides.
    51  func (a *AESEncryption) GetType() CipherType {
    52  	return AES
    53  }
    54  
    55  // GenerateKey will create a new key to use with this instance of AES
    56  func (AESEncryption) GenerateKey() []byte {
    57  	return generator.Bytes(AES256KeySize)
    58  }
    59  
    60  // GetKey currently being used by this instance of AES
    61  func (a *AESEncryption) GetKey() []byte {
    62  	return a.key
    63  }
    64  
    65  // RotateKey generates a new AES256 key and sets for use on this instance and returns it.
    66  func (a *AESEncryption) RotateKey() []byte {
    67  	a.SetKey(a.GenerateKey())
    68  	return a.key
    69  }
    70  
    71  // SetKey for use on this instance of AES256.
    72  func (a *AESEncryption) SetKey(key []byte) error {
    73  	var err error
    74  	block, err := aes.NewCipher(key)
    75  	if nil != err {
    76  		return err
    77  	}
    78  	gcm, err := cipher.NewGCM(block)
    79  	if nil != err {
    80  		return err
    81  	}
    82  	a.key = key
    83  	a.block = block
    84  	a.gcm = gcm
    85  	return nil
    86  }
    87  
    88  // Encrypt with AES256-GCM
    89  func (a *AESEncryption) Encrypt(plaintext []byte) (ciphertext []byte, err error) {
    90  	nonce := generator.Bytes(a.gcm.NonceSize())
    91  	return a.gcm.Seal(nonce, nonce, plaintext, nil), nil
    92  }
    93  
    94  // Decrypt data using AES256-GCM
    95  func (a *AESEncryption) Decrypt(ciphertext []byte) (plaintext []byte, err error) {
    96  	if len(ciphertext) < a.gcm.NonceSize() {
    97  		return nil, NewIncompleteDataError()
    98  	}
    99  
   100  	return a.gcm.Open(nil,
   101  		ciphertext[:a.gcm.NonceSize()],
   102  		ciphertext[a.gcm.NonceSize():],
   103  		nil,
   104  	)
   105  }
   106  
   107  // Sign does nothing with AES
   108  func (a *AESEncryption) Sign(plaintext []byte) (signature []byte, err error) {
   109  	return []byte{}, nil
   110  }
   111  
   112  // Verify does nothing with AES
   113  func (a *AESEncryption) Verify(plaintext []byte, signature []byte) (err error) {
   114  	return nil
   115  }