storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/crypto/header_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  	"net/http"
    19  	"sort"
    20  	"testing"
    21  
    22  	xhttp "storj.io/minio/cmd/http"
    23  )
    24  
    25  func TestIsRequested(t *testing.T) {
    26  	for i, test := range kmsIsRequestedTests {
    27  		_, got := IsRequested(test.Header)
    28  		got = got && S3KMS.IsRequested(test.Header)
    29  		if got != test.Expected {
    30  			t.Errorf("SSE-KMS: Test %d: Wanted %v but got %v", i, test.Expected, got)
    31  		}
    32  	}
    33  	for i, test := range s3IsRequestedTests {
    34  		_, got := IsRequested(test.Header)
    35  		got = got && S3.IsRequested(test.Header)
    36  		if got != test.Expected {
    37  			t.Errorf("SSE-S3: Test %d: Wanted %v but got %v", i, test.Expected, got)
    38  		}
    39  	}
    40  	for i, test := range ssecIsRequestedTests {
    41  		_, got := IsRequested(test.Header)
    42  		got = got && SSEC.IsRequested(test.Header)
    43  		if got != test.Expected {
    44  			t.Errorf("SSE-C: Test %d: Wanted %v but got %v", i, test.Expected, got)
    45  		}
    46  	}
    47  }
    48  
    49  var kmsIsRequestedTests = []struct {
    50  	Header   http.Header
    51  	Expected bool
    52  }{
    53  	{Header: http.Header{}, Expected: false},                                                                                     // 0
    54  	{Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"aws:kms"}}, Expected: true},                                   // 1
    55  	{Header: http.Header{"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"0839-9047947-844842874-481"}}, Expected: true}, // 2
    56  	{Header: http.Header{"X-Amz-Server-Side-Encryption-Context": []string{"7PpPLAK26ONlVUGOWlusfg=="}}, Expected: true},          // 3
    57  	{
    58  		Header: http.Header{
    59  			"X-Amz-Server-Side-Encryption":                []string{""},
    60  			"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{""},
    61  			"X-Amz-Server-Side-Encryption-Context":        []string{""},
    62  		},
    63  		Expected: true,
    64  	}, // 4
    65  	{
    66  		Header: http.Header{
    67  			"X-Amz-Server-Side-Encryption":                []string{"AES256"},
    68  			"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{""},
    69  		},
    70  		Expected: true,
    71  	}, // 5
    72  	{Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"AES256"}}, Expected: false}, // 6
    73  }
    74  
    75  func TestKMSIsRequested(t *testing.T) {
    76  	for i, test := range kmsIsRequestedTests {
    77  		if got := S3KMS.IsRequested(test.Header); got != test.Expected {
    78  			t.Errorf("Test %d: Wanted %v but got %v", i, test.Expected, got)
    79  		}
    80  	}
    81  }
    82  
    83  var kmsParseHTTPTests = []struct {
    84  	Header     http.Header
    85  	ShouldFail bool
    86  }{
    87  	{Header: http.Header{}, ShouldFail: true},                                                     // 0
    88  	{Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"aws:kms"}}, ShouldFail: false}, // 1
    89  	{Header: http.Header{
    90  		"X-Amz-Server-Side-Encryption":                []string{"aws:kms"},
    91  		"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"},
    92  	}, ShouldFail: false}, // 2
    93  	{Header: http.Header{
    94  		"X-Amz-Server-Side-Encryption":                []string{"aws:kms"},
    95  		"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"},
    96  		"X-Amz-Server-Side-Encryption-Context":        []string{"{}"},
    97  	}, ShouldFail: false}, // 3
    98  	{Header: http.Header{
    99  		"X-Amz-Server-Side-Encryption":                []string{"aws:kms"},
   100  		"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"},
   101  		"X-Amz-Server-Side-Encryption-Context":        []string{"{\"bucket\": \"some-bucket\"}"},
   102  	}, ShouldFail: false}, // 4
   103  	{Header: http.Header{
   104  		"X-Amz-Server-Side-Encryption":                []string{"aws:kms"},
   105  		"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"},
   106  		"X-Amz-Server-Side-Encryption-Context":        []string{"{\"bucket\": \"some-bucket\"}"},
   107  	}, ShouldFail: false}, // 5
   108  	{Header: http.Header{
   109  		"X-Amz-Server-Side-Encryption":                []string{"AES256"},
   110  		"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"},
   111  		"X-Amz-Server-Side-Encryption-Context":        []string{"{\"bucket\": \"some-bucket\"}"},
   112  	}, ShouldFail: true}, // 6
   113  	{Header: http.Header{
   114  		"X-Amz-Server-Side-Encryption":                []string{"aws:kms"},
   115  		"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": []string{"s3-007-293847485-724784"},
   116  		"X-Amz-Server-Side-Encryption-Context":        []string{"{\"bucket\": \"some-bucket\""}, // invalid JSON
   117  	}, ShouldFail: true}, // 7
   118  
   119  }
   120  
   121  func TestKMSParseHTTP(t *testing.T) {
   122  	for i, test := range kmsParseHTTPTests {
   123  		_, _, err := S3KMS.ParseHTTP(test.Header)
   124  		if err == nil && test.ShouldFail {
   125  			t.Errorf("Test %d: should fail but succeeded", i)
   126  		}
   127  		if err != nil && !test.ShouldFail {
   128  			t.Errorf("Test %d: should pass but failed with: %v", i, err)
   129  		}
   130  	}
   131  }
   132  
   133  var s3IsRequestedTests = []struct {
   134  	Header   http.Header
   135  	Expected bool
   136  }{
   137  	{Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"AES256"}}, Expected: true},                // 0
   138  	{Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"AES-256"}}, Expected: true},               // 1
   139  	{Header: http.Header{"X-Amz-Server-Side-Encryption": []string{""}}, Expected: true},                      // 2
   140  	{Header: http.Header{"X-Amz-Server-Side-Encryptio": []string{"AES256"}}, Expected: false},                // 3
   141  	{Header: http.Header{"X-Amz-Server-Side-Encryption": []string{xhttp.AmzEncryptionKMS}}, Expected: false}, // 4
   142  }
   143  
   144  func TestS3IsRequested(t *testing.T) {
   145  	for i, test := range s3IsRequestedTests {
   146  		if got := S3.IsRequested(test.Header); got != test.Expected {
   147  			t.Errorf("Test %d: Wanted %v but got %v", i, test.Expected, got)
   148  		}
   149  	}
   150  }
   151  
   152  var s3ParseTests = []struct {
   153  	Header      http.Header
   154  	ExpectedErr error
   155  }{
   156  	{Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"AES256"}}, ExpectedErr: nil},                         // 0
   157  	{Header: http.Header{"X-Amz-Server-Side-Encryption": []string{"AES-256"}}, ExpectedErr: ErrInvalidEncryptionMethod}, // 1
   158  	{Header: http.Header{"X-Amz-Server-Side-Encryption": []string{""}}, ExpectedErr: ErrInvalidEncryptionMethod},        // 2
   159  	{Header: http.Header{"X-Amz-Server-Side-Encryptio": []string{"AES256"}}, ExpectedErr: ErrInvalidEncryptionMethod},   // 3
   160  }
   161  
   162  func TestS3Parse(t *testing.T) {
   163  	for i, test := range s3ParseTests {
   164  		if err := S3.ParseHTTP(test.Header); err != test.ExpectedErr {
   165  			t.Errorf("Test %d: Wanted '%v' but got '%v'", i, test.ExpectedErr, err)
   166  		}
   167  	}
   168  }
   169  
   170  var ssecIsRequestedTests = []struct {
   171  	Header   http.Header
   172  	Expected bool
   173  }{
   174  	{Header: http.Header{}, Expected: false}, // 0
   175  	{Header: http.Header{"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}}, Expected: true},                                 // 1
   176  	{Header: http.Header{"X-Amz-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}}, Expected: true}, // 2
   177  	{Header: http.Header{"X-Amz-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}}, Expected: true},                 // 3
   178  	{
   179  		Header: http.Header{
   180  			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{""},
   181  			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{""},
   182  			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{""},
   183  		},
   184  		Expected: true,
   185  	}, // 4
   186  	{
   187  		Header: http.Header{
   188  			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   189  			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   190  			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   191  		},
   192  		Expected: true,
   193  	}, // 5
   194  	{
   195  		Header: http.Header{
   196  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   197  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   198  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   199  		},
   200  		Expected: false,
   201  	}, // 6
   202  }
   203  
   204  func TestSSECIsRequested(t *testing.T) {
   205  	for i, test := range ssecIsRequestedTests {
   206  		if got := SSEC.IsRequested(test.Header); got != test.Expected {
   207  			t.Errorf("Test %d: Wanted %v but got %v", i, test.Expected, got)
   208  		}
   209  	}
   210  }
   211  
   212  var ssecCopyIsRequestedTests = []struct {
   213  	Header   http.Header
   214  	Expected bool
   215  }{
   216  	{Header: http.Header{}, Expected: false}, // 0
   217  	{Header: http.Header{"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"}}, Expected: true},                                 // 1
   218  	{Header: http.Header{"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}}, Expected: true}, // 2
   219  	{Header: http.Header{"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": []string{"7PpPLAK26ONlVUGOWlusfg=="}}, Expected: true},                 // 3
   220  	{
   221  		Header: http.Header{
   222  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{""},
   223  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{""},
   224  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{""},
   225  		},
   226  		Expected: true,
   227  	}, // 4
   228  	{
   229  		Header: http.Header{
   230  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   231  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   232  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   233  		},
   234  		Expected: true,
   235  	}, // 5
   236  	{
   237  		Header: http.Header{
   238  			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   239  			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   240  			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   241  		},
   242  		Expected: false,
   243  	}, // 6
   244  }
   245  
   246  func TestSSECopyIsRequested(t *testing.T) {
   247  	for i, test := range ssecCopyIsRequestedTests {
   248  		if got := SSECopy.IsRequested(test.Header); got != test.Expected {
   249  			t.Errorf("Test %d: Wanted %v but got %v", i, test.Expected, got)
   250  		}
   251  	}
   252  }
   253  
   254  var ssecParseTests = []struct {
   255  	Header      http.Header
   256  	ExpectedErr error
   257  }{
   258  	{
   259  		Header: http.Header{
   260  			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   261  			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   262  			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   263  		},
   264  		ExpectedErr: nil, // 0
   265  	},
   266  	{
   267  		Header: http.Header{
   268  			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES-256"}, // invalid algorithm
   269  			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   270  			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   271  		},
   272  		ExpectedErr: ErrInvalidCustomerAlgorithm, // 1
   273  	},
   274  	{
   275  		Header: http.Header{
   276  			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   277  			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{""}, // no client key
   278  			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   279  		},
   280  		ExpectedErr: ErrMissingCustomerKey, // 2
   281  	},
   282  	{
   283  		Header: http.Header{
   284  			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   285  			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRr.ZXltdXN0cHJvdmlkZWQ="}, // invalid key
   286  			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   287  		},
   288  		ExpectedErr: ErrInvalidCustomerKey, // 3
   289  	},
   290  	{
   291  		Header: http.Header{
   292  			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   293  			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   294  			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{""}, // no key MD5
   295  		},
   296  		ExpectedErr: ErrMissingCustomerKeyMD5, // 4
   297  	},
   298  	{
   299  		Header: http.Header{
   300  			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   301  			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"DzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, // wrong client key
   302  			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   303  		},
   304  		ExpectedErr: ErrCustomerKeyMD5Mismatch, // 5
   305  	},
   306  	{
   307  		Header: http.Header{
   308  			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   309  			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   310  			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{".7PpPLAK26ONlVUGOWlusfg=="}, // wrong key MD5
   311  		},
   312  		ExpectedErr: ErrCustomerKeyMD5Mismatch, // 6
   313  	},
   314  }
   315  
   316  func TestSSECParse(t *testing.T) {
   317  	var zeroKey [32]byte
   318  	for i, test := range ssecParseTests {
   319  		key, err := SSEC.ParseHTTP(test.Header)
   320  		if err != test.ExpectedErr {
   321  			t.Errorf("Test %d: want error '%v' but got '%v'", i, test.ExpectedErr, err)
   322  		}
   323  
   324  		if err != nil && key != zeroKey {
   325  			t.Errorf("Test %d: parsing failed and client key is not zero key", i)
   326  		}
   327  		if err == nil && key == zeroKey {
   328  			t.Errorf("Test %d: parsed client key is zero key", i)
   329  		}
   330  	}
   331  }
   332  
   333  var ssecCopyParseTests = []struct {
   334  	Header      http.Header
   335  	ExpectedErr error
   336  }{
   337  	{
   338  		Header: http.Header{
   339  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   340  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   341  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   342  		},
   343  		ExpectedErr: nil, // 0
   344  	},
   345  	{
   346  		Header: http.Header{
   347  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES-256"}, // invalid algorithm
   348  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   349  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   350  		},
   351  		ExpectedErr: ErrInvalidCustomerAlgorithm, // 1
   352  	},
   353  	{
   354  		Header: http.Header{
   355  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   356  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{""}, // no client key
   357  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   358  		},
   359  		ExpectedErr: ErrMissingCustomerKey, // 2
   360  	},
   361  	{
   362  		Header: http.Header{
   363  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   364  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRr.ZXltdXN0cHJvdmlkZWQ="}, // invalid key
   365  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   366  		},
   367  		ExpectedErr: ErrInvalidCustomerKey, // 3
   368  	},
   369  	{
   370  		Header: http.Header{
   371  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   372  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   373  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{""}, // no key MD5
   374  		},
   375  		ExpectedErr: ErrMissingCustomerKeyMD5, // 4
   376  	},
   377  	{
   378  		Header: http.Header{
   379  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   380  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"DzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="}, // wrong client key
   381  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
   382  		},
   383  		ExpectedErr: ErrCustomerKeyMD5Mismatch, // 5
   384  	},
   385  	{
   386  		Header: http.Header{
   387  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
   388  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   389  			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{".7PpPLAK26ONlVUGOWlusfg=="}, // wrong key MD5
   390  		},
   391  		ExpectedErr: ErrCustomerKeyMD5Mismatch, // 6
   392  	},
   393  }
   394  
   395  func TestSSECopyParse(t *testing.T) {
   396  	var zeroKey [32]byte
   397  	for i, test := range ssecCopyParseTests {
   398  		key, err := SSECopy.ParseHTTP(test.Header)
   399  		if err != test.ExpectedErr {
   400  			t.Errorf("Test %d: want error '%v' but got '%v'", i, test.ExpectedErr, err)
   401  		}
   402  
   403  		if err != nil && key != zeroKey {
   404  			t.Errorf("Test %d: parsing failed and client key is not zero key", i)
   405  		}
   406  		if err == nil && key == zeroKey {
   407  			t.Errorf("Test %d: parsed client key is zero key", i)
   408  		}
   409  		if _, ok := test.Header[xhttp.AmzServerSideEncryptionCustomerKey]; ok {
   410  			t.Errorf("Test %d: client key is not removed from HTTP headers after parsing", i)
   411  		}
   412  	}
   413  }
   414  
   415  var removeSensitiveHeadersTests = []struct {
   416  	Header, ExpectedHeader http.Header
   417  }{
   418  	{
   419  		Header: http.Header{
   420  			xhttp.AmzServerSideEncryptionCustomerKey:     []string{""},
   421  			xhttp.AmzServerSideEncryptionCopyCustomerKey: []string{""},
   422  		},
   423  		ExpectedHeader: http.Header{},
   424  	},
   425  	{ // Standard SSE-C request headers
   426  		Header: http.Header{
   427  			xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES},
   428  			xhttp.AmzServerSideEncryptionCustomerKey:       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   429  			xhttp.AmzServerSideEncryptionCustomerKeyMD5:    []string{"7PpPLAK26ONlVUGOWlusfg=="},
   430  		},
   431  		ExpectedHeader: http.Header{
   432  			xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES},
   433  			xhttp.AmzServerSideEncryptionCustomerKeyMD5:    []string{"7PpPLAK26ONlVUGOWlusfg=="},
   434  		},
   435  	},
   436  	{ // Standard SSE-C + SSE-C-copy request headers
   437  		Header: http.Header{
   438  			xhttp.AmzServerSideEncryptionCustomerAlgorithm:  []string{xhttp.AmzEncryptionAES},
   439  			xhttp.AmzServerSideEncryptionCustomerKey:        []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   440  			xhttp.AmzServerSideEncryptionCustomerKeyMD5:     []string{"7PpPLAK26ONlVUGOWlusfg=="},
   441  			xhttp.AmzServerSideEncryptionCopyCustomerKey:    []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   442  			xhttp.AmzServerSideEncryptionCopyCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="},
   443  		},
   444  		ExpectedHeader: http.Header{
   445  			xhttp.AmzServerSideEncryptionCustomerAlgorithm:  []string{xhttp.AmzEncryptionAES},
   446  			xhttp.AmzServerSideEncryptionCustomerKeyMD5:     []string{"7PpPLAK26ONlVUGOWlusfg=="},
   447  			xhttp.AmzServerSideEncryptionCopyCustomerKeyMD5: []string{"7PpPLAK26ONlVUGOWlusfg=="},
   448  		},
   449  	},
   450  	{ // Standard SSE-C + metadata request headers
   451  		Header: http.Header{
   452  			xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES},
   453  			xhttp.AmzServerSideEncryptionCustomerKey:       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
   454  			xhttp.AmzServerSideEncryptionCustomerKeyMD5:    []string{"7PpPLAK26ONlVUGOWlusfg=="},
   455  			"X-Amz-Meta-Test-1":                            []string{"Test-1"},
   456  		},
   457  		ExpectedHeader: http.Header{
   458  			xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{xhttp.AmzEncryptionAES},
   459  			xhttp.AmzServerSideEncryptionCustomerKeyMD5:    []string{"7PpPLAK26ONlVUGOWlusfg=="},
   460  			"X-Amz-Meta-Test-1":                            []string{"Test-1"},
   461  		},
   462  	},
   463  	{ // https://github.com/google/security-research/security/advisories/GHSA-76wf-9vgp-pj7w
   464  		Header: http.Header{
   465  			"X-Amz-Meta-X-Amz-Unencrypted-Content-Md5":    []string{"value"},
   466  			"X-Amz-Meta-X-Amz-Unencrypted-Content-Length": []string{"value"},
   467  			"X-Amz-Meta-Test-1":                           []string{"Test-1"},
   468  		},
   469  		ExpectedHeader: http.Header{
   470  			"X-Amz-Meta-Test-1": []string{"Test-1"},
   471  		},
   472  	},
   473  }
   474  
   475  func TestRemoveSensitiveHeaders(t *testing.T) {
   476  	isEqual := func(x, y http.Header) bool {
   477  		if len(x) != len(y) {
   478  			return false
   479  		}
   480  		for k, v := range x {
   481  			u, ok := y[k]
   482  			if !ok || len(v) != len(u) {
   483  				return false
   484  			}
   485  			sort.Strings(v)
   486  			sort.Strings(u)
   487  			for j := range v {
   488  				if v[j] != u[j] {
   489  					return false
   490  				}
   491  			}
   492  		}
   493  		return true
   494  	}
   495  	areKeysEqual := func(h http.Header, metadata map[string]string) bool {
   496  		if len(h) != len(metadata) {
   497  			return false
   498  		}
   499  		for k := range h {
   500  			if _, ok := metadata[k]; !ok {
   501  				return false
   502  			}
   503  		}
   504  		return true
   505  	}
   506  
   507  	for i, test := range removeSensitiveHeadersTests {
   508  		metadata := make(map[string]string, len(test.Header))
   509  		for k := range test.Header {
   510  			metadata[k] = "" // set metadata key - we don't care about the value
   511  		}
   512  
   513  		RemoveSensitiveHeaders(test.Header)
   514  		if !isEqual(test.ExpectedHeader, test.Header) {
   515  			t.Errorf("Test %d: filtered headers do not match expected headers - got: %v , want: %v", i, test.Header, test.ExpectedHeader)
   516  		}
   517  		RemoveSensitiveEntries(metadata)
   518  		if !areKeysEqual(test.ExpectedHeader, metadata) {
   519  			t.Errorf("Test %d: filtered headers do not match expected headers - got: %v , want: %v", i, test.Header, test.ExpectedHeader)
   520  		}
   521  	}
   522  }