From a38b4ab2e2f51416edef640e36f74f1bc2681ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Kokelj?= Date: Mon, 18 Mar 2024 12:09:25 +0100 Subject: [PATCH] Ziga/add personal sign authentication message and refactor signature verification (#1811) --- go/common/viewingkey/viewing_key.go | 230 ++++++++++++------ go/enclave/vkhandler/vk_handler.go | 41 +--- go/enclave/vkhandler/vk_handler_test.go | 137 ++++++----- go/rpc/encrypted_client.go | 4 +- integration/obscurogateway/gateway_user.go | 12 + integration/obscurogateway/tengateway_test.go | 21 +- .../accountmanager/account_manager.go | 4 +- tools/walletextension/api/routes.go | 15 +- tools/walletextension/common/common.go | 2 + tools/walletextension/common/constants.go | 9 + tools/walletextension/common/types.go | 1 + .../container/walletextension_container.go | 4 +- tools/walletextension/lib/client_lib.go | 45 ++++ .../mariadb/003_add_signature_type.sql | 2 + .../storage/database/mariadb/mariadb.go | 12 +- .../storage/database/sqlite/sqlite.go | 13 +- tools/walletextension/storage/storage.go | 4 +- tools/walletextension/storage/storage_test.go | 6 +- tools/walletextension/test/apis.go | 2 +- .../user_account_manager.go | 4 +- tools/walletextension/wallet_extension.go | 15 +- 21 files changed, 385 insertions(+), 198 deletions(-) create mode 100644 tools/walletextension/storage/database/mariadb/003_add_signature_type.sql diff --git a/go/common/viewingkey/viewing_key.go b/go/common/viewingkey/viewing_key.go index 2392f74351..c46c285585 100644 --- a/go/common/viewingkey/viewing_key.go +++ b/go/common/viewingkey/viewing_key.go @@ -26,48 +26,157 @@ import ( const SignedMsgPrefix = "vk" const ( - EIP712Domain = "EIP712Domain" - EIP712Type = "Authentication" - EIP712DomainName = "name" - EIP712DomainVersion = "version" - EIP712DomainChainID = "chainId" - EIP712EncryptionToken = "Encryption Token" - // EIP712EncryptionTokenV2 is used to support older versions of third party libraries - // that don't have the support for spaces in type names - EIP712EncryptionTokenV2 = "EncryptionToken" - EIP712DomainNameValue = "Ten" - EIP712DomainVersionValue = "1.0" - UserIDHexLength = 40 + EIP712Domain = "EIP712Domain" + EIP712Type = "Authentication" + EIP712DomainName = "name" + EIP712DomainVersion = "version" + EIP712DomainChainID = "chainId" + EIP712EncryptionToken = "Encryption Token" + EIP712DomainNameValue = "Ten" + EIP712DomainVersionValue = "1.0" + UserIDHexLength = 40 + PersonalSignMessageFormat = "Token: %s on chain: %d version:%d" +) + +const ( + EIP712Signature SignatureType = 0 + PersonalSign SignatureType = 1 + Legacy SignatureType = 2 ) // EIP712EncryptionTokens is a list of all possible options for Encryption token name var EIP712EncryptionTokens = [...]string{ EIP712EncryptionToken, - EIP712EncryptionTokenV2, } +// PersonalSignMessageSupportedVersions is a list of supported versions for the personal sign message +var PersonalSignMessageSupportedVersions = []int{1} + +// SignatureType is used to differentiate between different signature types (string is used, because int is not RLP-serializable) +type SignatureType uint8 + // ViewingKey encapsulates the signed viewing key for an account for use in encrypted communication with an enclave. -// It is th client-side perspective of the viewing key used for decrypting incoming traffic. +// It is the client-side perspective of the viewing key used for decrypting incoming traffic. type ViewingKey struct { Account *gethcommon.Address // Account address that this Viewing Key is bound to - Users Pubkey address PrivateKey *ecies.PrivateKey // ViewingKey private key to encrypt data to the enclave PublicKey []byte // ViewingKey public key in decrypt data from the enclave SignatureWithAccountKey []byte // ViewingKey public key signed by the Accounts Private key - Allows to retrieve the Account address + SignatureType SignatureType // Type of signature used to sign the public key } // RPCSignedViewingKey - used for transporting a minimalist viewing key via // every RPC request to a sensitive method, including Log subscriptions. // only the public key and the signature are required // the account address is sent as well to aid validation -// todo - send the type of Message that was signed instead of the Account type RPCSignedViewingKey struct { - Account *gethcommon.Address PublicKey []byte SignatureWithAccountKey []byte + SignatureType SignatureType +} + +// SignatureChecker is an interface for checking +// if signature is valid for provided encryptionToken and chainID and return singing address or nil if not valid +type SignatureChecker interface { + CheckSignature(encryptionToken string, signature []byte, chainID int64) (*gethcommon.Address, error) +} + +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 +func (psc PersonalSignChecker) CheckSignature(encryptionToken string, signature []byte, chainID int64) (*gethcommon.Address, error) { + if len(signature) != 65 { + return nil, fmt.Errorf("invalid signaure length: %d", len(signature)) + } + // We transform the V from 27/28 to 0/1. This same change is made in Geth internals, for legacy reasons to be able + // to recover the address: https://github.com/ethereum/go-ethereum/blob/55599ee95d4151a2502465e0afc7c47bd1acba77/internal/ethapi/api.go#L452-L459 + if signature[64] == 27 || signature[64] == 28 { + signature[64] -= 27 + } + + // create all possible hashes (for all the supported versions) of the message (needed for signature verification) + for _, version := range PersonalSignMessageSupportedVersions { + message := GeneratePersonalSignMessage(encryptionToken, chainID, version) + messageHash := accounts.TextHash([]byte(message)) + + // current signature is valid - return account address + address, err := CheckSignatureAndReturnAccountAddress(messageHash, signature) + if err == nil { + return address, nil + } + } + + return nil, fmt.Errorf("signature verification failed") +} + +func (e EIP712Checker) CheckSignature(encryptionToken string, signature []byte, chainID int64) (*gethcommon.Address, error) { + if len(signature) != 65 { + return nil, fmt.Errorf("invalid signaure length: %d", len(signature)) + } + + rawDataOptions, err := GenerateAuthenticationEIP712RawDataOptions(encryptionToken, chainID) + if err != nil { + return nil, fmt.Errorf("cannot generate eip712 message. Cause %w", err) + } + + // We transform the V from 27/28 to 0/1. This same change is made in Geth internals, for legacy reasons to be able + // to recover the address: https://github.com/ethereum/go-ethereum/blob/55599ee95d4151a2502465e0afc7c47bd1acba77/internal/ethapi/api.go#L452-L459 + if signature[64] == 27 || signature[64] == 28 { + signature[64] -= 27 + } + + for _, rawData := range rawDataOptions { + // create a hash of structured message (needed for signature verification) + hashBytes := crypto.Keccak256(rawData) + + // current signature is valid - return account address + address, err := CheckSignatureAndReturnAccountAddress(hashBytes, signature) + if err == nil { + return address, nil + } + } + 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 +func CheckSignature(encryptionToken string, signature []byte, chainID int64, signatureType SignatureType) (*gethcommon.Address, error) { + checker, exists := signatureCheckers[signatureType] + if !exists { + return nil, fmt.Errorf("unsupported signature type") + } + return checker.CheckSignature(encryptionToken, signature, chainID) } // 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() @@ -93,6 +202,7 @@ func GenerateViewingKeyForWallet(wal wallet.Wallet) (*ViewingKey, error) { PrivateKey: viewingPrivateKeyECIES, PublicKey: viewingPubKeyBytes, SignatureWithAccountKey: signature, + SignatureType: Legacy, }, nil } @@ -139,6 +249,10 @@ func GenerateSignMessage(vkPubKey []byte) string { return SignedMsgPrefix + hex.EncodeToString(vkPubKey) } +func GeneratePersonalSignMessage(encryptionToken string, chainID int64, version int) string { + return fmt.Sprintf(PersonalSignMessageFormat, encryptionToken, chainID, version) +} + // 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. @@ -159,6 +273,7 @@ func getBytesFromTypedData(typedData apitypes.TypedData) ([]byte, error) { // GenerateAuthenticationEIP712RawDataOptions generates all the options or raw data messages (bytes) // for an EIP-712 message used to authenticate an address with user +// (currently only one option is supported, but function leaves room for future expansion of options) func GenerateAuthenticationEIP712RawDataOptions(userID string, chainID int64) ([][]byte, error) { if len(userID) != UserIDHexLength { return nil, fmt.Errorf("userID hex length must be %d, received %d", UserIDHexLength, len(userID)) @@ -171,40 +286,35 @@ func GenerateAuthenticationEIP712RawDataOptions(userID string, chainID int64) ([ ChainId: (*math.HexOrDecimal256)(big.NewInt(chainID)), } - typedDataList := make([]apitypes.TypedData, 0, len(EIP712EncryptionTokens)) - for _, encTokenName := range EIP712EncryptionTokens { - message := map[string]interface{}{ - encTokenName: encryptionToken, - } + message := map[string]interface{}{ + EIP712EncryptionToken: encryptionToken, + } - types := apitypes.Types{ - EIP712Domain: { - {Name: EIP712DomainName, Type: "string"}, - {Name: EIP712DomainVersion, Type: "string"}, - {Name: EIP712DomainChainID, Type: "uint256"}, - }, - EIP712Type: { - {Name: encTokenName, Type: "address"}, - }, - } + types := apitypes.Types{ + EIP712Domain: { + {Name: EIP712DomainName, Type: "string"}, + {Name: EIP712DomainVersion, Type: "string"}, + {Name: EIP712DomainChainID, Type: "uint256"}, + }, + EIP712Type: { + {Name: EIP712EncryptionToken, Type: "address"}, + }, + } - newTypeElement := apitypes.TypedData{ - Types: types, - PrimaryType: EIP712Type, - Domain: domain, - Message: message, - } - typedDataList = append(typedDataList, newTypeElement) + newTypeElement := apitypes.TypedData{ + Types: types, + PrimaryType: EIP712Type, + Domain: domain, + Message: message, } - rawDataOptions := make([][]byte, 0, len(typedDataList)) - for _, typedDataItem := range typedDataList { - rawData, err := getBytesFromTypedData(typedDataItem) - if err != nil { - return nil, err - } - rawDataOptions = append(rawDataOptions, rawData) + rawDataOptions := make([][]byte, 0) + rawData, err := getBytesFromTypedData(newTypeElement) + if err != nil { + return nil, err } + rawDataOptions = append(rawDataOptions, rawData) + return rawDataOptions, nil } @@ -244,33 +354,3 @@ func CheckSignatureAndReturnAccountAddress(hashBytes []byte, signature []byte) ( } return nil, fmt.Errorf("invalid signature") } - -// CheckEIP712Signature checks if signature is valid for provided userID and chainID and return address or nil if not valid -func CheckEIP712Signature(userID string, signature []byte, chainID int64) (*gethcommon.Address, error) { - if len(signature) != 65 { - return nil, fmt.Errorf("invalid signaure length: %d", len(signature)) - } - - rawDataOptions, err := GenerateAuthenticationEIP712RawDataOptions(userID, chainID) - if err != nil { - return nil, fmt.Errorf("cannot generate eip712 message. Cause %w", err) - } - - // We transform the V from 27/28 to 0/1. This same change is made in Geth internals, for legacy reasons to be able - // to recover the address: https://github.com/ethereum/go-ethereum/blob/55599ee95d4151a2502465e0afc7c47bd1acba77/internal/ethapi/api.go#L452-L459 - if signature[64] == 27 || signature[64] == 28 { - signature[64] -= 27 - } - - for _, rawData := range rawDataOptions { - // create a hash of structured message (needed for signature verification) - hashBytes := crypto.Keccak256(rawData) - - // current signature is valid - return account address - address, err := CheckSignatureAndReturnAccountAddress(hashBytes, signature) - if err == nil { - return address, nil - } - } - return nil, errors.New("EIP 712 signature verification failed") -} diff --git a/go/enclave/vkhandler/vk_handler.go b/go/enclave/vkhandler/vk_handler.go index 3d1dd9eab8..b9245f3ad6 100644 --- a/go/enclave/vkhandler/vk_handler.go +++ b/go/enclave/vkhandler/vk_handler.go @@ -5,7 +5,6 @@ import ( "fmt" "io" - "github.com/ethereum/go-ethereum/accounts" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ten-protocol/go-ten/go/common/viewingkey" @@ -32,9 +31,8 @@ func VerifyViewingKey(rpcVK *viewingkey.RPCSignedViewingKey, chainID int64) (*Au } rvk := &AuthenticatedViewingKey{ - AccountAddress: rpcVK.Account, - rpcVK: rpcVK, - ecdsaKey: ecies.ImportECDSAPublic(vkPubKey), + rpcVK: rpcVK, + ecdsaKey: ecies.ImportECDSAPublic(vkPubKey), } // 2. Authenticate @@ -47,42 +45,25 @@ func VerifyViewingKey(rpcVK *viewingkey.RPCSignedViewingKey, chainID int64) (*Au return rvk, nil } -// this method is unnecessarily complex due to a legacy signing format +// checkViewingKeyAndRecoverAddress checks the signature and recovers the address from the viewing key func checkViewingKeyAndRecoverAddress(vk *AuthenticatedViewingKey, chainID int64) (*gethcommon.Address, error) { // get userID from viewingKey public key userID := viewingkey.CalculateUserIDHex(vk.rpcVK.PublicKey) vk.UserID = userID - // check signature and recover the address assuming the message was signed with EIP712 - recoveredSignerAddress, err := viewingkey.CheckEIP712Signature(userID, vk.rpcVK.SignatureWithAccountKey, chainID) - if err != nil { - // Signature failed - // Either it is invalid or it might have been using the legacy format - legacyMessageHash := accounts.TextHash([]byte(viewingkey.GenerateSignMessage(vk.rpcVK.PublicKey))) - _, err = viewingkey.CheckSignatureAndReturnAccountAddress(legacyMessageHash, vk.rpcVK.SignatureWithAccountKey) - if err != nil { - return nil, fmt.Errorf("invalid vk signature") - } - } - - // compare the recovered address against the address declared in the vk - if recoveredSignerAddress != nil && recoveredSignerAddress.Hex() == vk.AccountAddress.Hex() { - return vk.AccountAddress, nil + // 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 } - // recover the address using the legacy format and compare with the vk address - // TODO @Ziga - this must be removed. - msgToSignLegacy := viewingkey.GenerateSignMessage(vk.rpcVK.PublicKey) - recoveredAccountPublicKeyLegacy, err := crypto.SigToPub(accounts.TextHash([]byte(msgToSignLegacy)), vk.rpcVK.SignatureWithAccountKey) + // 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 { - return nil, fmt.Errorf("invalid vk signature - %w", err) - } - recoveredAccountAddressLegacy := crypto.PubkeyToAddress(*recoveredAccountPublicKeyLegacy) - if recoveredAccountAddressLegacy.Hex() != vk.AccountAddress.Hex() { - return nil, fmt.Errorf("invalid VK") + return nil, fmt.Errorf("signature verification failed %w", err) } - return vk.AccountAddress, err + return recoveredSignerAddress, err } // crypto.rand is quite slow. When this variable is true, we will use a fast CSPRNG algorithm diff --git a/go/enclave/vkhandler/vk_handler_test.go b/go/enclave/vkhandler/vk_handler_test.go index 15146ce73d..7d66185c86 100644 --- a/go/enclave/vkhandler/vk_handler_test.go +++ b/go/enclave/vkhandler/vk_handler_test.go @@ -1,8 +1,12 @@ package vkhandler import ( + "crypto/ecdsa" + "fmt" "testing" + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/ecies" @@ -12,96 +16,109 @@ import ( const chainID = 443 -func TestVKHandler(t *testing.T) { - // generate user private Key - userPrivKey, err := crypto.GenerateKey() +// generateRandomUserKeys - +// generates a random user private key and a random viewing key private key and returns the user private key, +// the viewing key private key, the userID and the user address +func generateRandomUserKeys() (*ecdsa.PrivateKey, *ecdsa.PrivateKey, string, gethcommon.Address) { + userPrivKey, err := crypto.GenerateKey() // user private key if err != nil { - t.Fatalf(err.Error()) + return nil, nil, "", gethcommon.Address{} } - userAccAddress := crypto.PubkeyToAddress(userPrivKey.PublicKey) - - // generate ViewingKey private Key - vkPrivKey, err := crypto.GenerateKey() + vkPrivKey, _ := crypto.GenerateKey() // viewingkey generated in the gateway if err != nil { - t.Fatalf(err.Error()) + return nil, nil, "", gethcommon.Address{} } + + // get the address from userPrivKey + userAddress := crypto.PubkeyToAddress(userPrivKey.PublicKey) + + // get userID from viewingKey public key vkPubKeyBytes := crypto.CompressPubkey(ecies.ImportECDSAPublic(&vkPrivKey.PublicKey).ExportECDSA()) userID := viewingkey.CalculateUserIDHex(vkPubKeyBytes) - WEMessageFormatTestHash := accounts.TextHash([]byte(viewingkey.GenerateSignMessage(vkPubKeyBytes))) + + return userPrivKey, vkPrivKey, userID, userAddress +} + +// MessageWithSignatureType - struct to hold the message hash and the signature type for testing purposes +type MessageWithSignatureType struct { + Hash []byte + SignatureType viewingkey.SignatureType +} + +func TestCheckSignature(t *testing.T) { + userPrivKey, _, userID, userAddress := generateRandomUserKeys() + + // Generate all message types and create map with the corresponding signature type + // Test EIP712 message format EIP712MessageDataOptions, err := viewingkey.GenerateAuthenticationEIP712RawDataOptions(userID, chainID) if err != nil { t.Fatalf(err.Error()) } - if len(EIP712MessageDataOptions) == 0 { - t.Fatalf("GenerateAuthenticationEIP712RawDataOptions returned no results") - } - EIP712MessageFormatTestHash := crypto.Keccak256(EIP712MessageDataOptions[0]) + EIP712MessageHash := crypto.Keccak256(EIP712MessageDataOptions[0]) + PersonalSignMessageHash := accounts.TextHash([]byte(viewingkey.GeneratePersonalSignMessage(userID, chainID, viewingkey.PersonalSignMessageSupportedVersions[0]))) - tests := map[string][]byte{ - "WEMessageFormatTest": WEMessageFormatTestHash, - "EIP712MessageFormatTest": EIP712MessageFormatTestHash, + messages := map[string]MessageWithSignatureType{ + "EIP712MessageHash": { + Hash: EIP712MessageHash, + SignatureType: viewingkey.EIP712Signature, + }, + "PersonalSignMessageHash": { + Hash: PersonalSignMessageHash, + SignatureType: viewingkey.PersonalSign, + }, } - - for testName, msgHashToSign := range tests { + // sign each message hash with the user private key and check the signature with the corresponding signature type + for testName, message := range messages { + fmt.Println(testName) t.Run(testName, func(t *testing.T) { - signature, err := crypto.Sign(msgHashToSign, userPrivKey) + signature, err := crypto.Sign(message.Hash, userPrivKey) assert.NoError(t, err) - // Create a new vk Handler - _, err = VerifyViewingKey(&viewingkey.RPCSignedViewingKey{ - Account: &userAccAddress, - PublicKey: vkPubKeyBytes, - SignatureWithAccountKey: signature, - }, chainID) + addr, err := viewingkey.CheckSignature(userID, signature, chainID, message.SignatureType) assert.NoError(t, err) + + assert.Equal(t, userAddress.Hex(), addr.Hex()) }) } } -func TestSignAndCheckSignature(t *testing.T) { - // generate user private Key - userPrivKey, err := crypto.GenerateKey() - if err != nil { - t.Fatalf(err.Error()) - } - userAddr := crypto.PubkeyToAddress(userPrivKey.PublicKey) - - // generate ViewingKey private Key - vkPrivKey, err := crypto.GenerateKey() - if err != nil { - t.Fatalf(err.Error()) - } - vkPubKeyBytes := crypto.CompressPubkey(ecies.ImportECDSAPublic(&vkPrivKey.PublicKey).ExportECDSA()) - userID := viewingkey.CalculateUserIDHex(vkPubKeyBytes) - WEMessageFormatTestHash := accounts.TextHash([]byte(viewingkey.GenerateSignMessage(vkPubKeyBytes))) - EIP712MessageData, err := viewingkey.GenerateAuthenticationEIP712RawDataOptions(userID, chainID) +func TestVerifyViewingKey(t *testing.T) { + userPrivKey, vkPrivKey, userID, userAddress := generateRandomUserKeys() + // Generate all message types and create map with the corresponding signature type + // Test EIP712 message format + EIP712MessageDataOptions, err := viewingkey.GenerateAuthenticationEIP712RawDataOptions(userID, chainID) if err != nil { t.Fatalf(err.Error()) } - EIP712MessageFormatTestHash := crypto.Keccak256(EIP712MessageData[0]) + EIP712MessageHash := crypto.Keccak256(EIP712MessageDataOptions[0]) + PersonalSignMessageHash := accounts.TextHash([]byte(viewingkey.GeneratePersonalSignMessage(userID, chainID, viewingkey.PersonalSignMessageSupportedVersions[0]))) - tests := map[string][]byte{ - "WEMessageFormatTest": WEMessageFormatTestHash, - "EIP712MessageFormatTest": EIP712MessageFormatTestHash, + messages := map[string]MessageWithSignatureType{ + "EIP712MessageHash": { + Hash: EIP712MessageHash, + SignatureType: viewingkey.EIP712Signature, + }, + "PersonalSignMessageHash": { + Hash: PersonalSignMessageHash, + SignatureType: viewingkey.PersonalSign, + }, } - for testName, msgHashToSign := range tests { + for testName, message := range messages { t.Run(testName, func(t *testing.T) { - // sign the message - signature, err := crypto.Sign(msgHashToSign, userPrivKey) + signature, err := crypto.Sign(message.Hash, userPrivKey) assert.NoError(t, err) - // Recover the key based on the signed message and the signature. - recoveredAccountPublicKey, err := crypto.SigToPub(msgHashToSign, signature) - assert.NoError(t, err) - recoveredAccountAddress := crypto.PubkeyToAddress(*recoveredAccountPublicKey) - - if recoveredAccountAddress.Hex() != userAddr.Hex() { - t.Fatalf("Expected user address %s, got %s", userAddr.Hex(), recoveredAccountAddress.Hex()) - } - - _, err = crypto.DecompressPubkey(vkPubKeyBytes) + vkPubKeyBytes := crypto.CompressPubkey(ecies.ImportECDSAPublic(&vkPrivKey.PublicKey).ExportECDSA()) + // Create a new vk Handler + rpcSignedVK, err := VerifyViewingKey(&viewingkey.RPCSignedViewingKey{ + PublicKey: vkPubKeyBytes, + SignatureWithAccountKey: signature, + SignatureType: message.SignatureType, + }, chainID) assert.NoError(t, err) + assert.Equal(t, rpcSignedVK.UserID, userID) + assert.Equal(t, rpcSignedVK.AccountAddress.Hex(), userAddress.Hex()) }) } } diff --git a/go/rpc/encrypted_client.go b/go/rpc/encrypted_client.go index 01d31f87b4..2412d8af50 100644 --- a/go/rpc/encrypted_client.go +++ b/go/rpc/encrypted_client.go @@ -172,7 +172,7 @@ func (c *EncRPCClient) createAuthenticatedLogSubscription(args []interface{}) (* ViewingKey: &viewingkey.RPCSignedViewingKey{ PublicKey: c.viewingKey.PublicKey, SignatureWithAccountKey: c.viewingKey.SignatureWithAccountKey, - Account: c.Account(), + SignatureType: c.viewingKey.SignatureType, }, } @@ -305,9 +305,9 @@ func (c *EncRPCClient) encryptArgs(args ...interface{}) ([]byte, error) { return nil, nil } vk := viewingkey.RPCSignedViewingKey{ - Account: c.Account(), PublicKey: c.viewingKey.PublicKey, SignatureWithAccountKey: c.viewingKey.SignatureWithAccountKey, + SignatureType: c.viewingKey.SignatureType, } argsWithVK := &rpc.RequestWithVk{VK: &vk, Params: args} diff --git a/integration/obscurogateway/gateway_user.go b/integration/obscurogateway/gateway_user.go index 43043415f4..3f425d351c 100644 --- a/integration/obscurogateway/gateway_user.go +++ b/integration/obscurogateway/gateway_user.go @@ -61,6 +61,18 @@ func (u GatewayUser) RegisterAccounts() error { return nil } +func (u GatewayUser) RegisterAccountsPersonalSign() error { + for _, w := range u.Wallets { + err := u.tgClient.RegisterAccountPersonalSign(w.PrivateKey(), w.Address()) + if err != nil { + return err + } + testlog.Logger().Info(fmt.Sprintf("Successfully registered address %s for user: %s. With personal sign message", w.Address().Hex(), u.tgClient.UserID())) + } + + return nil +} + func (u GatewayUser) GetUserAccountsBalances() ([]*big.Int, error) { balances := []*big.Int{} for _, w := range u.Wallets { diff --git a/integration/obscurogateway/tengateway_test.go b/integration/obscurogateway/tengateway_test.go index 380e598be7..774a2a4d19 100644 --- a/integration/obscurogateway/tengateway_test.go +++ b/integration/obscurogateway/tengateway_test.go @@ -101,6 +101,7 @@ func TestTenGateway(t *testing.T) { "testUnsubscribe": testUnsubscribe, "testClosingConnectionWhileSubscribed": testClosingConnectionWhileSubscribed, "testSubscriptionTopics": testSubscriptionTopics, + "testDifferentMessagesOnRegister": testDifferentMessagesOnRegister, } { t.Run(name, func(t *testing.T) { test(t, httpURL, wsURL, w) @@ -128,11 +129,11 @@ func testMultipleAccountsSubscription(t *testing.T, httpURL, wsURL string, w wal testlog.Logger().Info("Created user with encryption token", "t", user2.tgClient.UserID()) // register all the accounts for that user - err = user0.RegisterAccounts() + err = user0.RegisterAccountsPersonalSign() require.NoError(t, err) - err = user1.RegisterAccounts() + err = user1.RegisterAccountsPersonalSign() require.NoError(t, err) - err = user2.RegisterAccounts() + err = user2.RegisterAccountsPersonalSign() require.NoError(t, err) var amountToTransfer int64 = 1_000_000_000_000_000_000 @@ -605,6 +606,20 @@ func testClosingConnectionWhileSubscribed(t *testing.T, httpURL, wsURL string, w subscription.Unsubscribe() } +func testDifferentMessagesOnRegister(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { + user, err := NewUser([]wallet.Wallet{w, datagenerator.RandomWallet(integration.TenChainID)}, httpURL, wsURL) + require.NoError(t, err) + testlog.Logger().Info("Created user with encryption token: %s\n", user.tgClient.UserID()) + + // register all the accounts for the user with EIP-712 message format + err = user.RegisterAccounts() + require.NoError(t, err) + + // register all the accounts for the user with personal sign message format + err = user.RegisterAccountsPersonalSign() + require.NoError(t, err) +} + func transferRandomAddr(t *testing.T, client *ethclient.Client, w wallet.Wallet) common.TxHash { //nolint: unused ctx := context.Background() toAddr := datagenerator.RandomAddress() diff --git a/tools/walletextension/accountmanager/account_manager.go b/tools/walletextension/accountmanager/account_manager.go index 6d7ab47f20..126adc134e 100644 --- a/tools/walletextension/accountmanager/account_manager.go +++ b/tools/walletextension/accountmanager/account_manager.go @@ -8,6 +8,8 @@ import ( "strings" "sync" + "github.com/ten-protocol/go-ten/go/common/viewingkey" + "github.com/ethereum/go-ethereum/eth/filters" "github.com/ten-protocol/go-ten/go/common" @@ -186,7 +188,7 @@ func (m *AccountManager) filterAccounts(rpcReq *wecommon.RPCRequest, accounts [] func (m *AccountManager) createClientsForAccounts(accounts []wecommon.AccountDB, userPrivateKey []byte) ([]rpc.Client, error) { clients := make([]rpc.Client, 0, len(accounts)) for _, account := range accounts { - encClient, err := wecommon.CreateEncClient(m.hostRPCBindAddrWS, account.AccountAddress, userPrivateKey, account.Signature, m.logger) + encClient, err := wecommon.CreateEncClient(m.hostRPCBindAddrWS, account.AccountAddress, userPrivateKey, account.Signature, viewingkey.SignatureType(account.SignatureType), m.logger) if err != nil { m.logger.Error(fmt.Errorf("error creating new client, %w", err).Error()) continue diff --git a/tools/walletextension/api/routes.go b/tools/walletextension/api/routes.go index eabb7e1845..625cd9ad7a 100644 --- a/tools/walletextension/api/routes.go +++ b/tools/walletextension/api/routes.go @@ -38,7 +38,6 @@ func NewHTTPRoutes(walletExt *walletextension.WalletExtension) []Route { Name: common.PathGenerateViewingKey, Func: httpHandler(walletExt, generateViewingKeyRequestHandler), }, - { Name: common.PathSubmitViewingKey, Func: httpHandler(walletExt, submitViewingKeyRequestHandler), @@ -318,6 +317,18 @@ func authenticateRequestHandler(walletExt *walletextension.WalletExtension, conn return } + // get optional type of the message that was signed + messageTypeValue := common.DefaultGatewayAuthMessageType + if typeFromRequest, ok := reqJSONMap[common.JSONKeyType]; ok && typeFromRequest != "" { + messageTypeValue = typeFromRequest + } + + // check if message type is valid + messageType, ok := common.SignatureTypeMap[messageTypeValue] + if !ok { + handleError(conn, walletExt.Logger(), fmt.Errorf("invalid message type: %s", messageTypeValue)) + } + // read userID from query params hexUserID, err := getUserID(conn, 2) if err != nil { @@ -326,7 +337,7 @@ func authenticateRequestHandler(walletExt *walletextension.WalletExtension, conn } // check signature and add address and signature for that user - err = walletExt.AddAddressToUser(hexUserID, address, signature) + err = walletExt.AddAddressToUser(hexUserID, address, signature, messageType) if err != nil { handleError(conn, walletExt.Logger(), fmt.Errorf("internal error")) walletExt.Logger().Error(fmt.Sprintf("error adding address: %s to user: %s with signature: %s", address, hexUserID, signature)) diff --git a/tools/walletextension/common/common.go b/tools/walletextension/common/common.go index 56df40c86a..8a13de5a3d 100644 --- a/tools/walletextension/common/common.go +++ b/tools/walletextension/common/common.go @@ -44,6 +44,7 @@ func CreateEncClient( addressBytes []byte, privateKeyBytes []byte, signature []byte, + signatureType viewingkey.SignatureType, logger gethlog.Logger, ) (*rpc.EncRPCClient, error) { privateKey, err := BytesToPrivateKey(privateKeyBytes) @@ -58,6 +59,7 @@ func CreateEncClient( PrivateKey: privateKey, PublicKey: PrivateKeyToCompressedPubKey(privateKey), SignatureWithAccountKey: signature, + SignatureType: signatureType, } encClient, err := rpc.NewEncNetworkClient(hostRPCBindAddr, vk, logger) if err != nil { diff --git a/tools/walletextension/common/constants.go b/tools/walletextension/common/constants.go index 0edcc92871..8e66ea55dd 100644 --- a/tools/walletextension/common/constants.go +++ b/tools/walletextension/common/constants.go @@ -2,6 +2,8 @@ package common import ( "time" + + "github.com/ten-protocol/go-ten/go/common/viewingkey" ) const ( @@ -21,6 +23,7 @@ const ( JSONKeySubscription = "subscription" JSONKeyCode = "code" JSONKeyMessage = "message" + JSONKeyType = "type" ) const ( @@ -50,6 +53,12 @@ const ( MethodEthSubscription = "eth_subscription" PathVersion = "/version/" DeduplicationBufferSize = 20 + DefaultGatewayAuthMessageType = "EIP712" ) var ReaderHeadTimeout = 10 * time.Second + +var SignatureTypeMap = map[string]viewingkey.SignatureType{ + "EIP712": viewingkey.EIP712Signature, + "Personal": viewingkey.PersonalSign, +} diff --git a/tools/walletextension/common/types.go b/tools/walletextension/common/types.go index 8943fccc7b..cde690813f 100644 --- a/tools/walletextension/common/types.go +++ b/tools/walletextension/common/types.go @@ -3,6 +3,7 @@ package common type AccountDB struct { AccountAddress []byte Signature []byte + SignatureType int } type UserDB struct { diff --git a/tools/walletextension/container/walletextension_container.go b/tools/walletextension/container/walletextension_container.go index d964a23192..1dccaab400 100644 --- a/tools/walletextension/container/walletextension_container.go +++ b/tools/walletextension/container/walletextension_container.go @@ -8,6 +8,8 @@ import ( "net/http" "os" + "github.com/ten-protocol/go-ten/go/common/viewingkey" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -85,7 +87,7 @@ func NewWalletExtensionContainerFromConfig(config config.Config, logger gethlog. os.Exit(1) } for _, account := range accounts { - encClient, err := wecommon.CreateEncClient(hostRPCBindAddrWS, account.AccountAddress, user.PrivateKey, account.Signature, logger) + encClient, err := wecommon.CreateEncClient(hostRPCBindAddrWS, account.AccountAddress, user.PrivateKey, account.Signature, viewingkey.SignatureType(account.SignatureType), logger) if err != nil { logger.Error(fmt.Errorf("error creating new client, %w", err).Error()) os.Exit(1) diff --git a/tools/walletextension/lib/client_lib.go b/tools/walletextension/lib/client_lib.go index 70d14a13ae..04accae2e4 100644 --- a/tools/walletextension/lib/client_lib.go +++ b/tools/walletextension/lib/client_lib.go @@ -9,6 +9,8 @@ import ( "net/http" "strings" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ten-protocol/go-ten/integration" gethcommon "github.com/ethereum/go-ethereum/common" @@ -93,6 +95,49 @@ func (o *TGLib) RegisterAccount(pk *ecdsa.PrivateKey, addr gethcommon.Address) e return nil } +func (o *TGLib) RegisterAccountPersonalSign(pk *ecdsa.PrivateKey, addr gethcommon.Address) error { + // create the registration message + personalSignMessage := viewingkey.GeneratePersonalSignMessage(string(o.userID), integration.TenChainID, 1) + messageHash := accounts.TextHash([]byte(personalSignMessage)) + + sig, err := crypto.Sign(messageHash, pk) + if err != nil { + return fmt.Errorf("failed to sign message: %w", err) + } + sig[64] += 27 + signature := "0x" + hex.EncodeToString(sig) + payload := fmt.Sprintf("{\"signature\": \"%s\", \"address\": \"%s\", \"type\": \"%s\"}", signature, addr.Hex(), "Personal") + + // issue the registration message + req, err := http.NewRequestWithContext( + context.Background(), + http.MethodPost, + o.httpURL+"/v1/authenticate/?token="+string(o.userID), + strings.NewReader(payload), + ) + if err != nil { + return fmt.Errorf("unable to create request - %w", err) + } + + req.Header.Set("Content-Type", "application/json; charset=UTF-8") + + client := &http.Client{} + response, err := client.Do(req) + if err != nil { + return fmt.Errorf("unable to issue request - %w", err) + } + + defer response.Body.Close() + r, err := io.ReadAll(response.Body) + if err != nil { + return fmt.Errorf("unable to read response - %w", err) + } + if string(r) != "success" { + return fmt.Errorf("expected success, got %s", string(r)) + } + return nil +} + func (o *TGLib) HTTP() string { return fmt.Sprintf("%s/v1/?token=%s", o.httpURL, o.userID) } diff --git a/tools/walletextension/storage/database/mariadb/003_add_signature_type.sql b/tools/walletextension/storage/database/mariadb/003_add_signature_type.sql new file mode 100644 index 0000000000..f99247c7a6 --- /dev/null +++ b/tools/walletextension/storage/database/mariadb/003_add_signature_type.sql @@ -0,0 +1,2 @@ +ALTER TABLE ogdb.accounts +ADD COLUMN signature_type INT DEFAULT 0; \ No newline at end of file diff --git a/tools/walletextension/storage/database/mariadb/mariadb.go b/tools/walletextension/storage/database/mariadb/mariadb.go index 23030f168f..651c958745 100644 --- a/tools/walletextension/storage/database/mariadb/mariadb.go +++ b/tools/walletextension/storage/database/mariadb/mariadb.go @@ -7,6 +7,8 @@ import ( "path/filepath" "runtime" + "github.com/ten-protocol/go-ten/go/common/viewingkey" + "github.com/ethereum/go-ethereum/crypto" _ "github.com/go-sql-driver/mysql" // Importing MariaDB driver @@ -85,14 +87,14 @@ func (m *MariaDB) GetUserPrivateKey(userID []byte) ([]byte, error) { return privateKey, nil } -func (m *MariaDB) AddAccount(userID []byte, accountAddress []byte, signature []byte) error { - stmt, err := m.db.Prepare("INSERT INTO accounts(user_id, account_address, signature) VALUES (?, ?, ?)") +func (m *MariaDB) AddAccount(userID []byte, accountAddress []byte, signature []byte, signatureType viewingkey.SignatureType) error { + stmt, err := m.db.Prepare("INSERT INTO accounts(user_id, account_address, signature, signature_type) VALUES (?, ?, ?, ?)") if err != nil { return err } defer stmt.Close() - _, err = stmt.Exec(userID, accountAddress, signature) + _, err = stmt.Exec(userID, accountAddress, signature, int(signatureType)) if err != nil { return err } @@ -101,7 +103,7 @@ func (m *MariaDB) AddAccount(userID []byte, accountAddress []byte, signature []b } func (m *MariaDB) GetAccounts(userID []byte) ([]common.AccountDB, error) { - rows, err := m.db.Query("SELECT account_address, signature FROM accounts WHERE user_id = ?", userID) + rows, err := m.db.Query("SELECT account_address, signature, signature_type FROM accounts WHERE user_id = ?", userID) if err != nil { return nil, err } @@ -110,7 +112,7 @@ func (m *MariaDB) GetAccounts(userID []byte) ([]common.AccountDB, error) { var accounts []common.AccountDB for rows.Next() { var account common.AccountDB - if err := rows.Scan(&account.AccountAddress, &account.Signature); err != nil { + if err := rows.Scan(&account.AccountAddress, &account.Signature, &account.SignatureType); err != nil { return nil, err } accounts = append(accounts, account) diff --git a/tools/walletextension/storage/database/sqlite/sqlite.go b/tools/walletextension/storage/database/sqlite/sqlite.go index e1ee97d3fb..8de29603f1 100644 --- a/tools/walletextension/storage/database/sqlite/sqlite.go +++ b/tools/walletextension/storage/database/sqlite/sqlite.go @@ -7,6 +7,8 @@ import ( "os" "path/filepath" + "github.com/ten-protocol/go-ten/go/common/viewingkey" + "github.com/ethereum/go-ethereum/crypto" _ "github.com/mattn/go-sqlite3" // sqlite driver for sql.Open() @@ -54,6 +56,7 @@ func NewSqliteDatabase(dbPath string) (*Database, error) { user_id binary(20), account_address binary(20), signature binary(65), + signature_type int, FOREIGN KEY(user_id) REFERENCES users(user_id) ON DELETE CASCADE );`) @@ -121,14 +124,14 @@ func (s *Database) GetUserPrivateKey(userID []byte) ([]byte, error) { return privateKey, nil } -func (s *Database) AddAccount(userID []byte, accountAddress []byte, signature []byte) error { - stmt, err := s.db.Prepare("INSERT INTO accounts(user_id, account_address, signature) VALUES (?, ?, ?)") +func (s *Database) AddAccount(userID []byte, accountAddress []byte, signature []byte, signatureType viewingkey.SignatureType) error { + stmt, err := s.db.Prepare("INSERT INTO accounts(user_id, account_address, signature, signature_type) VALUES (?, ?, ?, ?)") if err != nil { return err } defer stmt.Close() - _, err = stmt.Exec(userID, accountAddress, signature) + _, err = stmt.Exec(userID, accountAddress, signature, int(signatureType)) if err != nil { return err } @@ -137,7 +140,7 @@ func (s *Database) AddAccount(userID []byte, accountAddress []byte, signature [] } func (s *Database) GetAccounts(userID []byte) ([]common.AccountDB, error) { - rows, err := s.db.Query("SELECT account_address, signature FROM accounts WHERE user_id = ?", userID) + rows, err := s.db.Query("SELECT account_address, signature, signature_type FROM accounts WHERE user_id = ?", userID) if err != nil { return nil, err } @@ -146,7 +149,7 @@ func (s *Database) GetAccounts(userID []byte) ([]common.AccountDB, error) { var accounts []common.AccountDB for rows.Next() { var account common.AccountDB - if err := rows.Scan(&account.AccountAddress, &account.Signature); err != nil { + if err := rows.Scan(&account.AccountAddress, &account.Signature, &account.SignatureType); err != nil { return nil, err } accounts = append(accounts, account) diff --git a/tools/walletextension/storage/storage.go b/tools/walletextension/storage/storage.go index 5cbc969ae1..78efcd1a39 100644 --- a/tools/walletextension/storage/storage.go +++ b/tools/walletextension/storage/storage.go @@ -3,6 +3,8 @@ package storage import ( "fmt" + "github.com/ten-protocol/go-ten/go/common/viewingkey" + "github.com/ten-protocol/go-ten/tools/walletextension/storage/database/mariadb" "github.com/ten-protocol/go-ten/tools/walletextension/storage/database/sqlite" @@ -13,7 +15,7 @@ type Storage interface { AddUser(userID []byte, privateKey []byte) error DeleteUser(userID []byte) error GetUserPrivateKey(userID []byte) ([]byte, error) - AddAccount(userID []byte, accountAddress []byte, signature []byte) error + AddAccount(userID []byte, accountAddress []byte, signature []byte, signatureType viewingkey.SignatureType) error GetAccounts(userID []byte) ([]common.AccountDB, error) GetAllUsers() ([]common.UserDB, error) StoreTransaction(rawTx string, userID []byte) error diff --git a/tools/walletextension/storage/storage_test.go b/tools/walletextension/storage/storage_test.go index fc71dd41fd..4bdc6e1cee 100644 --- a/tools/walletextension/storage/storage_test.go +++ b/tools/walletextension/storage/storage_test.go @@ -5,6 +5,8 @@ import ( "errors" "testing" + "github.com/ten-protocol/go-ten/go/common/viewingkey" + "github.com/stretchr/testify/require" "github.com/ten-protocol/go-ten/go/common/errutil" ) @@ -59,7 +61,7 @@ func testAddAndGetAccounts(storage Storage, t *testing.T) { t.Fatal(err) } - err = storage.AddAccount(userID, accountAddress1, signature1) + err = storage.AddAccount(userID, accountAddress1, signature1, viewingkey.EIP712Signature) if err != nil { t.Fatal(err) } @@ -67,7 +69,7 @@ func testAddAndGetAccounts(storage Storage, t *testing.T) { accountAddress2 := []byte("accountAddress2") signature2 := []byte("signature2") - err = storage.AddAccount(userID, accountAddress2, signature2) + err = storage.AddAccount(userID, accountAddress2, signature2, viewingkey.EIP712Signature) if err != nil { t.Fatal(err) } diff --git a/tools/walletextension/test/apis.go b/tools/walletextension/test/apis.go index 4bd349c50a..8d0a0a5bb4 100644 --- a/tools/walletextension/test/apis.go +++ b/tools/walletextension/test/apis.go @@ -175,9 +175,9 @@ func (api *DummyAPI) reEncryptParams(encryptedParams []byte) (*responses.Enclave } encryptor, err := vkhandler.VerifyViewingKey(&viewingkey.RPCSignedViewingKey{ - Account: api.address, PublicKey: api.viewingKey, SignatureWithAccountKey: api.signature, + SignatureType: viewingkey.Legacy, // todo - is this correct }, l2ChainIDDecimal) if err != nil { return nil, fmt.Errorf("unable to create vk encryption for request - %w", err) diff --git a/tools/walletextension/useraccountmanager/user_account_manager.go b/tools/walletextension/useraccountmanager/user_account_manager.go index 9af05a8779..664c2cd994 100644 --- a/tools/walletextension/useraccountmanager/user_account_manager.go +++ b/tools/walletextension/useraccountmanager/user_account_manager.go @@ -5,6 +5,8 @@ import ( "fmt" "sync" + "github.com/ten-protocol/go-ten/go/common/viewingkey" + "github.com/ethereum/go-ethereum/common" gethlog "github.com/ethereum/go-ethereum/log" "github.com/ten-protocol/go-ten/go/rpc" @@ -96,7 +98,7 @@ func (m *UserAccountManager) GetUserAccountManager(userID string) (*accountmanag } // create a new client - encClient, err := wecommon.CreateEncClient(m.hostRPCBinAddrWS, account.AccountAddress, userPrivateKey, account.Signature, m.logger) + encClient, err := wecommon.CreateEncClient(m.hostRPCBinAddrWS, account.AccountAddress, userPrivateKey, account.Signature, viewingkey.SignatureType(account.SignatureType), m.logger) if err != nil { m.logger.Error(fmt.Errorf("error creating new client, %w", err).Error()) } diff --git a/tools/walletextension/wallet_extension.go b/tools/walletextension/wallet_extension.go index e1ccc1fc34..5fcc3d6b32 100644 --- a/tools/walletextension/wallet_extension.go +++ b/tools/walletextension/wallet_extension.go @@ -209,6 +209,7 @@ func (w *WalletExtension) GenerateViewingKey(addr gethcommon.Address) (string, e PrivateKey: viewingPrivateKeyEcies, PublicKey: viewingPublicKeyBytes, SignatureWithAccountKey: nil, // we await a signature from the user before we can set up the EncRPCClient + SignatureType: viewingkey.Legacy, } // compress the viewing key and convert it to hex string ( this is what Metamask signs) @@ -247,7 +248,7 @@ func (w *WalletExtension) SubmitViewingKey(address gethcommon.Address, signature defaultAccountManager.AddClient(address, client) - err = w.storage.AddAccount([]byte(common.DefaultUser), vk.Account.Bytes(), vk.SignatureWithAccountKey) + err = w.storage.AddAccount([]byte(common.DefaultUser), vk.Account.Bytes(), vk.SignatureWithAccountKey, viewingkey.Legacy) if err != nil { return fmt.Errorf("error saving account %s for user %s", vk.Account.Hex(), common.DefaultUser) } @@ -291,26 +292,22 @@ func (w *WalletExtension) GenerateAndStoreNewUser() (string, error) { } // AddAddressToUser checks if a message is in correct format and if signature is valid. If all checks pass we save address and signature against userID -func (w *WalletExtension) AddAddressToUser(hexUserID string, address string, signature []byte) error { +func (w *WalletExtension) AddAddressToUser(hexUserID string, address string, signature []byte, signatureType viewingkey.SignatureType) error { requestStartTime := time.Now() addressFromMessage := gethcommon.HexToAddress(address) // check if a message was signed by the correct address and if the signature is valid - sigAddrs, err := viewingkey.CheckEIP712Signature(hexUserID, signature, int64(w.config.TenChainID)) + _, err := viewingkey.CheckSignature(hexUserID, signature, int64(w.config.TenChainID), signatureType) if err != nil { return fmt.Errorf("signature is not valid: %w", err) } - if sigAddrs.Hex() != address { - return fmt.Errorf("signature is not valid. Signature address %s!=%s ", sigAddrs, address) - } - // register the account for that viewing key userIDBytes, err := common.GetUserIDbyte(hexUserID) if err != nil { w.Logger().Error(fmt.Errorf("error decoding string (%s), %w", hexUserID[2:], err).Error()) return errors.New("error decoding userID. It should be in hex format") } - err = w.storage.AddAccount(userIDBytes, addressFromMessage.Bytes(), signature) + err = w.storage.AddAccount(userIDBytes, addressFromMessage.Bytes(), signature, signatureType) if err != nil { w.Logger().Error(fmt.Errorf("error while storing account (%s) for user (%s): %w", addressFromMessage.Hex(), hexUserID, err).Error()) return err @@ -324,7 +321,7 @@ func (w *WalletExtension) AddAddressToUser(hexUserID string, address string, sig accManager := w.userAccountManager.AddAndReturnAccountManager(hexUserID) - encClient, err := common.CreateEncClient(w.hostAddrHTTP, addressFromMessage.Bytes(), privateKeyBytes, signature, w.Logger()) + encClient, err := common.CreateEncClient(w.hostAddrHTTP, addressFromMessage.Bytes(), privateKeyBytes, signature, signatureType, w.Logger()) if err != nil { w.Logger().Error(fmt.Errorf("error creating encrypted client for user: (%s), %w", hexUserID, err).Error()) return fmt.Errorf("error creating encrypted client for user: (%s), %w", hexUserID, err)