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

     1  package osscrypto
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"io"
     8  	math_rand "math/rand"
     9  )
    10  
    11  // MasterCipher encrypt or decrpt CipherData
    12  // support master key: rsa && ali kms
    13  type MasterCipher interface {
    14  	Encrypt([]byte) ([]byte, error)
    15  	Decrypt([]byte) ([]byte, error)
    16  	GetWrapAlgorithm() string
    17  	GetMatDesc() string
    18  }
    19  
    20  // ContentCipherBuilder is used to create ContentCipher for encryting object's data
    21  type ContentCipherBuilder interface {
    22  	ContentCipher() (ContentCipher, error)
    23  	ContentCipherEnv(Envelope) (ContentCipher, error)
    24  	GetMatDesc() string
    25  }
    26  
    27  // ContentCipher is used to encrypt or decrypt object's data
    28  type ContentCipher interface {
    29  	EncryptContent(io.Reader) (io.ReadCloser, error)
    30  	DecryptContent(io.Reader) (io.ReadCloser, error)
    31  	Clone(cd CipherData) (ContentCipher, error)
    32  	GetEncryptedLen(int64) int64
    33  	GetCipherData() *CipherData
    34  	GetAlignLen() int
    35  }
    36  
    37  // Envelope is stored in oss object's meta
    38  type Envelope struct {
    39  	IV                    string
    40  	CipherKey             string
    41  	MatDesc               string
    42  	WrapAlg               string
    43  	CEKAlg                string
    44  	UnencryptedMD5        string
    45  	UnencryptedContentLen string
    46  }
    47  
    48  func (el Envelope) IsValid() bool {
    49  	return len(el.IV) > 0 &&
    50  		len(el.CipherKey) > 0 &&
    51  		len(el.WrapAlg) > 0 &&
    52  		len(el.CEKAlg) > 0
    53  }
    54  
    55  func (el Envelope) String() string {
    56  	return fmt.Sprintf("IV=%s&CipherKey=%s&WrapAlg=%s&CEKAlg=%s", el.IV, el.CipherKey, el.WrapAlg, el.CEKAlg)
    57  }
    58  
    59  // CipherData is secret key information
    60  type CipherData struct {
    61  	IV            []byte
    62  	Key           []byte
    63  	MatDesc       string
    64  	WrapAlgorithm string
    65  	CEKAlgorithm  string
    66  	EncryptedIV   []byte
    67  	EncryptedKey  []byte
    68  }
    69  
    70  func (cd *CipherData) RandomKeyIv(keyLen int, ivLen int) error {
    71  	// Key
    72  	cd.Key = make([]byte, keyLen)
    73  	if _, err := io.ReadFull(rand.Reader, cd.Key); err != nil {
    74  		return err
    75  	}
    76  
    77  	// sizeof uint64
    78  	if ivLen < 8 {
    79  		return fmt.Errorf("ivLen:%d less than 8", ivLen)
    80  	}
    81  
    82  	// IV:reserve 8 bytes
    83  	cd.IV = make([]byte, ivLen)
    84  	if _, err := io.ReadFull(rand.Reader, cd.IV[0:ivLen-8]); err != nil {
    85  		return err
    86  	}
    87  
    88  	// only use 4 byte,in order not to overflow when SeekIV()
    89  	randNumber := math_rand.Uint32()
    90  	cd.SetIV(uint64(randNumber))
    91  	return nil
    92  }
    93  
    94  func (cd *CipherData) SetIV(iv uint64) {
    95  	ivLen := len(cd.IV)
    96  	binary.BigEndian.PutUint64(cd.IV[ivLen-8:], iv)
    97  }
    98  
    99  func (cd *CipherData) GetIV() uint64 {
   100  	ivLen := len(cd.IV)
   101  	return binary.BigEndian.Uint64(cd.IV[ivLen-8:])
   102  }
   103  
   104  func (cd *CipherData) SeekIV(startPos uint64) {
   105  	cd.SetIV(cd.GetIV() + startPos/uint64(len(cd.IV)))
   106  }
   107  
   108  func (cd *CipherData) Clone() CipherData {
   109  	var cloneCd CipherData
   110  	cloneCd = *cd
   111  
   112  	cloneCd.Key = make([]byte, len(cd.Key))
   113  	copy(cloneCd.Key, cd.Key)
   114  
   115  	cloneCd.IV = make([]byte, len(cd.IV))
   116  	copy(cloneCd.IV, cd.IV)
   117  
   118  	cloneCd.EncryptedIV = make([]byte, len(cd.EncryptedIV))
   119  	copy(cloneCd.EncryptedIV, cd.EncryptedIV)
   120  
   121  	cloneCd.EncryptedKey = make([]byte, len(cd.EncryptedKey))
   122  	copy(cloneCd.EncryptedKey, cd.EncryptedKey)
   123  
   124  	return cloneCd
   125  }