Skip to content

Commit

Permalink
fixed eth sign
Browse files Browse the repository at this point in the history
  • Loading branch information
dan13ram committed Jul 3, 2024
1 parent 5e33e5b commit 8432b51
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 10 deletions.
48 changes: 45 additions & 3 deletions common/gcp_kms_signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type GCPKeyManagementClient interface {
type GcpKmsSigner struct {
client GCPKeyManagementClient
keyName string
publicKeyBytes []byte
ethAddress common.Address
cosmosPubKey types.PubKey
secp256k1PubKey *dcrecSecp256k1.PublicKey
Expand Down Expand Up @@ -77,8 +78,17 @@ func NewGcpKmsSigner(keyName string) (Signer, error) {
return nil, fmt.Errorf("failed to resolve public key: %w", err)
}

ethPublicKey, err := crypto.UnmarshalPubkey(pubKeyBytes)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal public key: %w", err)
}

ethAddress := getEthAddr(pubKeyBytes)

if ethAddress != crypto.PubkeyToAddress(*ethPublicKey) {
return nil, fmt.Errorf("ethereum address mismatch")
}

secp256k1PubKey, err := getSecp256k1PubKey(pubKeyBytes)
if err != nil {
return nil, fmt.Errorf("failed to get secp256k1 public key: %w", err)
Expand Down Expand Up @@ -207,6 +217,7 @@ func ethSignHash(hash common.Hash, client GCPKeyManagementClient, keyName string

// Brute force try includes KMS verification
var recoverErr error
var finalSig []byte
for recoveryID := byte(0); recoveryID < 2; recoveryID++ {
sig[0] = recoveryID + 27 // BitCoin header
btcsig := sig[:65] // Exclude Ethereum 'v' parameter
Expand All @@ -219,11 +230,41 @@ func ethSignHash(hash common.Hash, client GCPKeyManagementClient, keyName string
if getEthAddr(pubKey.SerializeUncompressed()) == ethAddress {
// Sign the transaction
sig[65] = recoveryID // Ethereum 'v' parameter
return sig[1:], nil // Exclude BitCoin header

finalSig = sig[1:] // Exclude BitCoin header
break

}
}
// RecoverErr can be nil, but that's OK
return nil, fmt.Errorf("asymmetric signature address recovery mis: %w", recoverErr)

if recoverErr != nil {
return nil, fmt.Errorf("asymmetric signature address recovery failed: %w", recoverErr)
}

if finalSig == nil {
return nil, fmt.Errorf("signature address mismatch")
}

recoveredPubKey, err := crypto.Ecrecover(hash[:], finalSig)
if err != nil {
return nil, fmt.Errorf("failed to recover public key: %w", err)
}

recoveredPubKeyECDSA, err := crypto.UnmarshalPubkey(recoveredPubKey)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal recoverred public key: %w", err)
}

recoveredAddr := crypto.PubkeyToAddress(*recoveredPubKeyECDSA)
if recoveredAddr != ethAddress {
return nil, fmt.Errorf("recovered address mismatch")
}

if finalSig[64] < 4 {
finalSig[64] += 27
}

return finalSig, nil
}

func cosmosSignHash(client GCPKeyManagementClient, keyName string, hash [32]byte, pubKey *dcrecSecp256k1.PublicKey) ([]byte, error) {
Expand Down Expand Up @@ -322,4 +363,5 @@ func resolveKeyVersionDetails(client GCPKeyManagementClient, keyName string) (*k
}

return resp, nil

}
20 changes: 13 additions & 7 deletions common/gcp_kms_signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,20 @@ func (m *MockGCPKeyManagementClient) GetCryptoKeyVersion(ctx context.Context, re
return args.Get(0).(*kmspb.CryptoKeyVersion), args.Error(1)
}

func mockASN1Signature() []byte {
r, _ := new(big.Int).SetString("0adb0cad4842abd2003c8dcf4f2663b1ba9106b208a8b9f62aaa628121d7e818", 16)
s, _ := new(big.Int).SetString("05a2e4ace4f4dae5437804d8ff3a67151e96d0efad0427cb49844ea80c3a03a5", 16)
func mockEthASN1Signature() []byte {
r, _ := new(big.Int).SetString("81318ab2232fbc4fd547d968ff554e9bd791543a1785fe075338693d946cb6ec", 16)
s, _ := new(big.Int).SetString("3c7829539dc8fd5e3b6e4dc9b3d6c5c9628bcb72d2639df18e6078af0273cf98", 16)
return asn1Bytes(r, s)
}

func mockCosmosASN1Signature() []byte {
r, _ := new(big.Int).SetString("5f7833a1432cb88825ba1d4ebd79cfcbe9693c08ab47ca42b596a0938c1dbe05", 16)
s, _ := new(big.Int).SetString("4826a12d3b9406b21754f395cb40955477ac4ae77c51be1659fdcc6657bb5900", 16)
return asn1Bytes(r, s)
}

func mockPublicKey() []byte {
keyHex := "0459fe4b6a8682418cb86df571c0a36b06f1b37e6760985009599c31d783c6ccac6cb07ba459e7d4949d12b178f8468802ebf7d932007e46b02fc7a2bf90761fd6"
keyHex := "0466673eea9ed9e7c2e838e566cc3424505d1b07be6a415c5e62cb56e69f9543da0104d2c81e9f7512687f11d65b714d852139680ff08923b4d9696f2960271f15"
return common.Hex2Bytes(keyHex)
}

Expand Down Expand Up @@ -88,7 +94,7 @@ func TestNewGcpKmsSigner(t *testing.T) {
func TestGcpKmsSigner_EthSign(t *testing.T) {
mockClient := new(MockGCPKeyManagementClient)
keyName := "test-key"
ethAddress := common.HexToAddress("0xE14FE42D9Cf3C39c27E1c1Ca3dAa033C43eD4d88")
ethAddress := common.HexToAddress("0x14BFf3BDb55E171Dc5af4B0F6F779752bC146C6E")

signer := &GcpKmsSigner{
client: mockClient,
Expand All @@ -99,7 +105,7 @@ func TestGcpKmsSigner_EthSign(t *testing.T) {
data := []byte("example transaction data")
// expectedHash := crypto.Keccak256(data)
expectedSignature := &kmspb.AsymmetricSignResponse{
Signature: mockASN1Signature(),
Signature: mockEthASN1Signature(),
}
mockClient.On("AsymmetricSign", mock.Anything, mock.Anything, mock.Anything).Return(expectedSignature, nil)

Expand Down Expand Up @@ -128,7 +134,7 @@ func TestGcpKmsSigner_CosmosSign(t *testing.T) {
data := []byte("example transaction data")
// expectedHash := crypto.Keccak256(data)
expectedSignature := &kmspb.AsymmetricSignResponse{
Signature: mockASN1Signature(),
Signature: mockCosmosASN1Signature(),
}
mockClient.On("AsymmetricSign", mock.Anything, mock.Anything, mock.Anything).Return(expectedSignature, nil)

Expand Down

0 comments on commit 8432b51

Please sign in to comment.