mirror of
				https://github.com/minio/minio.git
				synced 2025-10-31 00:01:27 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			197 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // MinIO Cloud Storage, (C) 2015, 2016, 2017, 2018 MinIO, Inc.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //    http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| package crypto
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"crypto/rand"
 | |
| 	"encoding/hex"
 | |
| 	"io"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/minio/minio/cmd/logger"
 | |
| )
 | |
| 
 | |
| var shortRandom = func(limit int64) io.Reader { return io.LimitReader(rand.Reader, limit) }
 | |
| 
 | |
| func recoverTest(i int, shouldPass bool, t *testing.T) {
 | |
| 	if err := recover(); err == nil && !shouldPass {
 | |
| 		t.Errorf("Test %d should fail but passed successfully", i)
 | |
| 	} else if err != nil && shouldPass {
 | |
| 		t.Errorf("Test %d should pass but failed: %v", i, err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var generateKeyTests = []struct {
 | |
| 	ExtKey     [32]byte
 | |
| 	Random     io.Reader
 | |
| 	ShouldPass bool
 | |
| }{
 | |
| 	{ExtKey: [32]byte{}, Random: nil, ShouldPass: true},              // 0
 | |
| 	{ExtKey: [32]byte{}, Random: rand.Reader, ShouldPass: true},      // 1
 | |
| 	{ExtKey: [32]byte{}, Random: shortRandom(32), ShouldPass: true},  // 2
 | |
| 	{ExtKey: [32]byte{}, Random: shortRandom(31), ShouldPass: false}, // 3
 | |
| }
 | |
| 
 | |
| func TestGenerateKey(t *testing.T) {
 | |
| 	defer func(disableLog bool) { logger.Disable = disableLog }(logger.Disable)
 | |
| 	logger.Disable = true
 | |
| 
 | |
| 	for i, test := range generateKeyTests {
 | |
| 		i, test := i, test
 | |
| 		func() {
 | |
| 			defer recoverTest(i, test.ShouldPass, t)
 | |
| 			key := GenerateKey(test.ExtKey, test.Random)
 | |
| 			if [32]byte(key) == [32]byte{} {
 | |
| 				t.Errorf("Test %d: generated key is zero key", i) // check that we generate random and unique key
 | |
| 			}
 | |
| 		}()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var generateIVTests = []struct {
 | |
| 	Random     io.Reader
 | |
| 	ShouldPass bool
 | |
| }{
 | |
| 	{Random: nil, ShouldPass: true},              // 0
 | |
| 	{Random: rand.Reader, ShouldPass: true},      // 1
 | |
| 	{Random: shortRandom(32), ShouldPass: true},  // 2
 | |
| 	{Random: shortRandom(31), ShouldPass: false}, // 3
 | |
| }
 | |
| 
 | |
| func TestGenerateIV(t *testing.T) {
 | |
| 	defer func(disableLog bool) { logger.Disable = disableLog }(logger.Disable)
 | |
| 	logger.Disable = true
 | |
| 
 | |
| 	for i, test := range generateIVTests {
 | |
| 		i, test := i, test
 | |
| 		func() {
 | |
| 			defer recoverTest(i, test.ShouldPass, t)
 | |
| 			iv := GenerateIV(test.Random)
 | |
| 			if iv == [32]byte{} {
 | |
| 				t.Errorf("Test %d: generated IV is zero IV", i) // check that we generate random and unique IV
 | |
| 			}
 | |
| 		}()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var sealUnsealKeyTests = []struct {
 | |
| 	SealExtKey, SealIV                 [32]byte
 | |
| 	SealDomain, SealBucket, SealObject string
 | |
| 
 | |
| 	UnsealExtKey                             [32]byte
 | |
| 	UnsealDomain, UnsealBucket, UnsealObject string
 | |
| 
 | |
| 	ShouldPass bool
 | |
| }{
 | |
| 	{
 | |
| 		SealExtKey: [32]byte{}, SealIV: [32]byte{}, SealDomain: "SSE-C", SealBucket: "bucket", SealObject: "object",
 | |
| 		UnsealExtKey: [32]byte{}, UnsealDomain: "SSE-C", UnsealBucket: "bucket", UnsealObject: "object",
 | |
| 		ShouldPass: true,
 | |
| 	}, // 0
 | |
| 	{
 | |
| 		SealExtKey: [32]byte{}, SealIV: [32]byte{}, SealDomain: "SSE-C", SealBucket: "bucket", SealObject: "object",
 | |
| 		UnsealExtKey: [32]byte{1}, UnsealDomain: "SSE-C", UnsealBucket: "bucket", UnsealObject: "object", // different ext-key
 | |
| 		ShouldPass: false,
 | |
| 	}, // 1
 | |
| 	{
 | |
| 		SealExtKey: [32]byte{}, SealIV: [32]byte{}, SealDomain: "SSE-S3", SealBucket: "bucket", SealObject: "object",
 | |
| 		UnsealExtKey: [32]byte{}, UnsealDomain: "SSE-C", UnsealBucket: "bucket", UnsealObject: "object", // different domain
 | |
| 		ShouldPass: false,
 | |
| 	}, // 2
 | |
| 	{
 | |
| 		SealExtKey: [32]byte{}, SealIV: [32]byte{}, SealDomain: "SSE-C", SealBucket: "bucket", SealObject: "object",
 | |
| 		UnsealExtKey: [32]byte{}, UnsealDomain: "SSE-C", UnsealBucket: "Bucket", UnsealObject: "object", // different bucket
 | |
| 		ShouldPass: false,
 | |
| 	}, // 3
 | |
| 	{
 | |
| 		SealExtKey: [32]byte{}, SealIV: [32]byte{}, SealDomain: "SSE-C", SealBucket: "bucket", SealObject: "object",
 | |
| 		UnsealExtKey: [32]byte{}, UnsealDomain: "SSE-C", UnsealBucket: "bucket", UnsealObject: "Object", // different object
 | |
| 		ShouldPass: false,
 | |
| 	}, // 4
 | |
| }
 | |
| 
 | |
| func TestSealUnsealKey(t *testing.T) {
 | |
| 	for i, test := range sealUnsealKeyTests {
 | |
| 		key := GenerateKey(test.SealExtKey, rand.Reader)
 | |
| 		sealedKey := key.Seal(test.SealExtKey, test.SealIV, test.SealDomain, test.SealBucket, test.SealObject)
 | |
| 		if err := key.Unseal(test.UnsealExtKey, sealedKey, test.UnsealDomain, test.UnsealBucket, test.UnsealObject); err == nil && !test.ShouldPass {
 | |
| 			t.Errorf("Test %d should fail but passed successfully", i)
 | |
| 		} else if err != nil && test.ShouldPass {
 | |
| 			t.Errorf("Test %d should pass put failed: %v", i, err)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Test legacy InsecureSealAlgorithm
 | |
| 	var extKey, iv [32]byte
 | |
| 	key := GenerateKey(extKey, rand.Reader)
 | |
| 	sealedKey := key.Seal(extKey, iv, "SSE-S3", "bucket", "object")
 | |
| 	sealedKey.Algorithm = InsecureSealAlgorithm
 | |
| 	if err := key.Unseal(extKey, sealedKey, "SSE-S3", "bucket", "object"); err == nil {
 | |
| 		t.Errorf("'%s' test succeeded but it should fail because the legacy algorithm was used", sealedKey.Algorithm)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var derivePartKeyTest = []struct {
 | |
| 	PartID  uint32
 | |
| 	PartKey string
 | |
| }{
 | |
| 	{PartID: 0, PartKey: "aa7855e13839dd767cd5da7c1ff5036540c9264b7a803029315e55375287b4af"},
 | |
| 	{PartID: 1, PartKey: "a3e7181c6eed030fd52f79537c56c4d07da92e56d374ff1dd2043350785b37d8"},
 | |
| 	{PartID: 10000, PartKey: "f86e65c396ed52d204ee44bd1a0bbd86eb8b01b7354e67a3b3ae0e34dd5bd115"},
 | |
| }
 | |
| 
 | |
| func TestDerivePartKey(t *testing.T) {
 | |
| 	var key ObjectKey
 | |
| 	for i, test := range derivePartKeyTest {
 | |
| 		expectedPartKey, err := hex.DecodeString(test.PartKey)
 | |
| 		if err != nil {
 | |
| 			t.Fatalf("Test %d failed to decode expected part-key: %v", i, err)
 | |
| 		}
 | |
| 		partKey := key.DerivePartKey(test.PartID)
 | |
| 		if !bytes.Equal(partKey[:], expectedPartKey[:]) {
 | |
| 			t.Errorf("Test %d derives wrong part-key: got '%s' want: '%s'", i, hex.EncodeToString(partKey[:]), test.PartKey)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var sealUnsealETagTests = []string{
 | |
| 	"",
 | |
| 	"90682b8e8cc7609c",
 | |
| 	"90682b8e8cc7609c4671e1d64c73fc30",
 | |
| 	"90682b8e8cc7609c4671e1d64c73fc307fb3104f",
 | |
| }
 | |
| 
 | |
| func TestSealETag(t *testing.T) {
 | |
| 	var key ObjectKey
 | |
| 	for i := range key {
 | |
| 		key[i] = byte(i)
 | |
| 	}
 | |
| 	for i, etag := range sealUnsealETagTests {
 | |
| 		tag, err := hex.DecodeString(etag)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("Test %d: failed to decode etag: %s", i, err)
 | |
| 		}
 | |
| 		sealedETag := key.SealETag(tag)
 | |
| 		unsealedETag, err := key.UnsealETag(sealedETag)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("Test %d: failed to decrypt etag: %s", i, err)
 | |
| 		}
 | |
| 		if !bytes.Equal(unsealedETag, tag) {
 | |
| 			t.Errorf("Test %d: unsealed etag does not match: got %s - want %s", i, hex.EncodeToString(unsealedETag), etag)
 | |
| 		}
 | |
| 	}
 | |
| }
 |