OSDN Git Service

Create ossClient.go (#574)
[bytom/vapor.git] / vendor / github.com / aliyun / aliyun-oss-go-sdk / oss / crypto / crypto_multipart.go
1 package osscrypto
2
3 import (
4         "fmt"
5         "io"
6         "os"
7         "strconv"
8
9         "github.com/aliyun/aliyun-oss-go-sdk/oss"
10 )
11
12 // PartCryptoContext save encryption or decryption information
13 type PartCryptoContext struct {
14         ContentCipher ContentCipher
15         DataSize      int64
16         PartSize      int64
17 }
18
19 // Valid judge PartCryptoContext is valid or not
20 func (pcc PartCryptoContext) Valid() bool {
21         if pcc.ContentCipher == nil || pcc.DataSize == 0 || pcc.PartSize == 0 {
22                 return false
23         }
24         return true
25 }
26
27 // InitiateMultipartUpload initializes multipart upload for client encryption
28 // cryptoContext.PartSize and cryptoContext.DataSize are input parameter
29 // cryptoContext.PartSize must aligned to the secret iv length
30 // cryptoContext.ContentCipher is output parameter
31 // cryptoContext will be used in next API
32 func (bucket CryptoBucket) InitiateMultipartUpload(objectKey string, cryptoContext *PartCryptoContext, options ...oss.Option) (oss.InitiateMultipartUploadResult, error) {
33         options = bucket.AddEncryptionUaSuffix(options)
34         var imur oss.InitiateMultipartUploadResult
35         if cryptoContext == nil {
36                 return imur, fmt.Errorf("error,cryptoContext is nil")
37         }
38
39         if cryptoContext.PartSize <= 0 {
40                 return imur, fmt.Errorf("invalid PartCryptoContext's PartSize %d", cryptoContext.PartSize)
41         }
42
43         cc, err := bucket.ContentCipherBuilder.ContentCipher()
44         if err != nil {
45                 return imur, err
46         }
47
48         if cryptoContext.PartSize%int64(cc.GetAlignLen()) != 0 {
49                 return imur, fmt.Errorf("PartCryptoContext's PartSize must be aligned to %d", cc.GetAlignLen())
50         }
51
52         opts := addCryptoHeaders(options, cc.GetCipherData())
53         if cryptoContext.DataSize > 0 {
54                 opts = append(opts, oss.Meta(OssClientSideEncryptionDataSize, strconv.FormatInt(cryptoContext.DataSize, 10)))
55         }
56         opts = append(opts, oss.Meta(OssClientSideEncryptionPartSize, strconv.FormatInt(cryptoContext.PartSize, 10)))
57
58         imur, err = bucket.Bucket.InitiateMultipartUpload(objectKey, opts...)
59         if err == nil {
60                 cryptoContext.ContentCipher = cc
61         }
62         return imur, err
63 }
64
65 // UploadPart uploads parts to oss, the part data are encrypted automaticly on client side
66 // cryptoContext is the input parameter
67 func (bucket CryptoBucket) UploadPart(imur oss.InitiateMultipartUploadResult, reader io.Reader,
68         partSize int64, partNumber int, cryptoContext PartCryptoContext, options ...oss.Option) (oss.UploadPart, error) {
69         options = bucket.AddEncryptionUaSuffix(options)
70         var uploadPart oss.UploadPart
71         if cryptoContext.ContentCipher == nil {
72                 return uploadPart, fmt.Errorf("error,cryptoContext is nil or cryptoContext.ContentCipher is nil")
73         }
74
75         if partNumber < 1 {
76                 return uploadPart, fmt.Errorf("partNumber:%d is smaller than 1", partNumber)
77         }
78
79         if cryptoContext.PartSize%int64(cryptoContext.ContentCipher.GetAlignLen()) != 0 {
80                 return uploadPart, fmt.Errorf("PartCryptoContext's PartSize must be aligned to %d", cryptoContext.ContentCipher.GetAlignLen())
81         }
82
83         cipherData := cryptoContext.ContentCipher.GetCipherData().Clone()
84         // caclulate iv based on part number
85         if partNumber > 1 {
86                 cipherData.SeekIV(uint64(partNumber-1) * uint64(cryptoContext.PartSize))
87         }
88
89         // for parallel upload part
90         partCC, _ := cryptoContext.ContentCipher.Clone(cipherData)
91
92         cryptoReader, err := partCC.EncryptContent(reader)
93         if err != nil {
94                 return uploadPart, err
95         }
96
97         request := &oss.UploadPartRequest{
98                 InitResult: &imur,
99                 Reader:     cryptoReader,
100                 PartSize:   partCC.GetEncryptedLen(partSize),
101                 PartNumber: partNumber,
102         }
103
104         opts := addCryptoHeaders(options, partCC.GetCipherData())
105         if cryptoContext.DataSize > 0 {
106                 opts = append(opts, oss.Meta(OssClientSideEncryptionDataSize, strconv.FormatInt(cryptoContext.DataSize, 10)))
107         }
108         opts = append(opts, oss.Meta(OssClientSideEncryptionPartSize, strconv.FormatInt(cryptoContext.PartSize, 10)))
109
110         result, err := bucket.Bucket.DoUploadPart(request, opts)
111         return result.Part, err
112 }
113
114 // UploadPartFromFile uploads part from the file, the part data are encrypted automaticly on client side
115 // cryptoContext is the input parameter
116 func (bucket CryptoBucket) UploadPartFromFile(imur oss.InitiateMultipartUploadResult, filePath string,
117         startPosition, partSize int64, partNumber int, cryptoContext PartCryptoContext, options ...oss.Option) (oss.UploadPart, error) {
118         options = bucket.AddEncryptionUaSuffix(options)
119         var uploadPart = oss.UploadPart{}
120         if cryptoContext.ContentCipher == nil {
121                 return uploadPart, fmt.Errorf("error,cryptoContext is nil or cryptoContext.ContentCipher is nil")
122         }
123
124         if cryptoContext.PartSize%int64(cryptoContext.ContentCipher.GetAlignLen()) != 0 {
125                 return uploadPart, fmt.Errorf("PartCryptoContext's PartSize must be aligned to %d", cryptoContext.ContentCipher.GetAlignLen())
126         }
127
128         fd, err := os.Open(filePath)
129         if err != nil {
130                 return uploadPart, err
131         }
132         defer fd.Close()
133         fd.Seek(startPosition, os.SEEK_SET)
134
135         if partNumber < 1 {
136                 return uploadPart, fmt.Errorf("partNumber:%d is smaller than 1", partNumber)
137         }
138
139         cipherData := cryptoContext.ContentCipher.GetCipherData().Clone()
140         // calculate iv based on part number
141         if partNumber > 1 {
142                 cipherData.SeekIV(uint64(partNumber-1) * uint64(cryptoContext.PartSize))
143         }
144
145         // for parallel upload part
146         partCC, _ := cryptoContext.ContentCipher.Clone(cipherData)
147         cryptoReader, err := partCC.EncryptContent(fd)
148         if err != nil {
149                 return uploadPart, err
150         }
151
152         encryptedLen := partCC.GetEncryptedLen(partSize)
153         opts := addCryptoHeaders(options, partCC.GetCipherData())
154         if cryptoContext.DataSize > 0 {
155                 opts = append(opts, oss.Meta(OssClientSideEncryptionDataSize, strconv.FormatInt(cryptoContext.DataSize, 10)))
156         }
157         opts = append(opts, oss.Meta(OssClientSideEncryptionPartSize, strconv.FormatInt(cryptoContext.PartSize, 10)))
158
159         request := &oss.UploadPartRequest{
160                 InitResult: &imur,
161                 Reader:     cryptoReader,
162                 PartSize:   encryptedLen,
163                 PartNumber: partNumber,
164         }
165         result, err := bucket.Bucket.DoUploadPart(request, opts)
166         return result.Part, err
167 }
168
169 // UploadPartCopy uploads part copy
170 func (bucket CryptoBucket) UploadPartCopy(imur oss.InitiateMultipartUploadResult, srcBucketName, srcObjectKey string,
171         startPosition, partSize int64, partNumber int, cryptoContext PartCryptoContext, options ...oss.Option) (oss.UploadPart, error) {
172         var uploadPart = oss.UploadPart{}
173         return uploadPart, fmt.Errorf("CryptoBucket doesn't support UploadPartCopy")
174 }