Skip to content

Commit

Permalink
use go-ethereum ecies due to instability with ecies/go/v2 (#178)
Browse files Browse the repository at this point in the history
* use go-ethereum ecies due to instability with ecies/go/v2

* remove extra logging

* check ECIES key also in get leader cmd

* compile error

* tidy logic

* Handle feedback
  • Loading branch information
agouin authored Jul 19, 2023
1 parent d6b20b5 commit ac0a811
Show file tree
Hide file tree
Showing 16 changed files with 424 additions and 1,409 deletions.
30 changes: 22 additions & 8 deletions cmd/horcrux/cmd/leader_election.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,26 +107,40 @@ func getLeaderCmd() *cobra.Command {
return fmt.Errorf("threshold mode configuration has no cosigners")
}

keyFile, err := config.KeyFileExistsCosignerRSA()
if err != nil {
return err
}
var id int

key, err := signer.LoadCosignerRSAKey(keyFile)
keyFileECIES, err := config.KeyFileExistsCosignerECIES()
if err != nil {
return fmt.Errorf("error reading cosigner key (%s): %w", keyFile, err)
keyFileRSA, err := config.KeyFileExistsCosignerRSA()
if err != nil {
return fmt.Errorf("cosigner encryption keys not found (%s) - (%s): %w", keyFileECIES, keyFileRSA, err)
}

key, err := signer.LoadCosignerRSAKey(keyFileRSA)
if err != nil {
return fmt.Errorf("error reading cosigner key (%s): %w", keyFileRSA, err)
}

id = key.ID
} else {
key, err := signer.LoadCosignerECIESKey(keyFileECIES)
if err != nil {
return fmt.Errorf("error reading cosigner key (%s): %w", keyFileECIES, err)
}

id = key.ID
}

var p2pListen string

for _, c := range thresholdCfg.Cosigners {
if c.ShardID == key.ID {
if c.ShardID == id {
p2pListen = c.P2PAddr
}
}

if p2pListen == "" {
return fmt.Errorf("cosigner config does not exist for our shard ID %d", key.ID)
return fmt.Errorf("cosigner config does not exist for our shard ID %d", id)
}

retryOpts := []grpcretry.CallOption{
Expand Down
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/armon/go-metrics v0.4.1
github.com/cometbft/cometbft v0.37.2
github.com/cosmos/cosmos-sdk v0.47.3
github.com/ecies/go/v2 v2.0.6
github.com/ethereum/go-ethereum v1.12.0
github.com/gogo/protobuf v1.3.2
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/hashicorp/raft v1.5.0
Expand Down Expand Up @@ -52,15 +52,14 @@ require (
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ethereum/go-ethereum v1.11.5 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/golang/glog v1.1.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/gtank/merlin v0.1.1 // indirect
Expand All @@ -70,9 +69,11 @@ require (
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-msgpack v1.1.5 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-uuid v1.0.1 // indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hdevalence/ed25519consensus v0.1.0 // indirect
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/klauspost/compress v1.16.3 // indirect
Expand Down
736 changes: 6 additions & 730 deletions go.sum

Large diffs are not rendered by default.

111 changes: 111 additions & 0 deletions go.work.sum

Large diffs are not rendered by default.

26 changes: 2 additions & 24 deletions signer/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,18 +122,7 @@ func (c RuntimeConfig) CosignerSecurityECIES() (*CosignerSecurityECIES, error) {
return nil, fmt.Errorf("error reading cosigner key (%s): %w", keyFile, err)
}

pubKeys := make([]CosignerECIESPubKey, len(key.ECIESPubs))
for i, pk := range key.ECIESPubs {
pubKeys[i] = CosignerECIESPubKey{
ID: i + 1,
PublicKey: pk,
}
}

return NewCosignerSecurityECIES(
key,
pubKeys,
), nil
return NewCosignerSecurityECIES(key), nil
}

func (c RuntimeConfig) CosignerSecurityRSA() (*CosignerSecurityRSA, error) {
Expand All @@ -147,18 +136,7 @@ func (c RuntimeConfig) CosignerSecurityRSA() (*CosignerSecurityRSA, error) {
return nil, fmt.Errorf("error reading cosigner key (%s): %w", keyFile, err)
}

pubKeys := make([]CosignerRSAPubKey, len(key.RSAPubs))
for i, pk := range key.RSAPubs {
pubKeys[i] = CosignerRSAPubKey{
ID: i + 1,
PublicKey: *pk,
}
}

return NewCosignerSecurityRSA(
key,
pubKeys,
), nil
return NewCosignerSecurityRSA(key), nil
}

func (c RuntimeConfig) cachedKeyDirectory() string {
Expand Down
7 changes: 4 additions & 3 deletions signer/cosigner_key_shares.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (

cometjson "github.com/cometbft/cometbft/libs/json"
"github.com/cometbft/cometbft/privval"
ecies "github.com/ecies/go/v2"
"github.com/ethereum/go-ethereum/crypto/ecies"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
tsed25519 "gitlab.com/unit410/threshold-ed25519/pkg"
"golang.org/x/sync/errgroup"
)
Expand Down Expand Up @@ -137,12 +138,12 @@ func makeECIESKeys(num int) ([]*ecies.PrivateKey, []*ecies.PublicKey, error) {
for i := 0; i < num; i++ {
i := i
eg.Go(func() error {
eciesKey, err := ecies.GenerateKey()
eciesKey, err := ecies.GenerateKey(rand.Reader, secp256k1.S256(), nil)
if err != nil {
return err
}
eciesKeys[i] = eciesKey
pubKeys[i] = eciesKey.PublicKey
pubKeys[i] = &eciesKey.PublicKey
return nil
})
}
Expand Down
65 changes: 42 additions & 23 deletions signer/cosigner_security_ecies.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import (
"crypto/sha256"
"encoding/json"
"fmt"
"math/big"
"os"

cometjson "github.com/cometbft/cometbft/libs/json"
ecies "github.com/ecies/go/v2"
"github.com/ethereum/go-ethereum/crypto/ecies"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
"golang.org/x/sync/errgroup"
)

Expand Down Expand Up @@ -39,18 +41,22 @@ func (key *CosignerECIESKey) MarshalJSON() ([]byte, error) {
type Alias CosignerECIESKey

// marshal our private key and all public keys
privateBytes := key.ECIESKey
privateBytes := key.ECIESKey.D.Bytes()
pubKeysBytes := make([][]byte, len(key.ECIESPubs))
for i, pubKey := range key.ECIESPubs {
pubKeysBytes[i] = pubKey.Bytes(true)
pubBz := make([]byte, 65)
pubBz[0] = 0x04
copy(pubBz[1:33], pubKey.X.Bytes())
copy(pubBz[33:65], pubKey.Y.Bytes())
pubKeysBytes[i] = pubBz
}

return json.Marshal(&struct {
ECIESKey []byte `json:"eciesKey"`
ECIESPubs [][]byte `json:"eciesPubs"`
*Alias
}{
ECIESKey: privateBytes.Bytes(),
ECIESKey: privateBytes,
ECIESPubs: pubKeysBytes,
Alias: (*Alias)(key),
})
Expand All @@ -73,14 +79,21 @@ func (key *CosignerECIESKey) UnmarshalJSON(data []byte) error {
// unmarshal the public key bytes for each cosigner
key.ECIESPubs = make([]*ecies.PublicKey, len(aux.ECIESPubs))
for i, bytes := range aux.ECIESPubs {
pub, err := ecies.NewPublicKeyFromBytes(bytes)
if err != nil {
return err
pub := &ecies.PublicKey{
X: new(big.Int).SetBytes(bytes[1:33]),
Y: new(big.Int).SetBytes(bytes[33:]),
Curve: secp256k1.S256(),
Params: ecies.ECIES_AES128_SHA256,
}

key.ECIESPubs[i] = pub
}

key.ECIESKey = ecies.NewPrivateKeyFromBytes(aux.ECIESKey)
key.ECIESKey = &ecies.PrivateKey{
PublicKey: *key.ECIESPubs[aux.ID-1],
D: new(big.Int).SetBytes(aux.ECIESKey),
}

return nil
}

Expand All @@ -101,14 +114,17 @@ func LoadCosignerECIESKey(file string) (CosignerECIESKey, error) {
}

// NewCosignerSecurityECIES creates a new CosignerSecurityECIES.
func NewCosignerSecurityECIES(key CosignerECIESKey, eciesPubKeys []CosignerECIESPubKey) *CosignerSecurityECIES {
func NewCosignerSecurityECIES(key CosignerECIESKey) *CosignerSecurityECIES {
c := &CosignerSecurityECIES{
key: key,
eciesPubKeys: make(map[int]CosignerECIESPubKey, len(eciesPubKeys)),
eciesPubKeys: make(map[int]CosignerECIESPubKey, len(key.ECIESPubs)),
}

for _, pubKey := range eciesPubKeys {
c.eciesPubKeys[pubKey.ID] = pubKey
for i, pubKey := range key.ECIESPubs {
c.eciesPubKeys[i+1] = CosignerECIESPubKey{
ID: i + 1,
PublicKey: pubKey,
}
}

return c
Expand Down Expand Up @@ -136,12 +152,12 @@ func (c *CosignerSecurityECIES) EncryptAndSign(id int, noncePub []byte, nonceSha
var eg errgroup.Group

eg.Go(func() (err error) {
encryptedShare, err = ecies.Encrypt(pubKey.PublicKey, nonceShare)
encryptedShare, err = ecies.Encrypt(rand.Reader, pubKey.PublicKey, nonceShare, nil, nil)
return err
})

eg.Go(func() (err error) {
encryptedPub, err = ecies.Encrypt(pubKey.PublicKey, noncePub)
encryptedPub, err = ecies.Encrypt(rand.Reader, pubKey.PublicKey, noncePub, nil, nil)
return err
})

Expand All @@ -164,10 +180,7 @@ func (c *CosignerSecurityECIES) EncryptAndSign(id int, noncePub []byte, nonceSha
hash := sha256.Sum256(jsonBytes)
signature, err := ecdsa.SignASN1(
rand.Reader,
&ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey(*c.key.ECIESKey.PublicKey),
D: c.key.ECIESKey.D,
},
c.key.ECIESKey.ExportECDSA(),
hash[:],
)
if err != nil {
Expand Down Expand Up @@ -206,7 +219,7 @@ func (c *CosignerSecurityECIES) DecryptAndVerify(

digest := sha256.Sum256(digestBytes)

validSignature := ecdsa.VerifyASN1((*ecdsa.PublicKey)(pubKey.PublicKey), digest[:], signature)
validSignature := ecdsa.VerifyASN1(pubKey.PublicKey.ExportECDSA(), digest[:], signature)
if !validSignature {
return nil, nil, fmt.Errorf("signature is invalid")
}
Expand All @@ -217,13 +230,19 @@ func (c *CosignerSecurityECIES) DecryptAndVerify(
var nonceShare []byte

eg.Go(func() (err error) {
noncePub, err = ecies.Decrypt(c.key.ECIESKey, encryptedNoncePub)
return err
noncePub, err = c.key.ECIESKey.Decrypt(encryptedNoncePub, nil, nil)
if err != nil {
return fmt.Errorf("failed to decrypt nonce pub: %w", err)
}
return nil
})

eg.Go(func() (err error) {
nonceShare, err = ecies.Decrypt(c.key.ECIESKey, encryptedNonceShare)
return err
nonceShare, err = c.key.ECIESKey.Decrypt(encryptedNonceShare, nil, nil)
if err != nil {
return fmt.Errorf("failed to decrypt nonce share: %w", err)
}
return nil
})

if err := eg.Wait(); err != nil {
Expand Down
Loading

0 comments on commit ac0a811

Please sign in to comment.