storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/crypto/metadata_test.go (about)

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