storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/encryption-v1_test.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2017, 2018 MinIO, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package cmd 18 19 import ( 20 "bytes" 21 "encoding/base64" 22 "net/http" 23 "testing" 24 25 humanize "github.com/dustin/go-humanize" 26 "github.com/minio/minio-go/v7/pkg/encrypt" 27 "github.com/minio/sio" 28 29 "storj.io/minio/cmd/crypto" 30 xhttp "storj.io/minio/cmd/http" 31 ) 32 33 var encryptRequestTests = []struct { 34 header map[string]string 35 metadata map[string]string 36 }{ 37 { 38 header: map[string]string{ 39 xhttp.AmzServerSideEncryptionCustomerAlgorithm: "AES256", 40 xhttp.AmzServerSideEncryptionCustomerKey: "XAm0dRrJsEsyPb1UuFNezv1bl9hxuYsgUVC/MUctE2k=", 41 xhttp.AmzServerSideEncryptionCustomerKeyMD5: "bY4wkxQejw9mUJfo72k53A==", 42 }, 43 metadata: map[string]string{}, 44 }, 45 { 46 header: map[string]string{ 47 xhttp.AmzServerSideEncryptionCustomerAlgorithm: "AES256", 48 xhttp.AmzServerSideEncryptionCustomerKey: "XAm0dRrJsEsyPb1UuFNezv1bl9hxuYsgUVC/MUctE2k=", 49 xhttp.AmzServerSideEncryptionCustomerKeyMD5: "bY4wkxQejw9mUJfo72k53A==", 50 }, 51 metadata: map[string]string{ 52 xhttp.AmzServerSideEncryptionCustomerKey: "XAm0dRrJsEsyPb1UuFNezv1bl9hxuYsgUVC/MUctE2k=", 53 }, 54 }, 55 } 56 57 func TestEncryptRequest(t *testing.T) { 58 defer func(flag bool) { GlobalIsTLS = flag }(GlobalIsTLS) 59 GlobalIsTLS = true 60 for i, test := range encryptRequestTests { 61 content := bytes.NewReader(make([]byte, 64)) 62 req := &http.Request{Header: http.Header{}} 63 for k, v := range test.header { 64 req.Header.Set(k, v) 65 } 66 _, _, err := EncryptRequest(content, req, "bucket", "object", test.metadata) 67 68 if err != nil { 69 t.Fatalf("Test %d: Failed to encrypt request: %v", i, err) 70 } 71 if kdf, ok := test.metadata[crypto.MetaAlgorithm]; !ok { 72 t.Errorf("Test %d: ServerSideEncryptionKDF must be part of metadata: %v", i, kdf) 73 } 74 if iv, ok := test.metadata[crypto.MetaIV]; !ok { 75 t.Errorf("Test %d: crypto.SSEIV must be part of metadata: %v", i, iv) 76 } 77 if mac, ok := test.metadata[crypto.MetaSealedKeySSEC]; !ok { 78 t.Errorf("Test %d: ServerSideEncryptionKeyMAC must be part of metadata: %v", i, mac) 79 } 80 } 81 } 82 83 var decryptObjectInfoTests = []struct { 84 info ObjectInfo 85 request *http.Request 86 expErr error 87 }{ 88 { 89 info: ObjectInfo{Size: 100}, 90 request: &http.Request{Header: http.Header{}}, 91 expErr: nil, 92 }, 93 { 94 info: ObjectInfo{Size: 100, UserDefined: map[string]string{crypto.MetaAlgorithm: crypto.InsecureSealAlgorithm}}, 95 request: &http.Request{Header: http.Header{xhttp.AmzServerSideEncryption: []string{xhttp.AmzEncryptionAES}}}, 96 expErr: nil, 97 }, 98 { 99 info: ObjectInfo{Size: 0, UserDefined: map[string]string{crypto.MetaAlgorithm: crypto.InsecureSealAlgorithm}}, 100 request: &http.Request{Header: http.Header{xhttp.AmzServerSideEncryption: []string{xhttp.AmzEncryptionAES}}}, 101 expErr: nil, 102 }, 103 { 104 info: ObjectInfo{Size: 100, UserDefined: map[string]string{crypto.MetaSealedKeySSEC: "EAAfAAAAAAD7v1hQq3PFRUHsItalxmrJqrOq6FwnbXNarxOOpb8jTWONPPKyM3Gfjkjyj6NCf+aB/VpHCLCTBA=="}}, 105 request: &http.Request{Header: http.Header{}}, 106 expErr: errEncryptedObject, 107 }, 108 { 109 info: ObjectInfo{Size: 100, UserDefined: map[string]string{}}, 110 request: &http.Request{Method: http.MethodGet, Header: http.Header{xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES}}}, 111 expErr: errInvalidEncryptionParameters, 112 }, 113 { 114 info: ObjectInfo{Size: 100, UserDefined: map[string]string{}}, 115 request: &http.Request{Method: http.MethodHead, Header: http.Header{xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES}}}, 116 expErr: errInvalidEncryptionParameters, 117 }, 118 { 119 info: ObjectInfo{Size: 31, UserDefined: map[string]string{crypto.MetaAlgorithm: crypto.InsecureSealAlgorithm}}, 120 request: &http.Request{Header: http.Header{xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES}}}, 121 expErr: errObjectTampered, 122 }, 123 } 124 125 func TestDecryptObjectInfo(t *testing.T) { 126 for i, test := range decryptObjectInfoTests { 127 if encrypted, err := DecryptObjectInfo(&test.info, test.request); err != test.expErr { 128 t.Errorf("Test %d: Decryption returned wrong error code: got %d , want %d", i, err, test.expErr) 129 } else if _, enc := crypto.IsEncrypted(test.info.UserDefined); encrypted && enc != encrypted { 130 t.Errorf("Test %d: Decryption thinks object is encrypted but it is not", i) 131 } else if !encrypted && enc != encrypted { 132 t.Errorf("Test %d: Decryption thinks object is not encrypted but it is", i) 133 } 134 } 135 } 136 137 var decryptETagTests = []struct { 138 ObjectKey crypto.ObjectKey 139 ObjectInfo ObjectInfo 140 ShouldFail bool 141 ETag string 142 }{ 143 { 144 ObjectKey: [32]byte{}, 145 ObjectInfo: ObjectInfo{ETag: "20000f00f27834c9a2654927546df57f9e998187496394d4ee80f3d9978f85f3c7d81f72600cdbe03d80dc5a13d69354"}, 146 ETag: "8ad3fe6b84bf38489e95c701c84355b6", 147 }, 148 { 149 ObjectKey: [32]byte{}, 150 ObjectInfo: ObjectInfo{ETag: "20000f00f27834c9a2654927546df57f9e998187496394d4ee80f3d9978f85f3c7d81f72600cdbe03d80dc5a13d6935"}, 151 ETag: "", 152 ShouldFail: true, // ETag is not a valid hex value 153 }, 154 { 155 ObjectKey: [32]byte{}, 156 ObjectInfo: ObjectInfo{ETag: "00000f00f27834c9a2654927546df57f9e998187496394d4ee80f3d9978f85f3c7d81f72600cdbe03d80dc5a13d69354"}, 157 ETag: "", 158 ShouldFail: true, // modified ETag 159 }, 160 161 // Special tests for ETags that end with a '-x' 162 { 163 ObjectKey: [32]byte{}, 164 ObjectInfo: ObjectInfo{ETag: "916516b396f0f4d4f2a0e7177557bec4-1"}, 165 ETag: "916516b396f0f4d4f2a0e7177557bec4-1", 166 }, 167 { 168 ObjectKey: [32]byte{}, 169 ObjectInfo: ObjectInfo{ETag: "916516b396f0f4d4f2a0e7177557bec4-738"}, 170 ETag: "916516b396f0f4d4f2a0e7177557bec4-738", 171 }, 172 { 173 ObjectKey: [32]byte{}, 174 ObjectInfo: ObjectInfo{ETag: "916516b396f0f4d4f2a0e7177557bec4-Q"}, 175 ETag: "", 176 ShouldFail: true, // Q is not a number 177 }, 178 { 179 ObjectKey: [32]byte{}, 180 ObjectInfo: ObjectInfo{ETag: "16516b396f0f4d4f2a0e7177557bec4-1"}, 181 ETag: "", 182 ShouldFail: true, // ETag prefix is not a valid hex value 183 }, 184 { 185 ObjectKey: [32]byte{}, 186 ObjectInfo: ObjectInfo{ETag: "16516b396f0f4d4f2a0e7177557bec4-1-2"}, 187 ETag: "", 188 ShouldFail: true, // ETag contains multiple: - 189 }, 190 } 191 192 func TestDecryptETag(t *testing.T) { 193 for i, test := range decryptETagTests { 194 etag, err := DecryptETag(test.ObjectKey, test.ObjectInfo) 195 if err != nil && !test.ShouldFail { 196 t.Fatalf("Test %d: should succeed but failed: %v", i, err) 197 } 198 if err == nil && test.ShouldFail { 199 t.Fatalf("Test %d: should fail but succeeded", i) 200 } 201 if err == nil { 202 if etag != test.ETag { 203 t.Fatalf("Test %d: ETag mismatch: got %s - want %s", i, etag, test.ETag) 204 } 205 } 206 } 207 } 208 209 // Tests for issue reproduced when getting the right encrypted 210 // offset of the object. 211 func TestGetDecryptedRange_Issue50(t *testing.T) { 212 rs, err := parseRequestRangeSpec("bytes=594870256-594870263") 213 if err != nil { 214 t.Fatal(err) 215 } 216 217 objInfo := ObjectInfo{ 218 Bucket: "bucket", 219 Name: "object", 220 Size: 595160760, 221 UserDefined: map[string]string{ 222 crypto.MetaMultipart: "", 223 crypto.MetaIV: "HTexa=", 224 crypto.MetaAlgorithm: "DAREv2-HMAC-SHA256", 225 crypto.MetaSealedKeySSEC: "IAA8PGAA==", 226 ReservedMetadataPrefix + "actual-size": "594870264", 227 "content-type": "application/octet-stream", 228 "etag": "166b1545b4c1535294ee0686678bea8c-2", 229 }, 230 Parts: []ObjectPartInfo{ 231 { 232 Number: 1, 233 Size: 297580380, 234 ActualSize: 297435132, 235 }, 236 { 237 Number: 2, 238 Size: 297580380, 239 ActualSize: 297435132, 240 }, 241 }, 242 } 243 244 encOff, encLength, skipLen, seqNumber, partStart, err := objInfo.GetDecryptedRange(rs) 245 if err != nil { 246 t.Fatalf("Test: failed %s", err) 247 } 248 if encOff != 595127964 { 249 t.Fatalf("Test: expected %d, got %d", 595127964, encOff) 250 } 251 if encLength != 32796 { 252 t.Fatalf("Test: expected %d, got %d", 32796, encLength) 253 } 254 if skipLen != 32756 { 255 t.Fatalf("Test: expected %d, got %d", 32756, skipLen) 256 } 257 if seqNumber != 4538 { 258 t.Fatalf("Test: expected %d, got %d", 4538, seqNumber) 259 } 260 if partStart != 1 { 261 t.Fatalf("Test: expected %d, got %d", 1, partStart) 262 } 263 } 264 265 func TestGetDecryptedRange(t *testing.T) { 266 var ( 267 pkgSz = int64(64) * humanize.KiByte 268 minPartSz = int64(5) * humanize.MiByte 269 maxPartSz = int64(5) * humanize.GiByte 270 271 getEncSize = func(s int64) int64 { 272 v, _ := sio.EncryptedSize(uint64(s)) 273 return int64(v) 274 } 275 udMap = func(isMulti bool) map[string]string { 276 m := map[string]string{ 277 crypto.MetaAlgorithm: crypto.InsecureSealAlgorithm, 278 crypto.MetaMultipart: "1", 279 } 280 if !isMulti { 281 delete(m, crypto.MetaMultipart) 282 } 283 return m 284 } 285 ) 286 287 // Single part object tests 288 var ( 289 mkSPObj = func(s int64) ObjectInfo { 290 return ObjectInfo{ 291 Size: getEncSize(s), 292 UserDefined: udMap(false), 293 } 294 } 295 ) 296 297 testSP := []struct { 298 decSz int64 299 oi ObjectInfo 300 }{ 301 {0, mkSPObj(0)}, 302 {1, mkSPObj(1)}, 303 {pkgSz - 1, mkSPObj(pkgSz - 1)}, 304 {pkgSz, mkSPObj(pkgSz)}, 305 {2*pkgSz - 1, mkSPObj(2*pkgSz - 1)}, 306 {minPartSz, mkSPObj(minPartSz)}, 307 {maxPartSz, mkSPObj(maxPartSz)}, 308 } 309 310 for i, test := range testSP { 311 { 312 // nil range 313 o, l, skip, sn, ps, err := test.oi.GetDecryptedRange(nil) 314 if err != nil { 315 t.Errorf("Case %d: unexpected err: %v", i, err) 316 } 317 if skip != 0 || sn != 0 || ps != 0 || o != 0 || l != getEncSize(test.decSz) { 318 t.Errorf("Case %d: test failed: %d %d %d %d %d", i, o, l, skip, sn, ps) 319 } 320 } 321 322 if test.decSz >= 10 { 323 // first 10 bytes 324 o, l, skip, sn, ps, err := test.oi.GetDecryptedRange(&HTTPRangeSpec{false, 0, 9}) 325 if err != nil { 326 t.Errorf("Case %d: unexpected err: %v", i, err) 327 } 328 var rLen = pkgSz + 32 329 if test.decSz < pkgSz { 330 rLen = test.decSz + 32 331 } 332 if skip != 0 || sn != 0 || ps != 0 || o != 0 || l != rLen { 333 t.Errorf("Case %d: test failed: %d %d %d %d %d", i, o, l, skip, sn, ps) 334 } 335 } 336 337 kb32 := int64(32) * humanize.KiByte 338 if test.decSz >= (64+32)*humanize.KiByte { 339 // Skip the first 32Kib, and read the next 64Kib 340 o, l, skip, sn, ps, err := test.oi.GetDecryptedRange(&HTTPRangeSpec{false, kb32, 3*kb32 - 1}) 341 if err != nil { 342 t.Errorf("Case %d: unexpected err: %v", i, err) 343 } 344 var rLen = (pkgSz + 32) * 2 345 if test.decSz < 2*pkgSz { 346 rLen = (pkgSz + 32) + (test.decSz - pkgSz + 32) 347 } 348 if skip != kb32 || sn != 0 || ps != 0 || o != 0 || l != rLen { 349 t.Errorf("Case %d: test failed: %d %d %d %d %d", i, o, l, skip, sn, ps) 350 } 351 } 352 353 if test.decSz >= (64*2+32)*humanize.KiByte { 354 // Skip the first 96Kib and read the next 64Kib 355 o, l, skip, sn, ps, err := test.oi.GetDecryptedRange(&HTTPRangeSpec{false, 3 * kb32, 5*kb32 - 1}) 356 if err != nil { 357 t.Errorf("Case %d: unexpected err: %v", i, err) 358 } 359 var rLen = (pkgSz + 32) * 2 360 if test.decSz-pkgSz < 2*pkgSz { 361 rLen = (pkgSz + 32) + (test.decSz - pkgSz + 32*2) 362 } 363 if skip != kb32 || sn != 1 || ps != 0 || o != pkgSz+32 || l != rLen { 364 t.Errorf("Case %d: test failed: %d %d %d %d %d", i, o, l, skip, sn, ps) 365 } 366 } 367 368 } 369 370 // Multipart object tests 371 var ( 372 // make a multipart object-info given part sizes 373 mkMPObj = func(sizes []int64) ObjectInfo { 374 r := make([]ObjectPartInfo, len(sizes)) 375 sum := int64(0) 376 for i, s := range sizes { 377 r[i].Number = i 378 r[i].Size = getEncSize(s) 379 sum += r[i].Size 380 } 381 return ObjectInfo{ 382 Size: sum, 383 UserDefined: udMap(true), 384 Parts: r, 385 } 386 } 387 // Simple useful utilities 388 repeat = func(k int64, n int) []int64 { 389 a := []int64{} 390 for i := 0; i < n; i++ { 391 a = append(a, k) 392 } 393 return a 394 } 395 lsum = func(s []int64) int64 { 396 sum := int64(0) 397 for _, i := range s { 398 if i < 0 { 399 return -1 400 } 401 sum += i 402 } 403 return sum 404 } 405 esum = func(oi ObjectInfo) int64 { 406 sum := int64(0) 407 for _, i := range oi.Parts { 408 sum += i.Size 409 } 410 return sum 411 } 412 ) 413 414 s1 := []int64{5487701, 5487799, 3} 415 s2 := repeat(5487701, 5) 416 s3 := repeat(maxPartSz, 10000) 417 testMPs := []struct { 418 decSizes []int64 419 oi ObjectInfo 420 }{ 421 {s1, mkMPObj(s1)}, 422 {s2, mkMPObj(s2)}, 423 {s3, mkMPObj(s3)}, 424 } 425 426 // This function is a reference (re-)implementation of 427 // decrypted range computation, written solely for the purpose 428 // of the unit tests. 429 // 430 // `s` gives the decrypted part sizes, and the other 431 // parameters describe the desired read segment. When 432 // `isFromEnd` is true, `skipLen` argument is ignored. 433 decryptedRangeRef := func(s []int64, skipLen, readLen int64, isFromEnd bool) (o, l, skip int64, sn uint32, ps int) { 434 oSize := lsum(s) 435 if isFromEnd { 436 skipLen = oSize - readLen 437 } 438 if skipLen < 0 || readLen < 0 || oSize < 0 || skipLen+readLen > oSize { 439 t.Fatalf("Impossible read specified: %d %d %d", skipLen, readLen, oSize) 440 } 441 442 var cumulativeSum, cumulativeEncSum int64 443 toRead := readLen 444 readStart := false 445 for i, v := range s { 446 partOffset := int64(0) 447 partDarePkgOffset := int64(0) 448 if !readStart && cumulativeSum+v > skipLen { 449 // Read starts at the current part 450 readStart = true 451 452 partOffset = skipLen - cumulativeSum 453 454 // All return values except `l` are 455 // calculated here. 456 sn = uint32(partOffset / pkgSz) 457 skip = partOffset % pkgSz 458 ps = i 459 o = cumulativeEncSum + int64(sn)*(pkgSz+32) 460 461 partDarePkgOffset = partOffset - skip 462 } 463 if readStart { 464 currentPartBytes := v - partOffset 465 currentPartDareBytes := v - partDarePkgOffset 466 if currentPartBytes < toRead { 467 toRead -= currentPartBytes 468 l += getEncSize(currentPartDareBytes) 469 } else { 470 // current part has the last 471 // byte required 472 lbPartOffset := partOffset + toRead - 1 473 474 // round up the lbPartOffset 475 // to the end of the 476 // corresponding DARE package 477 lbPkgEndOffset := lbPartOffset - (lbPartOffset % pkgSz) + pkgSz 478 if lbPkgEndOffset > v { 479 lbPkgEndOffset = v 480 } 481 bytesToDrop := v - lbPkgEndOffset 482 483 // Last segment to update `l` 484 l += getEncSize(currentPartDareBytes - bytesToDrop) 485 break 486 } 487 } 488 489 cumulativeSum += v 490 cumulativeEncSum += getEncSize(v) 491 } 492 return 493 } 494 495 for i, test := range testMPs { 496 { 497 // nil range 498 o, l, skip, sn, ps, err := test.oi.GetDecryptedRange(nil) 499 if err != nil { 500 t.Errorf("Case %d: unexpected err: %v", i, err) 501 } 502 if o != 0 || l != esum(test.oi) || skip != 0 || sn != 0 || ps != 0 { 503 t.Errorf("Case %d: test failed: %d %d %d %d %d", i, o, l, skip, sn, ps) 504 } 505 } 506 507 // Skip 1Mib and read 1Mib (in the decrypted object) 508 // 509 // The check below ensures the object is large enough 510 // for the read. 511 if lsum(test.decSizes) >= 2*humanize.MiByte { 512 skipLen, readLen := int64(1)*humanize.MiByte, int64(1)*humanize.MiByte 513 o, l, skip, sn, ps, err := test.oi.GetDecryptedRange(&HTTPRangeSpec{false, skipLen, skipLen + readLen - 1}) 514 if err != nil { 515 t.Errorf("Case %d: unexpected err: %v", i, err) 516 } 517 518 oRef, lRef, skipRef, snRef, psRef := decryptedRangeRef(test.decSizes, skipLen, readLen, false) 519 if o != oRef || l != lRef || skip != skipRef || sn != snRef || ps != psRef { 520 t.Errorf("Case %d: test failed: %d %d %d %d %d (Ref: %d %d %d %d %d)", 521 i, o, l, skip, sn, ps, oRef, lRef, skipRef, snRef, psRef) 522 } 523 } 524 525 // Read the last 6Mib+1 bytes of the (decrypted) 526 // object 527 // 528 // The check below ensures the object is large enough 529 // for the read. 530 readLen := int64(6)*humanize.MiByte + 1 531 if lsum(test.decSizes) >= readLen { 532 o, l, skip, sn, ps, err := test.oi.GetDecryptedRange(&HTTPRangeSpec{true, -readLen, -1}) 533 if err != nil { 534 t.Errorf("Case %d: unexpected err: %v", i, err) 535 } 536 537 oRef, lRef, skipRef, snRef, psRef := decryptedRangeRef(test.decSizes, 0, readLen, true) 538 if o != oRef || l != lRef || skip != skipRef || sn != snRef || ps != psRef { 539 t.Errorf("Case %d: test failed: %d %d %d %d %d (Ref: %d %d %d %d %d)", 540 i, o, l, skip, sn, ps, oRef, lRef, skipRef, snRef, psRef) 541 } 542 } 543 544 } 545 } 546 547 var getDefaultOptsTests = []struct { 548 headers http.Header 549 copySource bool 550 metadata map[string]string 551 encryptionType encrypt.Type 552 err error 553 }{ 554 {headers: http.Header{xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{"AES256"}, 555 xhttp.AmzServerSideEncryptionCustomerKey: []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 556 xhttp.AmzServerSideEncryptionCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}}, 557 copySource: false, 558 metadata: nil, 559 encryptionType: encrypt.SSEC, 560 err: nil}, // 0 561 {headers: http.Header{xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{"AES256"}, 562 xhttp.AmzServerSideEncryptionCustomerKey: []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 563 xhttp.AmzServerSideEncryptionCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}}, 564 copySource: true, 565 metadata: nil, 566 encryptionType: "", 567 err: nil}, // 1 568 {headers: http.Header{xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{"AES256"}, 569 xhttp.AmzServerSideEncryptionCustomerKey: []string{"Mz"}, 570 xhttp.AmzServerSideEncryptionCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}}, 571 copySource: false, 572 metadata: nil, 573 encryptionType: "", 574 err: crypto.ErrInvalidCustomerKey}, // 2 575 {headers: http.Header{xhttp.AmzServerSideEncryption: []string{"AES256"}}, 576 copySource: false, 577 metadata: nil, 578 encryptionType: encrypt.S3, 579 err: nil}, // 3 580 {headers: http.Header{}, 581 copySource: false, 582 metadata: map[string]string{crypto.MetaSealedKeyS3: base64.StdEncoding.EncodeToString(make([]byte, 64)), 583 crypto.MetaKeyID: "kms-key", 584 crypto.MetaDataEncryptionKey: "m-key"}, 585 encryptionType: encrypt.S3, 586 err: nil}, // 4 587 {headers: http.Header{}, 588 copySource: true, 589 metadata: map[string]string{crypto.MetaSealedKeyS3: base64.StdEncoding.EncodeToString(make([]byte, 64)), 590 crypto.MetaKeyID: "kms-key", 591 crypto.MetaDataEncryptionKey: "m-key"}, 592 encryptionType: "", 593 err: nil}, // 5 594 {headers: http.Header{xhttp.AmzServerSideEncryptionCopyCustomerAlgorithm: []string{"AES256"}, 595 xhttp.AmzServerSideEncryptionCopyCustomerKey: []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 596 xhttp.AmzServerSideEncryptionCopyCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}}, 597 copySource: true, 598 metadata: nil, 599 encryptionType: encrypt.SSEC, 600 err: nil}, // 6 601 {headers: http.Header{xhttp.AmzServerSideEncryptionCopyCustomerAlgorithm: []string{"AES256"}, 602 xhttp.AmzServerSideEncryptionCopyCustomerKey: []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, 603 xhttp.AmzServerSideEncryptionCopyCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="}}, 604 copySource: false, 605 metadata: nil, 606 encryptionType: "", 607 err: nil}, // 7 608 } 609 610 func TestGetDefaultOpts(t *testing.T) { 611 for i, test := range getDefaultOptsTests { 612 opts, err := getDefaultOpts(test.headers, test.copySource, test.metadata) 613 if test.err != err { 614 t.Errorf("Case %d: expected err: %v , actual err: %v", i, test.err, err) 615 } 616 if err == nil { 617 if opts.ServerSideEncryption == nil && test.encryptionType != "" { 618 t.Errorf("Case %d: expected opts to be of %v encryption type", i, test.encryptionType) 619 } 620 if opts.ServerSideEncryption != nil && test.encryptionType != opts.ServerSideEncryption.Type() { 621 t.Errorf("Case %d: expected opts to have encryption type %v but was %v ", i, test.encryptionType, opts.ServerSideEncryption.Type()) 622 } 623 } 624 } 625 }