github.com/aliyun/aliyun-oss-go-sdk@v3.0.2+incompatible/oss/crypto/aes_ctr_cipher.go (about)

     1  package osscrypto
     2  
     3  import (
     4  	"io"
     5  )
     6  
     7  const (
     8  	aesKeySize = 32
     9  	ivSize     = 16
    10  )
    11  
    12  // aesCtrCipherBuilder for building ContentCipher
    13  type aesCtrCipherBuilder struct {
    14  	MasterCipher MasterCipher
    15  }
    16  
    17  // aesCtrCipher will use aes ctr algorithm
    18  type aesCtrCipher struct {
    19  	CipherData CipherData
    20  	Cipher     Cipher
    21  }
    22  
    23  // CreateAesCtrCipher creates ContentCipherBuilder
    24  func CreateAesCtrCipher(cipher MasterCipher) ContentCipherBuilder {
    25  	return aesCtrCipherBuilder{MasterCipher: cipher}
    26  }
    27  
    28  // createCipherData create CipherData for encrypt object data
    29  func (builder aesCtrCipherBuilder) createCipherData() (CipherData, error) {
    30  	var cd CipherData
    31  	var err error
    32  	err = cd.RandomKeyIv(aesKeySize, ivSize)
    33  	if err != nil {
    34  		return cd, err
    35  	}
    36  
    37  	cd.WrapAlgorithm = builder.MasterCipher.GetWrapAlgorithm()
    38  	cd.CEKAlgorithm = AesCtrAlgorithm
    39  	cd.MatDesc = builder.MasterCipher.GetMatDesc()
    40  
    41  	// EncryptedKey
    42  	cd.EncryptedKey, err = builder.MasterCipher.Encrypt(cd.Key)
    43  	if err != nil {
    44  		return cd, err
    45  	}
    46  
    47  	// EncryptedIV
    48  	cd.EncryptedIV, err = builder.MasterCipher.Encrypt(cd.IV)
    49  	if err != nil {
    50  		return cd, err
    51  	}
    52  
    53  	return cd, nil
    54  }
    55  
    56  // contentCipherCD is used to create ContentCipher with CipherData
    57  func (builder aesCtrCipherBuilder) contentCipherCD(cd CipherData) (ContentCipher, error) {
    58  	cipher, err := newAesCtr(cd)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	return &aesCtrCipher{
    64  		CipherData: cd,
    65  		Cipher:     cipher,
    66  	}, nil
    67  }
    68  
    69  // ContentCipher is used to create ContentCipher interface
    70  func (builder aesCtrCipherBuilder) ContentCipher() (ContentCipher, error) {
    71  	cd, err := builder.createCipherData()
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  	return builder.contentCipherCD(cd)
    76  }
    77  
    78  // ContentCipherEnv is used to create a decrption ContentCipher from Envelope
    79  func (builder aesCtrCipherBuilder) ContentCipherEnv(envelope Envelope) (ContentCipher, error) {
    80  	var cd CipherData
    81  	cd.EncryptedKey = make([]byte, len(envelope.CipherKey))
    82  	copy(cd.EncryptedKey, []byte(envelope.CipherKey))
    83  
    84  	plainKey, err := builder.MasterCipher.Decrypt([]byte(envelope.CipherKey))
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	cd.Key = make([]byte, len(plainKey))
    89  	copy(cd.Key, plainKey)
    90  
    91  	cd.EncryptedIV = make([]byte, len(envelope.IV))
    92  	copy(cd.EncryptedIV, []byte(envelope.IV))
    93  
    94  	plainIV, err := builder.MasterCipher.Decrypt([]byte(envelope.IV))
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	cd.IV = make([]byte, len(plainIV))
   100  	copy(cd.IV, plainIV)
   101  
   102  	cd.MatDesc = envelope.MatDesc
   103  	cd.WrapAlgorithm = envelope.WrapAlg
   104  	cd.CEKAlgorithm = envelope.CEKAlg
   105  
   106  	return builder.contentCipherCD(cd)
   107  }
   108  
   109  // GetMatDesc is used to get MasterCipher's MatDesc
   110  func (builder aesCtrCipherBuilder) GetMatDesc() string {
   111  	return builder.MasterCipher.GetMatDesc()
   112  }
   113  
   114  // EncryptContents will generate a random key and iv and encrypt the data using ctr
   115  func (cc *aesCtrCipher) EncryptContent(src io.Reader) (io.ReadCloser, error) {
   116  	reader := cc.Cipher.Encrypt(src)
   117  	return &CryptoEncrypter{Body: src, Encrypter: reader}, nil
   118  }
   119  
   120  // DecryptContent is used to decrypt object using ctr
   121  func (cc *aesCtrCipher) DecryptContent(src io.Reader) (io.ReadCloser, error) {
   122  	reader := cc.Cipher.Decrypt(src)
   123  	return &CryptoDecrypter{Body: src, Decrypter: reader}, nil
   124  }
   125  
   126  // GetCipherData is used to get cipher data information
   127  func (cc *aesCtrCipher) GetCipherData() *CipherData {
   128  	return &(cc.CipherData)
   129  }
   130  
   131  // GetCipherData returns cipher data
   132  func (cc *aesCtrCipher) GetEncryptedLen(plainTextLen int64) int64 {
   133  	// AES CTR encryption mode does not change content length
   134  	return plainTextLen
   135  }
   136  
   137  // GetAlignLen is used to get align length
   138  func (cc *aesCtrCipher) GetAlignLen() int {
   139  	return len(cc.CipherData.IV)
   140  }
   141  
   142  // Clone is used to create a new aesCtrCipher from itself
   143  func (cc *aesCtrCipher) Clone(cd CipherData) (ContentCipher, error) {
   144  	cipher, err := newAesCtr(cd)
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  
   149  	return &aesCtrCipher{
   150  		CipherData: cd,
   151  		Cipher:     cipher,
   152  	}, nil
   153  }