github.com/ethersphere/bee/v2@v2.2.0/pkg/accesscontrol/access_test.go (about)

     1  // Copyright 2024 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package accesscontrol_test
     6  
     7  import (
     8  	"context"
     9  	"crypto/ecdsa"
    10  	"crypto/elliptic"
    11  	"crypto/rand"
    12  	"encoding/hex"
    13  	"fmt"
    14  	"testing"
    15  
    16  	"github.com/ethersphere/bee/v2/pkg/accesscontrol"
    17  	kvsmock "github.com/ethersphere/bee/v2/pkg/accesscontrol/kvs/mock"
    18  	"github.com/ethersphere/bee/v2/pkg/crypto"
    19  	"github.com/ethersphere/bee/v2/pkg/swarm"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  func assertNoError(t *testing.T, msg string, err error) {
    24  	t.Helper()
    25  	if err != nil {
    26  		assert.FailNowf(t, err.Error(), msg)
    27  	}
    28  }
    29  
    30  func assertError(t *testing.T, msg string, err error) {
    31  	t.Helper()
    32  	if err == nil {
    33  		assert.FailNowf(t, fmt.Sprintf("Expected %s error, got nil", msg), "")
    34  	}
    35  }
    36  
    37  // Generates a new test environment with a fix private key.
    38  func setupAccessLogic() accesscontrol.ActLogic {
    39  	privateKey := getPrivKey(1)
    40  	diffieHellman := accesscontrol.NewDefaultSession(privateKey)
    41  	al := accesscontrol.NewLogic(diffieHellman)
    42  
    43  	return al
    44  }
    45  
    46  func getPrivKey(keyNumber int) *ecdsa.PrivateKey {
    47  	var keyHex string
    48  
    49  	switch keyNumber {
    50  	case 0:
    51  		keyHex = "a786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfa"
    52  	case 1:
    53  		keyHex = "b786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfb"
    54  	case 2:
    55  		keyHex = "c786dd84b61485de12146fd9c4c02d87e8fd95f0542765cb7fc3d2e428c0bcfc"
    56  	default:
    57  		panic("Invalid key number")
    58  	}
    59  
    60  	data, err := hex.DecodeString(keyHex)
    61  	if err != nil {
    62  		panic(err)
    63  	}
    64  
    65  	privKey, err := crypto.DecodeSecp256k1PrivateKey(data)
    66  	if err != nil {
    67  		panic(err)
    68  	}
    69  
    70  	return privKey
    71  }
    72  
    73  func TestDecryptRef_Publisher(t *testing.T) {
    74  	t.Parallel()
    75  	ctx := context.Background()
    76  	id1 := getPrivKey(1)
    77  	s := kvsmock.New()
    78  	al := setupAccessLogic()
    79  	err := al.AddGrantee(ctx, s, &id1.PublicKey, &id1.PublicKey)
    80  	assertNoError(t, "AddGrantee", err)
    81  
    82  	byteRef, err := hex.DecodeString("39a5ea87b141fe44aa609c3327ecd896c0e2122897f5f4bbacf74db1033c5559")
    83  	assertNoError(t, "DecodeString", err)
    84  	expectedRef := swarm.NewAddress(byteRef)
    85  	encryptedRef, err := al.EncryptRef(ctx, s, &id1.PublicKey, expectedRef)
    86  	assertNoError(t, "al encryptref", err)
    87  
    88  	t.Run("decrypt success", func(t *testing.T) {
    89  		actualRef, err := al.DecryptRef(ctx, s, encryptedRef, &id1.PublicKey)
    90  		assertNoError(t, "decrypt ref", err)
    91  
    92  		if !expectedRef.Equal(actualRef) {
    93  			assert.FailNowf(t, fmt.Sprintf("DecryptRef gave back wrong Swarm reference! Expedted: %v, actual: %v", expectedRef, actualRef), "")
    94  		}
    95  	})
    96  	t.Run("decrypt with nil publisher", func(t *testing.T) {
    97  		_, err = al.DecryptRef(ctx, s, encryptedRef, nil)
    98  		assertError(t, "al decryptref", err)
    99  	})
   100  }
   101  
   102  func TestDecryptRefWithGrantee_Success(t *testing.T) {
   103  	t.Parallel()
   104  	ctx := context.Background()
   105  	id0, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   106  	assertNoError(t, "GenerateKey", err)
   107  	diffieHellman := accesscontrol.NewDefaultSession(id0)
   108  	al := accesscontrol.NewLogic(diffieHellman)
   109  
   110  	s := kvsmock.New()
   111  	err = al.AddGrantee(ctx, s, &id0.PublicKey, &id0.PublicKey)
   112  	assertNoError(t, "AddGrantee publisher", err)
   113  
   114  	id1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   115  	assertNoError(t, "GenerateKey", err)
   116  	err = al.AddGrantee(ctx, s, &id0.PublicKey, &id1.PublicKey)
   117  	assertNoError(t, "AddGrantee id1", err)
   118  
   119  	byteRef, err := hex.DecodeString("39a5ea87b141fe44aa609c3327ecd896c0e2122897f5f4bbacf74db1033c5559")
   120  	assertNoError(t, "DecodeString", err)
   121  
   122  	expectedRef := swarm.NewAddress(byteRef)
   123  
   124  	encryptedRef, err := al.EncryptRef(ctx, s, &id0.PublicKey, expectedRef)
   125  	assertNoError(t, "al encryptref", err)
   126  
   127  	diffieHellman2 := accesscontrol.NewDefaultSession(id1)
   128  	granteeAccessLogic := accesscontrol.NewLogic(diffieHellman2)
   129  	actualRef, err := granteeAccessLogic.DecryptRef(ctx, s, encryptedRef, &id0.PublicKey)
   130  	assertNoError(t, "grantee al decryptref", err)
   131  
   132  	if !expectedRef.Equal(actualRef) {
   133  		assert.FailNowf(t, fmt.Sprintf("DecryptRef gave back wrong Swarm reference! Expedted: %v, actual: %v", expectedRef, actualRef), "")
   134  	}
   135  }
   136  
   137  func TestAddPublisher(t *testing.T) {
   138  	t.Parallel()
   139  	id0 := getPrivKey(0)
   140  	savedLookupKey := "b6ee086390c280eeb9824c331a4427596f0c8510d5564bc1b6168d0059a46e2b"
   141  	s := kvsmock.New()
   142  	ctx := context.Background()
   143  
   144  	al := setupAccessLogic()
   145  	err := al.AddGrantee(ctx, s, &id0.PublicKey, &id0.PublicKey)
   146  	assertNoError(t, "AddGrantee", err)
   147  
   148  	decodedSavedLookupKey, err := hex.DecodeString(savedLookupKey)
   149  	assertNoError(t, "decode LookupKey", err)
   150  
   151  	encryptedAccessKey, err := s.Get(ctx, decodedSavedLookupKey)
   152  	assertNoError(t, "kvs Get accesskey", err)
   153  
   154  	decodedEncryptedAccessKey := hex.EncodeToString(encryptedAccessKey)
   155  
   156  	// A random value is returned, so it is only possible to check the length of the returned value
   157  	// We know the lookup key because the generated private key is fixed
   158  	if len(decodedEncryptedAccessKey) != 64 {
   159  		assert.FailNowf(t, fmt.Sprintf("AddGrantee: expected encrypted access key length 64, got %d", len(decodedEncryptedAccessKey)), "")
   160  	}
   161  }
   162  
   163  func TestAddNewGranteeToContent(t *testing.T) {
   164  	t.Parallel()
   165  	id0 := getPrivKey(0)
   166  	id1 := getPrivKey(1)
   167  	id2 := getPrivKey(2)
   168  	ctx := context.Background()
   169  
   170  	publisherLookupKey := "b6ee086390c280eeb9824c331a4427596f0c8510d5564bc1b6168d0059a46e2b"
   171  	firstAddedGranteeLookupKey := "a13678e81f9d939b9401a3ad7e548d2ceb81c50f8c76424296e83a1ad79c0df0"
   172  	secondAddedGranteeLookupKey := "d5e9a6499ca74f5b8b958a4b89b7338045b2baa9420e115443a8050e26986564"
   173  
   174  	s := kvsmock.New()
   175  	al := setupAccessLogic()
   176  	err := al.AddGrantee(ctx, s, &id0.PublicKey, &id0.PublicKey)
   177  	assertNoError(t, "AddGrantee id0", err)
   178  
   179  	err = al.AddGrantee(ctx, s, &id0.PublicKey, &id1.PublicKey)
   180  	assertNoError(t, "AddGrantee id1", err)
   181  
   182  	err = al.AddGrantee(ctx, s, &id0.PublicKey, &id2.PublicKey)
   183  	assertNoError(t, "AddGrantee id2", err)
   184  
   185  	lookupKeyAsByte, err := hex.DecodeString(publisherLookupKey)
   186  	assertNoError(t, "publisher lookupkey DecodeString", err)
   187  
   188  	result, err := s.Get(ctx, lookupKeyAsByte)
   189  	assertNoError(t, "1st kvs get", err)
   190  	hexEncodedEncryptedAK := hex.EncodeToString(result)
   191  	if len(hexEncodedEncryptedAK) != 64 {
   192  		assert.FailNowf(t, fmt.Sprintf("AddNewGrantee: expected encrypted access key length 64, got %d", len(hexEncodedEncryptedAK)), "")
   193  	}
   194  
   195  	lookupKeyAsByte, err = hex.DecodeString(firstAddedGranteeLookupKey)
   196  	assertNoError(t, "1st lookupkey DecodeString", err)
   197  
   198  	result, err = s.Get(ctx, lookupKeyAsByte)
   199  	assertNoError(t, "2nd kvs get", err)
   200  	hexEncodedEncryptedAK = hex.EncodeToString(result)
   201  	if len(hexEncodedEncryptedAK) != 64 {
   202  		assert.FailNowf(t, fmt.Sprintf("AddNewGrantee: expected encrypted access key length 64, got %d", len(hexEncodedEncryptedAK)), "")
   203  	}
   204  
   205  	lookupKeyAsByte, err = hex.DecodeString(secondAddedGranteeLookupKey)
   206  	assertNoError(t, "2nd lookupkey DecodeString", err)
   207  
   208  	result, err = s.Get(ctx, lookupKeyAsByte)
   209  	assertNoError(t, "3rd kvs get", err)
   210  	hexEncodedEncryptedAK = hex.EncodeToString(result)
   211  	if len(hexEncodedEncryptedAK) != 64 {
   212  		assert.FailNowf(t, fmt.Sprintf("AddNewGrantee: expected encrypted access key length 64, got %d", len(hexEncodedEncryptedAK)), "")
   213  	}
   214  }