From bff56f93b456cb20fedc2a43e192fb852e9544a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Kokelj?= Date: Mon, 25 Mar 2024 14:35:07 +0100 Subject: [PATCH 1/3] remove legacy signature type --- go/common/viewingkey/viewing_key.go | 51 ++++++++----------- go/common/viewingkey/viewing_key_messages.go | 9 ---- go/common/viewingkey/viewing_key_signature.go | 19 ------- go/enclave/vkhandler/vk_handler.go | 6 --- tools/walletextension/common/constants.go | 2 - 5 files changed, 22 insertions(+), 65 deletions(-) diff --git a/go/common/viewingkey/viewing_key.go b/go/common/viewingkey/viewing_key.go index 464b29ca81..2098c2c8db 100644 --- a/go/common/viewingkey/viewing_key.go +++ b/go/common/viewingkey/viewing_key.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "fmt" - "github.com/ethereum/go-ethereum/accounts" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/ecies" @@ -33,41 +32,45 @@ type RPCSignedViewingKey struct { } // GenerateViewingKeyForWallet takes an account wallet, generates a viewing key and signs the key with the acc's private key -// uses the same method of signature handling as Metamask/geth -// TODO @Ziga - update this method to use the new EIP-712 signature format / personal sign after the removal of the legacy format func GenerateViewingKeyForWallet(wal wallet.Wallet) (*ViewingKey, error) { - // generate an ECDSA key pair to encrypt sensitive communications with the obscuro enclave - vk, err := crypto.GenerateKey() + chainID := int64(443) + messageType := PersonalSign + + // simulate what the gateway would do to generate the viewing key + viewingKeyPrivate, err := crypto.GenerateKey() + viewingPrivateKeyECIES := ecies.ImportECDSA(viewingKeyPrivate) if err != nil { - return nil, fmt.Errorf("failed to generate viewing key for RPC client: %w", err) + return nil, err } - - // get key in ECIES format - viewingPrivateKeyECIES := ecies.ImportECDSA(vk) - - // encode public key as bytes - viewingPubKeyBytes := crypto.CompressPubkey(&vk.PublicKey) - - // sign public key bytes with the wallet's private key - signature, err := mmSignViewingKey(viewingPubKeyBytes, wal.PrivateKey()) + encryptionToken := CalculateUserIDHex(crypto.CompressPubkey(viewingPrivateKeyECIES.PublicKey.ExportECDSA())) + messageToSign, err := GenerateMessage(encryptionToken, chainID, PersonalSignVersion, messageType) + if err != nil { + return nil, fmt.Errorf("failed to generate message for viewing key: %w", err) + } + msgHash, err := GetMessageHash(messageToSign, messageType) if err != nil { return nil, err } + signature, err := mmSignViewingKey(msgHash, wal.PrivateKey()) + if err != nil { + return nil, err + } + vkPubKeyBytes := crypto.CompressPubkey(ecies.ImportECDSAPublic(&viewingKeyPrivate.PublicKey).ExportECDSA()) accAddress := wal.Address() return &ViewingKey{ Account: &accAddress, PrivateKey: viewingPrivateKeyECIES, - PublicKey: viewingPubKeyBytes, + PublicKey: vkPubKeyBytes, SignatureWithAccountKey: signature, - SignatureType: Legacy, + SignatureType: PersonalSign, }, nil } // mmSignViewingKey takes a public key bytes as hex and the private key for a wallet, it simulates the back-and-forth to // MetaMask and returns the signature bytes to register with the enclave -func mmSignViewingKey(viewingPubKeyBytes []byte, signerKey *ecdsa.PrivateKey) ([]byte, error) { - signature, err := Sign(signerKey, viewingPubKeyBytes) +func mmSignViewingKey(messageHash []byte, signerKey *ecdsa.PrivateKey) ([]byte, error) { + signature, err := crypto.Sign(messageHash, signerKey) if err != nil { return nil, fmt.Errorf("failed to sign viewing key: %w", err) } @@ -89,13 +92,3 @@ func mmSignViewingKey(viewingPubKeyBytes []byte, signerKey *ecdsa.PrivateKey) ([ return outputSig, nil } - -// Sign takes a users Private key and signs the public viewingKey hex -func Sign(userPrivKey *ecdsa.PrivateKey, vkPubKey []byte) ([]byte, error) { - msgToSign := GenerateSignMessage(vkPubKey) - signature, err := crypto.Sign(accounts.TextHash([]byte(msgToSign)), userPrivKey) - if err != nil { - return nil, fmt.Errorf("unable to sign messages - %w", err) - } - return signature, nil -} diff --git a/go/common/viewingkey/viewing_key_messages.go b/go/common/viewingkey/viewing_key_messages.go index 036a82a99b..01ff4829e5 100644 --- a/go/common/viewingkey/viewing_key_messages.go +++ b/go/common/viewingkey/viewing_key_messages.go @@ -15,7 +15,6 @@ import ( const ( EIP712Signature SignatureType = 0 PersonalSign SignatureType = 1 - Legacy SignatureType = 2 ) // SignatureType is used to differentiate between different signature types (string is used, because int is not RLP-serializable) @@ -32,7 +31,6 @@ const ( EIP712DomainVersionValue = "1.0" UserIDHexLength = 40 PersonalSignMessageFormat = "Token: %s on chain: %d version: %d" - SignedMsgPrefix = "vk" // prefix for legacy signed messages (remove when legacy signature type is removed) PersonalSignVersion = 1 ) @@ -127,13 +125,6 @@ func GetMessageHash(message []byte, signatureType SignatureType) ([]byte, error) return hashFunction.getMessageHash(message), nil } -// GenerateSignMessage creates the message to be signed -// vkPubKey is expected to be a []byte("0x....") to create the signing message -// todo (@ziga) Remove this method once old WE endpoints are removed -func GenerateSignMessage(vkPubKey []byte) string { - return SignedMsgPrefix + hex.EncodeToString(vkPubKey) -} - // getBytesFromTypedData creates EIP-712 compliant hash from typedData. // It involves hashing the message with its structure, hashing domain separator, // and then encoding both hashes with specific EIP-712 bytes to construct the final message format. diff --git a/go/common/viewingkey/viewing_key_signature.go b/go/common/viewingkey/viewing_key_signature.go index 9c48f0b3cc..6737b5c574 100644 --- a/go/common/viewingkey/viewing_key_signature.go +++ b/go/common/viewingkey/viewing_key_signature.go @@ -6,7 +6,6 @@ import ( "fmt" "math/big" - "github.com/ethereum/go-ethereum/accounts" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ) @@ -20,7 +19,6 @@ type SignatureChecker interface { type ( PersonalSignChecker struct{} EIP712Checker struct{} - LegacyChecker struct{} ) // CheckSignature checks if signature is valid for provided encryptionToken and chainID and return address or nil if not valid @@ -83,27 +81,10 @@ func (e EIP712Checker) CheckSignature(encryptionToken string, signature []byte, return nil, errors.New("EIP 712 signature verification failed") } -// CheckSignature checks if signature is valid for provided encryptionToken and chainID and return address or nil if not valid -// todo (@ziga) Remove this method once old WE endpoints are removed -// encryptionToken is expected to be a public key and not encrypted token as with other signature types -// (since this is only temporary fix and legacy format will be removed soon) -func (lsc LegacyChecker) CheckSignature(encryptionToken string, signature []byte, _ int64) (*gethcommon.Address, error) { - publicKey := []byte(encryptionToken) - msgToSignLegacy := GenerateSignMessage(publicKey) - - recoveredAccountPublicKeyLegacy, err := crypto.SigToPub(accounts.TextHash([]byte(msgToSignLegacy)), signature) - if err != nil { - return nil, fmt.Errorf("failed to recover account public key from legacy signature: %w", err) - } - recoveredAccountAddressLegacy := crypto.PubkeyToAddress(*recoveredAccountPublicKeyLegacy) - return &recoveredAccountAddressLegacy, nil -} - // SignatureChecker is a map of SignatureType to SignatureChecker var signatureCheckers = map[SignatureType]SignatureChecker{ PersonalSign: PersonalSignChecker{}, EIP712Signature: EIP712Checker{}, - Legacy: LegacyChecker{}, } // CheckSignature checks if signature is valid for provided encryptionToken and chainID and return address or nil if not valid diff --git a/go/enclave/vkhandler/vk_handler.go b/go/enclave/vkhandler/vk_handler.go index b9245f3ad6..06d6d27335 100644 --- a/go/enclave/vkhandler/vk_handler.go +++ b/go/enclave/vkhandler/vk_handler.go @@ -51,12 +51,6 @@ func checkViewingKeyAndRecoverAddress(vk *AuthenticatedViewingKey, chainID int64 userID := viewingkey.CalculateUserIDHex(vk.rpcVK.PublicKey) vk.UserID = userID - // todo - remove this when the legacy format is no longer supported - // this is a temporary fix to support the legacy format which will be removed soon - if vk.rpcVK.SignatureType == viewingkey.Legacy { - userID = string(vk.rpcVK.PublicKey) // for legacy format, the userID is the public key - } - // check the signature and recover the address assuming the message was signed with EIP712 recoveredSignerAddress, err := viewingkey.CheckSignature(userID, vk.rpcVK.SignatureWithAccountKey, chainID, vk.rpcVK.SignatureType) if err != nil { diff --git a/tools/walletextension/common/constants.go b/tools/walletextension/common/constants.go index 6adbde8737..55d1da0ac4 100644 --- a/tools/walletextension/common/constants.go +++ b/tools/walletextension/common/constants.go @@ -30,8 +30,6 @@ const ( PathRoot = "/" PathReady = "/ready/" PathViewingKeys = "/viewingkeys/" - PathGenerateViewingKey = "/generateviewingkey/" - PathSubmitViewingKey = "/submitviewingkey/" PathJoin = "/join/" PathGetMessage = "/getmessage/" PathAuthenticate = "/authenticate/" From 1355f0b3b97c635ccd10b120a8957913f008b5ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Kokelj?= Date: Mon, 25 Mar 2024 15:38:33 +0100 Subject: [PATCH 2/3] use smoke_test without the gateway --- integration/networktest/tests/helpful/smoke_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/integration/networktest/tests/helpful/smoke_test.go b/integration/networktest/tests/helpful/smoke_test.go index c14777e18f..a97bbf54a5 100644 --- a/integration/networktest/tests/helpful/smoke_test.go +++ b/integration/networktest/tests/helpful/smoke_test.go @@ -4,10 +4,8 @@ import ( "math/big" "testing" - "github.com/ten-protocol/go-ten/integration/networktest/actions" - "github.com/ten-protocol/go-ten/integration/simulation/devnetwork" - "github.com/ten-protocol/go-ten/integration/networktest" + "github.com/ten-protocol/go-ten/integration/networktest/actions" "github.com/ten-protocol/go-ten/integration/networktest/env" ) @@ -20,7 +18,7 @@ func TestExecuteNativeFundsTransfer(t *testing.T) { networktest.Run( "native-funds-smoketest", t, - env.LocalDevNetwork(devnetwork.WithGateway()), + env.LocalDevNetwork(), actions.Series( &actions.CreateTestUser{UserID: 0}, &actions.CreateTestUser{UserID: 1}, From ea0ab5aaa4c4bcf17e02e210056a3d1e13b59e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Kokelj?= Date: Mon, 25 Mar 2024 15:54:04 +0100 Subject: [PATCH 3/3] use chainID from wallet --- go/common/viewingkey/viewing_key.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/common/viewingkey/viewing_key.go b/go/common/viewingkey/viewing_key.go index 2098c2c8db..6d70a59977 100644 --- a/go/common/viewingkey/viewing_key.go +++ b/go/common/viewingkey/viewing_key.go @@ -33,7 +33,7 @@ type RPCSignedViewingKey struct { // GenerateViewingKeyForWallet takes an account wallet, generates a viewing key and signs the key with the acc's private key func GenerateViewingKeyForWallet(wal wallet.Wallet) (*ViewingKey, error) { - chainID := int64(443) + chainID := wal.ChainID().Int64() messageType := PersonalSign // simulate what the gateway would do to generate the viewing key