github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/crypto/metadata_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 crypto
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/base64"
    23  	"encoding/hex"
    24  	"testing"
    25  
    26  	"github.com/minio/minio/internal/logger"
    27  )
    28  
    29  var isMultipartTests = []struct {
    30  	Metadata  map[string]string
    31  	Multipart bool
    32  }{
    33  	{Multipart: true, Metadata: map[string]string{MetaMultipart: ""}},                          // 0
    34  	{Multipart: true, Metadata: map[string]string{"X-Minio-Internal-Encrypted-Multipart": ""}}, // 1
    35  	{Multipart: true, Metadata: map[string]string{MetaMultipart: "some-value"}},                // 2
    36  	{Multipart: false, Metadata: map[string]string{"": ""}},                                    // 3
    37  	{Multipart: false, Metadata: map[string]string{"X-Minio-Internal-EncryptedMultipart": ""}}, // 4
    38  }
    39  
    40  func TestIsMultipart(t *testing.T) {
    41  	for i, test := range isMultipartTests {
    42  		if isMultipart := IsMultiPart(test.Metadata); isMultipart != test.Multipart {
    43  			t.Errorf("Test %d: got '%v' - want '%v'", i, isMultipart, test.Multipart)
    44  		}
    45  	}
    46  }
    47  
    48  var isEncryptedTests = []struct {
    49  	Metadata  map[string]string
    50  	Encrypted bool
    51  }{
    52  	{Encrypted: true, Metadata: map[string]string{MetaMultipart: ""}},                              // 0
    53  	{Encrypted: true, Metadata: map[string]string{MetaIV: ""}},                                     // 1
    54  	{Encrypted: true, Metadata: map[string]string{MetaAlgorithm: ""}},                              // 2
    55  	{Encrypted: true, Metadata: map[string]string{MetaSealedKeySSEC: ""}},                          // 3
    56  	{Encrypted: true, Metadata: map[string]string{MetaSealedKeyS3: ""}},                            // 4
    57  	{Encrypted: true, Metadata: map[string]string{MetaKeyID: ""}},                                  // 5
    58  	{Encrypted: true, Metadata: map[string]string{MetaDataEncryptionKey: ""}},                      // 6
    59  	{Encrypted: false, Metadata: map[string]string{"": ""}},                                        // 7
    60  	{Encrypted: false, Metadata: map[string]string{"X-Minio-Internal-Server-Side-Encryption": ""}}, // 8
    61  }
    62  
    63  func TestIsEncrypted(t *testing.T) {
    64  	for i, test := range isEncryptedTests {
    65  		if _, isEncrypted := IsEncrypted(test.Metadata); isEncrypted != test.Encrypted {
    66  			t.Errorf("Test %d: got '%v' - want '%v'", i, isEncrypted, test.Encrypted)
    67  		}
    68  	}
    69  }
    70  
    71  var s3IsEncryptedTests = []struct {
    72  	Metadata  map[string]string
    73  	Encrypted bool
    74  }{
    75  	{Encrypted: false, Metadata: map[string]string{MetaMultipart: ""}},                             // 0
    76  	{Encrypted: false, Metadata: map[string]string{MetaIV: ""}},                                    // 1
    77  	{Encrypted: false, Metadata: map[string]string{MetaAlgorithm: ""}},                             // 2
    78  	{Encrypted: false, Metadata: map[string]string{MetaSealedKeySSEC: ""}},                         // 3
    79  	{Encrypted: true, Metadata: map[string]string{MetaSealedKeyS3: ""}},                            // 4
    80  	{Encrypted: false, Metadata: map[string]string{MetaKeyID: ""}},                                 // 5
    81  	{Encrypted: false, Metadata: map[string]string{MetaDataEncryptionKey: ""}},                     // 6
    82  	{Encrypted: false, Metadata: map[string]string{"": ""}},                                        // 7
    83  	{Encrypted: false, Metadata: map[string]string{"X-Minio-Internal-Server-Side-Encryption": ""}}, // 8
    84  }
    85  
    86  func TestS3IsEncrypted(t *testing.T) {
    87  	for i, test := range s3IsEncryptedTests {
    88  		if isEncrypted := S3.IsEncrypted(test.Metadata); isEncrypted != test.Encrypted {
    89  			t.Errorf("Test %d: got '%v' - want '%v'", i, isEncrypted, test.Encrypted)
    90  		}
    91  	}
    92  }
    93  
    94  var ssecIsEncryptedTests = []struct {
    95  	Metadata  map[string]string
    96  	Encrypted bool
    97  }{
    98  	{Encrypted: false, Metadata: map[string]string{MetaMultipart: ""}},                             // 0
    99  	{Encrypted: false, Metadata: map[string]string{MetaIV: ""}},                                    // 1
   100  	{Encrypted: false, Metadata: map[string]string{MetaAlgorithm: ""}},                             // 2
   101  	{Encrypted: true, Metadata: map[string]string{MetaSealedKeySSEC: ""}},                          // 3
   102  	{Encrypted: false, Metadata: map[string]string{MetaSealedKeyS3: ""}},                           // 4
   103  	{Encrypted: false, Metadata: map[string]string{MetaKeyID: ""}},                                 // 5
   104  	{Encrypted: false, Metadata: map[string]string{MetaDataEncryptionKey: ""}},                     // 6
   105  	{Encrypted: false, Metadata: map[string]string{"": ""}},                                        // 7
   106  	{Encrypted: false, Metadata: map[string]string{"X-Minio-Internal-Server-Side-Encryption": ""}}, // 8
   107  }
   108  
   109  func TestSSECIsEncrypted(t *testing.T) {
   110  	for i, test := range ssecIsEncryptedTests {
   111  		if isEncrypted := SSEC.IsEncrypted(test.Metadata); isEncrypted != test.Encrypted {
   112  			t.Errorf("Test %d: got '%v' - want '%v'", i, isEncrypted, test.Encrypted)
   113  		}
   114  	}
   115  }
   116  
   117  var s3ParseMetadataTests = []struct {
   118  	Metadata    map[string]string
   119  	ExpectedErr error
   120  
   121  	DataKey   []byte
   122  	KeyID     string
   123  	SealedKey SealedKey
   124  }{
   125  	{ExpectedErr: errMissingInternalIV, Metadata: map[string]string{}, DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{}}, // 0
   126  	{
   127  		ExpectedErr: errMissingInternalSealAlgorithm, Metadata: map[string]string{MetaIV: ""},
   128  		DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{},
   129  	}, // 1
   130  	{
   131  		ExpectedErr: Errorf("The object metadata is missing the internal sealed key for SSE-S3"),
   132  		Metadata:    map[string]string{MetaIV: "", MetaAlgorithm: ""}, DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{},
   133  	}, // 2
   134  	{
   135  		ExpectedErr: Errorf("The object metadata is missing the internal KMS key-ID for SSE-S3"),
   136  		Metadata:    map[string]string{MetaIV: "", MetaAlgorithm: "", MetaSealedKeyS3: "", MetaDataEncryptionKey: "IAAF0b=="}, DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{},
   137  	}, // 3
   138  	{
   139  		ExpectedErr: Errorf("The object metadata is missing the internal sealed KMS data key for SSE-S3"),
   140  		Metadata:    map[string]string{MetaIV: "", MetaAlgorithm: "", MetaSealedKeyS3: "", MetaKeyID: ""},
   141  		DataKey:     []byte{}, KeyID: "", SealedKey: SealedKey{},
   142  	}, // 4
   143  	{
   144  		ExpectedErr: errInvalidInternalIV,
   145  		Metadata:    map[string]string{MetaIV: "", MetaAlgorithm: "", MetaSealedKeyS3: "", MetaKeyID: "", MetaDataEncryptionKey: ""},
   146  		DataKey:     []byte{}, KeyID: "", SealedKey: SealedKey{},
   147  	}, // 5
   148  	{
   149  		ExpectedErr: errInvalidInternalSealAlgorithm,
   150  		Metadata: map[string]string{
   151  			MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: "", MetaSealedKeyS3: "", MetaKeyID: "", MetaDataEncryptionKey: "",
   152  		},
   153  		DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{},
   154  	}, // 6
   155  	{
   156  		ExpectedErr: Errorf("The internal sealed key for SSE-S3 is invalid"),
   157  		Metadata: map[string]string{
   158  			MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: SealAlgorithm, MetaSealedKeyS3: "",
   159  			MetaKeyID: "", MetaDataEncryptionKey: "",
   160  		},
   161  		DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{},
   162  	}, // 7
   163  	{
   164  		ExpectedErr: Errorf("The internal sealed KMS data key for SSE-S3 is invalid"),
   165  		Metadata: map[string]string{
   166  			MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: SealAlgorithm,
   167  			MetaSealedKeyS3: base64.StdEncoding.EncodeToString(make([]byte, 64)), MetaKeyID: "key-1",
   168  			MetaDataEncryptionKey: ".MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ=", // invalid base64
   169  		},
   170  		DataKey: []byte{}, KeyID: "key-1", SealedKey: SealedKey{},
   171  	}, // 8
   172  	{
   173  		ExpectedErr: nil,
   174  		Metadata: map[string]string{
   175  			MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: SealAlgorithm,
   176  			MetaSealedKeyS3: base64.StdEncoding.EncodeToString(make([]byte, 64)), MetaKeyID: "", MetaDataEncryptionKey: "",
   177  		},
   178  		DataKey: []byte{}, KeyID: "", SealedKey: SealedKey{Algorithm: SealAlgorithm},
   179  	}, // 9
   180  	{
   181  		ExpectedErr: nil,
   182  		Metadata: map[string]string{
   183  			MetaIV: base64.StdEncoding.EncodeToString(append([]byte{1}, make([]byte, 31)...)), MetaAlgorithm: SealAlgorithm,
   184  			MetaSealedKeyS3: base64.StdEncoding.EncodeToString(append([]byte{1}, make([]byte, 63)...)), MetaKeyID: "key-1",
   185  			MetaDataEncryptionKey: base64.StdEncoding.EncodeToString(make([]byte, 48)),
   186  		},
   187  		DataKey: make([]byte, 48), KeyID: "key-1", SealedKey: SealedKey{Algorithm: SealAlgorithm, Key: [64]byte{1}, IV: [32]byte{1}},
   188  	}, // 10
   189  }
   190  
   191  func TestS3ParseMetadata(t *testing.T) {
   192  	for i, test := range s3ParseMetadataTests {
   193  		keyID, dataKey, sealedKey, err := S3.ParseMetadata(test.Metadata)
   194  		if err != nil && test.ExpectedErr == nil {
   195  			t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr)
   196  		}
   197  		if err == nil && test.ExpectedErr != nil {
   198  			t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr)
   199  		}
   200  		if err != nil && test.ExpectedErr != nil {
   201  			if err.Error() != test.ExpectedErr.Error() {
   202  				t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr)
   203  			}
   204  		}
   205  		if !bytes.Equal(dataKey, test.DataKey) {
   206  			t.Errorf("Test %d: got data key '%v' - want data key '%v'", i, dataKey, test.DataKey)
   207  		}
   208  		if keyID != test.KeyID {
   209  			t.Errorf("Test %d: got key-ID '%v' - want key-ID '%v'", i, keyID, test.KeyID)
   210  		}
   211  		if sealedKey.Algorithm != test.SealedKey.Algorithm {
   212  			t.Errorf("Test %d: got sealed key algorithm '%v' - want sealed key algorithm '%v'", i, sealedKey.Algorithm, test.SealedKey.Algorithm)
   213  		}
   214  		if !bytes.Equal(sealedKey.Key[:], test.SealedKey.Key[:]) {
   215  			t.Errorf("Test %d: got sealed key '%v' - want sealed key '%v'", i, sealedKey.Key, test.SealedKey.Key)
   216  		}
   217  		if !bytes.Equal(sealedKey.IV[:], test.SealedKey.IV[:]) {
   218  			t.Errorf("Test %d: got sealed key IV '%v' - want sealed key IV '%v'", i, sealedKey.IV, test.SealedKey.IV)
   219  		}
   220  	}
   221  }
   222  
   223  var ssecParseMetadataTests = []struct {
   224  	Metadata    map[string]string
   225  	ExpectedErr error
   226  
   227  	SealedKey SealedKey
   228  }{
   229  	{ExpectedErr: errMissingInternalIV, Metadata: map[string]string{}, SealedKey: SealedKey{}},                      // 0
   230  	{ExpectedErr: errMissingInternalSealAlgorithm, Metadata: map[string]string{MetaIV: ""}, SealedKey: SealedKey{}}, // 1
   231  	{
   232  		ExpectedErr: Errorf("The object metadata is missing the internal sealed key for SSE-C"),
   233  		Metadata:    map[string]string{MetaIV: "", MetaAlgorithm: ""}, SealedKey: SealedKey{},
   234  	}, // 2
   235  	{
   236  		ExpectedErr: errInvalidInternalIV,
   237  		Metadata:    map[string]string{MetaIV: "", MetaAlgorithm: "", MetaSealedKeySSEC: ""}, SealedKey: SealedKey{},
   238  	}, // 3
   239  	{
   240  		ExpectedErr: errInvalidInternalSealAlgorithm,
   241  		Metadata: map[string]string{
   242  			MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: "", MetaSealedKeySSEC: "",
   243  		},
   244  		SealedKey: SealedKey{},
   245  	}, // 4
   246  	{
   247  		ExpectedErr: Errorf("The internal sealed key for SSE-C is invalid"),
   248  		Metadata: map[string]string{
   249  			MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: SealAlgorithm, MetaSealedKeySSEC: "",
   250  		},
   251  		SealedKey: SealedKey{},
   252  	}, // 5
   253  	{
   254  		ExpectedErr: nil,
   255  		Metadata: map[string]string{
   256  			MetaIV: base64.StdEncoding.EncodeToString(make([]byte, 32)), MetaAlgorithm: SealAlgorithm,
   257  			MetaSealedKeySSEC: base64.StdEncoding.EncodeToString(make([]byte, 64)),
   258  		},
   259  		SealedKey: SealedKey{Algorithm: SealAlgorithm},
   260  	}, // 6
   261  	{
   262  		ExpectedErr: nil,
   263  		Metadata: map[string]string{
   264  			MetaIV: base64.StdEncoding.EncodeToString(append([]byte{1}, make([]byte, 31)...)), MetaAlgorithm: InsecureSealAlgorithm,
   265  			MetaSealedKeySSEC: base64.StdEncoding.EncodeToString(append([]byte{1}, make([]byte, 63)...)),
   266  		},
   267  		SealedKey: SealedKey{Algorithm: InsecureSealAlgorithm, Key: [64]byte{1}, IV: [32]byte{1}},
   268  	}, // 7
   269  }
   270  
   271  func TestCreateMultipartMetadata(t *testing.T) {
   272  	metadata := CreateMultipartMetadata(nil)
   273  	if v, ok := metadata[MetaMultipart]; !ok || v != "" {
   274  		t.Errorf("Metadata is missing the correct value for '%s': got '%s' - want '%s'", MetaMultipart, v, "")
   275  	}
   276  }
   277  
   278  func TestSSECParseMetadata(t *testing.T) {
   279  	for i, test := range ssecParseMetadataTests {
   280  		sealedKey, err := SSEC.ParseMetadata(test.Metadata)
   281  		if err != nil && test.ExpectedErr == nil {
   282  			t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr)
   283  		}
   284  		if err == nil && test.ExpectedErr != nil {
   285  			t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr)
   286  		}
   287  		if err != nil && test.ExpectedErr != nil {
   288  			if err.Error() != test.ExpectedErr.Error() {
   289  				t.Errorf("Test %d: got error '%v' - want error '%v'", i, err, test.ExpectedErr)
   290  			}
   291  		}
   292  		if sealedKey.Algorithm != test.SealedKey.Algorithm {
   293  			t.Errorf("Test %d: got sealed key algorithm '%v' - want sealed key algorithm '%v'", i, sealedKey.Algorithm, test.SealedKey.Algorithm)
   294  		}
   295  		if !bytes.Equal(sealedKey.Key[:], test.SealedKey.Key[:]) {
   296  			t.Errorf("Test %d: got sealed key '%v' - want sealed key '%v'", i, sealedKey.Key, test.SealedKey.Key)
   297  		}
   298  		if !bytes.Equal(sealedKey.IV[:], test.SealedKey.IV[:]) {
   299  			t.Errorf("Test %d: got sealed key IV '%v' - want sealed key IV '%v'", i, sealedKey.IV, test.SealedKey.IV)
   300  		}
   301  	}
   302  }
   303  
   304  var s3CreateMetadataTests = []struct {
   305  	KeyID         string
   306  	SealedDataKey []byte
   307  	SealedKey     SealedKey
   308  }{
   309  	{KeyID: "", SealedDataKey: nil, SealedKey: SealedKey{Algorithm: SealAlgorithm}},
   310  	{KeyID: "my-minio-key", SealedDataKey: make([]byte, 48), SealedKey: SealedKey{Algorithm: SealAlgorithm}},
   311  	{KeyID: "cafebabe", SealedDataKey: make([]byte, 48), SealedKey: SealedKey{Algorithm: SealAlgorithm}},
   312  	{KeyID: "deadbeef", SealedDataKey: make([]byte, 32), SealedKey: SealedKey{IV: [32]byte{0xf7}, Key: [64]byte{0xea}, Algorithm: SealAlgorithm}},
   313  }
   314  
   315  func TestS3CreateMetadata(t *testing.T) {
   316  	defer func(l bool) { logger.DisableErrorLog = l }(logger.DisableErrorLog)
   317  	logger.DisableErrorLog = true
   318  	for i, test := range s3CreateMetadataTests {
   319  		metadata := S3.CreateMetadata(nil, test.KeyID, test.SealedDataKey, test.SealedKey)
   320  		keyID, kmsKey, sealedKey, err := S3.ParseMetadata(metadata)
   321  		if err != nil {
   322  			t.Errorf("Test %d: failed to parse metadata: %v", i, err)
   323  			continue
   324  		}
   325  		if keyID != test.KeyID {
   326  			t.Errorf("Test %d: Key-ID mismatch: got '%s' - want '%s'", i, keyID, test.KeyID)
   327  		}
   328  		if !bytes.Equal(kmsKey, test.SealedDataKey) {
   329  			t.Errorf("Test %d: sealed KMS data mismatch: got '%v' - want '%v'", i, kmsKey, test.SealedDataKey)
   330  		}
   331  		if sealedKey.Algorithm != test.SealedKey.Algorithm {
   332  			t.Errorf("Test %d: seal algorithm mismatch: got '%s' - want '%s'", i, sealedKey.Algorithm, test.SealedKey.Algorithm)
   333  		}
   334  		if !bytes.Equal(sealedKey.IV[:], test.SealedKey.IV[:]) {
   335  			t.Errorf("Test %d: IV mismatch: got '%v' - want '%v'", i, sealedKey.IV, test.SealedKey.IV)
   336  		}
   337  		if !bytes.Equal(sealedKey.Key[:], test.SealedKey.Key[:]) {
   338  			t.Errorf("Test %d: sealed key mismatch: got '%v' - want '%v'", i, sealedKey.Key, test.SealedKey.Key)
   339  		}
   340  	}
   341  
   342  	defer func() {
   343  		if err := recover(); err == nil || err != logger.ErrCritical {
   344  			t.Errorf("Expected '%s' panic for invalid seal algorithm but got '%s'", logger.ErrCritical, err)
   345  		}
   346  	}()
   347  	_ = S3.CreateMetadata(nil, "", []byte{}, SealedKey{Algorithm: InsecureSealAlgorithm})
   348  }
   349  
   350  var ssecCreateMetadataTests = []struct {
   351  	KeyID         string
   352  	SealedDataKey []byte
   353  	SealedKey     SealedKey
   354  }{
   355  	{KeyID: "", SealedDataKey: make([]byte, 48), SealedKey: SealedKey{Algorithm: SealAlgorithm}},
   356  	{KeyID: "cafebabe", SealedDataKey: make([]byte, 48), SealedKey: SealedKey{Algorithm: SealAlgorithm}},
   357  	{KeyID: "deadbeef", SealedDataKey: make([]byte, 32), SealedKey: SealedKey{IV: [32]byte{0xf7}, Key: [64]byte{0xea}, Algorithm: SealAlgorithm}},
   358  }
   359  
   360  func TestSSECCreateMetadata(t *testing.T) {
   361  	defer func(l bool) { logger.DisableErrorLog = l }(logger.DisableErrorLog)
   362  	logger.DisableErrorLog = true
   363  	for i, test := range ssecCreateMetadataTests {
   364  		metadata := SSEC.CreateMetadata(nil, test.SealedKey)
   365  		sealedKey, err := SSEC.ParseMetadata(metadata)
   366  		if err != nil {
   367  			t.Errorf("Test %d: failed to parse metadata: %v", i, err)
   368  			continue
   369  		}
   370  		if sealedKey.Algorithm != test.SealedKey.Algorithm {
   371  			t.Errorf("Test %d: seal algorithm mismatch: got '%s' - want '%s'", i, sealedKey.Algorithm, test.SealedKey.Algorithm)
   372  		}
   373  		if !bytes.Equal(sealedKey.IV[:], test.SealedKey.IV[:]) {
   374  			t.Errorf("Test %d: IV mismatch: got '%v' - want '%v'", i, sealedKey.IV, test.SealedKey.IV)
   375  		}
   376  		if !bytes.Equal(sealedKey.Key[:], test.SealedKey.Key[:]) {
   377  			t.Errorf("Test %d: sealed key mismatch: got '%v' - want '%v'", i, sealedKey.Key, test.SealedKey.Key)
   378  		}
   379  	}
   380  
   381  	defer func() {
   382  		if err := recover(); err == nil || err != logger.ErrCritical {
   383  			t.Errorf("Expected '%s' panic for invalid seal algorithm but got '%s'", logger.ErrCritical, err)
   384  		}
   385  	}()
   386  	_ = SSEC.CreateMetadata(nil, SealedKey{Algorithm: InsecureSealAlgorithm})
   387  }
   388  
   389  var isETagSealedTests = []struct {
   390  	ETag     string
   391  	IsSealed bool
   392  }{
   393  	{ETag: "", IsSealed: false},                                  // 0
   394  	{ETag: "90682b8e8cc7609c4671e1d64c73fc30", IsSealed: false},  // 1
   395  	{ETag: "f201040c9dc593e39ea004dc1323699bcd", IsSealed: true}, // 2 not valid ciphertext but looks like sealed ETag
   396  	{ETag: "20000f00fba2ee2ae4845f725964eeb9e092edfabc7ab9f9239e8344341f769a51ce99b4801b0699b92b16a72fa94972", IsSealed: true}, // 3
   397  }
   398  
   399  func TestIsETagSealed(t *testing.T) {
   400  	for i, test := range isETagSealedTests {
   401  		etag, err := hex.DecodeString(test.ETag)
   402  		if err != nil {
   403  			t.Errorf("Test %d: failed to decode etag: %s", i, err)
   404  		}
   405  		if sealed := IsETagSealed(etag); sealed != test.IsSealed {
   406  			t.Errorf("Test %d: got %v - want %v", i, sealed, test.IsSealed)
   407  		}
   408  	}
   409  }
   410  
   411  var removeInternalEntriesTests = []struct {
   412  	Metadata, Expected map[string]string
   413  }{
   414  	{ // 0
   415  		Metadata: map[string]string{
   416  			MetaMultipart:         "",
   417  			MetaIV:                "",
   418  			MetaAlgorithm:         "",
   419  			MetaSealedKeySSEC:     "",
   420  			MetaSealedKeyS3:       "",
   421  			MetaKeyID:             "",
   422  			MetaDataEncryptionKey: "",
   423  		},
   424  		Expected: map[string]string{},
   425  	},
   426  	{ // 1
   427  		Metadata: map[string]string{
   428  			MetaMultipart:        "",
   429  			MetaIV:               "",
   430  			"X-Amz-Meta-A":       "X",
   431  			"X-Minio-Internal-B": "Y",
   432  		},
   433  		Expected: map[string]string{
   434  			"X-Amz-Meta-A":       "X",
   435  			"X-Minio-Internal-B": "Y",
   436  		},
   437  	},
   438  }
   439  
   440  func TestRemoveInternalEntries(t *testing.T) {
   441  	isEqual := func(x, y map[string]string) bool {
   442  		if len(x) != len(y) {
   443  			return false
   444  		}
   445  		for k, v := range x {
   446  			if u, ok := y[k]; !ok || v != u {
   447  				return false
   448  			}
   449  		}
   450  		return true
   451  	}
   452  
   453  	for i, test := range removeInternalEntriesTests {
   454  		RemoveInternalEntries(test.Metadata)
   455  		if !isEqual(test.Metadata, test.Expected) {
   456  			t.Errorf("Test %d: got %v - want %v", i, test.Metadata, test.Expected)
   457  		}
   458  	}
   459  }