github.com/aavshr/aws-sdk-go@v1.41.3/service/s3/s3crypto/aes_gcm.go (about)

     1  package s3crypto
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/aes"
     6  	"crypto/cipher"
     7  	"io"
     8  	"io/ioutil"
     9  )
    10  
    11  // AESGCM Symmetric encryption algorithm. Since Golang designed this
    12  // with only TLS in mind. We have to load it all into memory meaning
    13  // this isn't streamed.
    14  type aesGCM struct {
    15  	aead  cipher.AEAD
    16  	nonce []byte
    17  }
    18  
    19  // newAESGCM creates a new AES GCM cipher. Expects keys to be of
    20  // the correct size.
    21  //
    22  // Example:
    23  //
    24  //	cd := &s3crypto.CipherData{
    25  //		Key: key,
    26  //		"IV": iv,
    27  //	}
    28  //	cipher, err := s3crypto.newAESGCM(cd)
    29  func newAESGCM(cd CipherData) (Cipher, error) {
    30  	block, err := aes.NewCipher(cd.Key)
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  
    35  	aesgcm, err := cipher.NewGCM(block)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  
    40  	return &aesGCM{aesgcm, cd.IV}, nil
    41  }
    42  
    43  // Encrypt will encrypt the data using AES GCM
    44  // Tag will be included as the last 16 bytes of the slice
    45  func (c *aesGCM) Encrypt(src io.Reader) io.Reader {
    46  	reader := &gcmEncryptReader{
    47  		encrypter: c.aead,
    48  		nonce:     c.nonce,
    49  		src:       src,
    50  	}
    51  	return reader
    52  }
    53  
    54  type gcmEncryptReader struct {
    55  	encrypter cipher.AEAD
    56  	nonce     []byte
    57  	src       io.Reader
    58  	buf       *bytes.Buffer
    59  }
    60  
    61  func (reader *gcmEncryptReader) Read(data []byte) (int, error) {
    62  	if reader.buf == nil {
    63  		b, err := ioutil.ReadAll(reader.src)
    64  		if err != nil {
    65  			return 0, err
    66  		}
    67  		b = reader.encrypter.Seal(b[:0], reader.nonce, b, nil)
    68  		reader.buf = bytes.NewBuffer(b)
    69  	}
    70  
    71  	return reader.buf.Read(data)
    72  }
    73  
    74  // Decrypt will decrypt the data using AES GCM
    75  func (c *aesGCM) Decrypt(src io.Reader) io.Reader {
    76  	return &gcmDecryptReader{
    77  		decrypter: c.aead,
    78  		nonce:     c.nonce,
    79  		src:       src,
    80  	}
    81  }
    82  
    83  type gcmDecryptReader struct {
    84  	decrypter cipher.AEAD
    85  	nonce     []byte
    86  	src       io.Reader
    87  	buf       *bytes.Buffer
    88  }
    89  
    90  func (reader *gcmDecryptReader) Read(data []byte) (int, error) {
    91  	if reader.buf == nil {
    92  		b, err := ioutil.ReadAll(reader.src)
    93  		if err != nil {
    94  			return 0, err
    95  		}
    96  		b, err = reader.decrypter.Open(b[:0], reader.nonce, b, nil)
    97  		if err != nil {
    98  			return 0, err
    99  		}
   100  
   101  		reader.buf = bytes.NewBuffer(b)
   102  	}
   103  
   104  	return reader.buf.Read(data)
   105  }