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 }