@@ -26,6 +26,8 @@ import (
26
26
"strconv"
27
27
"strings"
28
28
"time"
29
+
30
+ md5simd "github.com/minio/md5-simd"
29
31
)
30
32
31
33
// Reference for constants used below -
@@ -90,28 +92,28 @@ func getStreamLength(dataLen, chunkSize int64, trailers http.Header) int64 {
90
92
91
93
// buildChunkStringToSign - returns the string to sign given chunk data
92
94
// and previous signature.
93
- func buildChunkStringToSign (t time.Time , region , previousSig string , chunkData [] byte ) string {
95
+ func buildChunkStringToSign (t time.Time , region , previousSig , chunkChecksum string ) string {
94
96
stringToSignParts := []string {
95
97
streamingPayloadHdr ,
96
98
t .Format (iso8601DateFormat ),
97
99
getScope (region , t , ServiceTypeS3 ),
98
100
previousSig ,
99
101
emptySHA256 ,
100
- hex . EncodeToString ( sum256 ( chunkData )) ,
102
+ chunkChecksum ,
101
103
}
102
104
103
105
return strings .Join (stringToSignParts , "\n " )
104
106
}
105
107
106
108
// buildTrailerChunkStringToSign - returns the string to sign given chunk data
107
109
// and previous signature.
108
- func buildTrailerChunkStringToSign (t time.Time , region , previousSig string , chunkData [] byte ) string {
110
+ func buildTrailerChunkStringToSign (t time.Time , region , previousSig , chunkChecksum string ) string {
109
111
stringToSignParts := []string {
110
112
streamingTrailerHdr ,
111
113
t .Format (iso8601DateFormat ),
112
114
getScope (region , t , ServiceTypeS3 ),
113
115
previousSig ,
114
- hex . EncodeToString ( sum256 ( chunkData )) ,
116
+ chunkChecksum ,
115
117
}
116
118
117
119
return strings .Join (stringToSignParts , "\n " )
@@ -148,21 +150,21 @@ func buildChunkHeader(chunkLen int64, signature string) []byte {
148
150
}
149
151
150
152
// buildChunkSignature - returns chunk signature for a given chunk and previous signature.
151
- func buildChunkSignature (chunkData [] byte , reqTime time.Time , region ,
153
+ func buildChunkSignature (chunkCheckSum string , reqTime time.Time , region ,
152
154
previousSignature , secretAccessKey string ,
153
155
) string {
154
156
chunkStringToSign := buildChunkStringToSign (reqTime , region ,
155
- previousSignature , chunkData )
157
+ previousSignature , chunkCheckSum )
156
158
signingKey := getSigningKey (secretAccessKey , region , reqTime , ServiceTypeS3 )
157
159
return getSignature (signingKey , chunkStringToSign )
158
160
}
159
161
160
162
// buildChunkSignature - returns chunk signature for a given chunk and previous signature.
161
- func buildTrailerChunkSignature (chunkData [] byte , reqTime time.Time , region ,
163
+ func buildTrailerChunkSignature (chunkChecksum string , reqTime time.Time , region ,
162
164
previousSignature , secretAccessKey string ,
163
165
) string {
164
166
chunkStringToSign := buildTrailerChunkStringToSign (reqTime , region ,
165
- previousSignature , chunkData )
167
+ previousSignature , chunkChecksum )
166
168
signingKey := getSigningKey (secretAccessKey , region , reqTime , ServiceTypeS3 )
167
169
return getSignature (signingKey , chunkStringToSign )
168
170
}
@@ -202,12 +204,17 @@ type StreamingReader struct {
202
204
totalChunks int
203
205
lastChunkSize int
204
206
trailer http.Header
207
+ sh256 md5simd.Hasher
205
208
}
206
209
207
210
// signChunk - signs a chunk read from s.baseReader of chunkLen size.
208
211
func (s * StreamingReader ) signChunk (chunkLen int , addCrLf bool ) {
209
212
// Compute chunk signature for next header
210
- signature := buildChunkSignature (s .chunkBuf [:chunkLen ], s .reqTime ,
213
+ s .sh256 .Reset ()
214
+ s .sh256 .Write (s .chunkBuf [:chunkLen ])
215
+ chunckChecksum := hex .EncodeToString (s .sh256 .Sum (nil ))
216
+
217
+ signature := buildChunkSignature (chunckChecksum , s .reqTime ,
211
218
s .region , s .prevSignature , s .secretAccessKey )
212
219
213
220
// For next chunk signature computation
@@ -239,8 +246,11 @@ func (s *StreamingReader) addSignedTrailer(h http.Header) {
239
246
s .chunkBuf = append (s .chunkBuf , []byte (strings .ToLower (k )+ trailerKVSeparator + v [0 ]+ "\n " )... )
240
247
}
241
248
249
+ s .sh256 .Reset ()
250
+ s .sh256 .Write (s .chunkBuf )
251
+ chunkChecksum := hex .EncodeToString (s .sh256 .Sum (nil ))
242
252
// Compute chunk signature
243
- signature := buildTrailerChunkSignature (s . chunkBuf , s .reqTime ,
253
+ signature := buildTrailerChunkSignature (chunkChecksum , s .reqTime ,
244
254
s .region , s .prevSignature , s .secretAccessKey )
245
255
246
256
// For next chunk signature computation
@@ -273,7 +283,7 @@ func (s *StreamingReader) setStreamingAuthHeader(req *http.Request) {
273
283
// StreamingSignV4 - provides chunked upload signatureV4 support by
274
284
// implementing io.Reader.
275
285
func StreamingSignV4 (req * http.Request , accessKeyID , secretAccessKey , sessionToken ,
276
- region string , dataLen int64 , reqTime time.Time ,
286
+ region string , dataLen int64 , reqTime time.Time , sh256 md5simd. Hasher ,
277
287
) * http.Request {
278
288
// Set headers needed for streaming signature.
279
289
prepareStreamingRequest (req , sessionToken , dataLen , reqTime )
@@ -294,6 +304,7 @@ func StreamingSignV4(req *http.Request, accessKeyID, secretAccessKey, sessionTok
294
304
chunkNum : 1 ,
295
305
totalChunks : int ((dataLen + payloadChunkSize - 1 )/ payloadChunkSize ) + 1 ,
296
306
lastChunkSize : int (dataLen % payloadChunkSize ),
307
+ sh256 : sh256 ,
297
308
}
298
309
if len (req .Trailer ) > 0 {
299
310
stReader .trailer = req .Trailer
@@ -384,5 +395,9 @@ func (s *StreamingReader) Read(buf []byte) (int, error) {
384
395
385
396
// Close - this method makes underlying io.ReadCloser's Close method available.
386
397
func (s * StreamingReader ) Close () error {
398
+ if s .sh256 != nil {
399
+ s .sh256 .Close ()
400
+ s .sh256 = nil
401
+ }
387
402
return s .baseReadCloser .Close ()
388
403
}
0 commit comments