Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove legacy signature type #1851

Merged
merged 3 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 22 additions & 29 deletions go/common/viewingkey/viewing_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think wallet has a chainID field on it, might be better to use that rather than hardcoding if poss. In case we end up with different chainIDs on diff Ten networks eventually.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, fixed 👍

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)
}
Expand All @@ -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
}
9 changes: 0 additions & 9 deletions go/common/viewingkey/viewing_key_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
)

Expand Down Expand Up @@ -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.
Expand Down
19 changes: 0 additions & 19 deletions go/common/viewingkey/viewing_key_signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 0 additions & 6 deletions go/enclave/vkhandler/vk_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 0 additions & 2 deletions tools/walletextension/common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ const (
PathRoot = "/"
PathReady = "/ready/"
PathViewingKeys = "/viewingkeys/"
PathGenerateViewingKey = "/generateviewingkey/"
PathSubmitViewingKey = "/submitviewingkey/"
PathJoin = "/join/"
PathGetMessage = "/getmessage/"
PathAuthenticate = "/authenticate/"
Expand Down
Loading