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