diff --git a/crypto/secp256k1/secp256.go b/crypto/secp256k1/secp256.go index 35d0eef34a..e54bf9a755 100644 --- a/crypto/secp256k1/secp256.go +++ b/crypto/secp256k1/secp256.go @@ -16,6 +16,7 @@ package secp256k1 #define NDEBUG #include "./libsecp256k1/src/secp256k1.c" #include "./libsecp256k1/src/modules/recovery/main_impl.h" +#include "./libsecp256k1/src/modules/ecdh/main_impl.h" #include "ext.h" typedef void (*callbackFunc) (const char* msg, void* data); @@ -86,6 +87,22 @@ func Sign(msg []byte, seckey []byte) ([]byte, error) { return sig, nil } +// SharedSecret computes the hashed ECDH shared secret. +// pubkey must be an EC public key +// seckey must be an EC private key +func SharedSecret(pubkey []byte, seckey []byte) ([]byte, error) { + if len(seckey) != 32 { + return nil, ErrInvalidKey + } + seckeydata := (*C.uchar)(unsafe.Pointer(&seckey[0])) + pubkeydata := (*C.uchar)(unsafe.Pointer(&pubkey[0])) + result := make([]byte, 32) + if C.secp256k1_ecdh(context, &result, pubkeydata, seckeydata) != 1 { + return nil, ErrInvalidKey + } + return result, nil +} + // RecoverPubkey returns the public key of the signer. // msg must be the 32-byte hash of the message to be signed. // sig must be a 65-byte compact ECDSA signature containing the diff --git a/signer/core/api.go b/signer/core/api.go index f76a34e877..b92ae6195e 100644 --- a/signer/core/api.go +++ b/signer/core/api.go @@ -142,7 +142,7 @@ type ( } // SharedSecretRequest contains info about the other key SharedSecretRequest struct { - Address common.MixedcaseAddress `json:"address"` + Address common.MixedcaseAddress `json:"address"` } // SharedSecretResponse result from SharedSecretRequest SharedSecretResponse struct { @@ -443,6 +443,34 @@ func (api *SignerAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (c return crypto.PubkeyToAddress(*rpk), nil } +// SharedSecret returns the shared ECDH secret, salted and hashed. +// TODO: Documentation in the Wiki +func (api *SignerAPI) SharedSecret(ctx context.Context, otherKey, salt hexutil.Bytes) (hexutil.Bytes, error) { + // Get the other public key + otherPubKey, err := crypto.UnmarshalPubkey(otherKey) + if err != nil { + return nil, err + } + addr := crypto.PubkeyToAddress(otherPubKey) + // We make the request prior to looking up if we actually have the account, to prevent + // account-enumeration via the API + req := &SharedSecretRequest{Address: addr} + res, err := api.UI.ApproveSharedSecret(req) + + if err != nil { + return nil, err + } + if !res.Approved { + return nil, ErrRequestDenied + } + // Look up the wallet containing the requested signer + account := accounts.Account{Address: addr.Address()} + wallet, err := api.am.Find(account) + if err != nil { + return nil, err + } +} + // SignHash is a helper function that calculates a hash for the given message that can be // safely used to calculate a signature from. // @@ -500,4 +528,3 @@ func (api *SignerAPI) Import(ctx context.Context, keyJSON json.RawMessage) (Acco } return Account{Typ: "Account", URL: acc.URL, Address: acc.Address}, nil } -