github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/app/crypto/ethkeystore/keystore.go (about) 1 package ethkeystore 2 3 import ( 4 "crypto/ecdsa" 5 "encoding/hex" 6 "fmt" 7 "github.com/fibonacci-chain/fbc/app/crypto/hd" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "time" 12 13 "github.com/ethereum/go-ethereum/accounts/keystore" 14 "github.com/ethereum/go-ethereum/common" 15 ethcrypto "github.com/ethereum/go-ethereum/crypto" 16 "github.com/fibonacci-chain/fbc/app/crypto/ethsecp256k1" 17 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/crypto/keys" 18 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/crypto/keys/mintkey" 19 tmcrypto "github.com/fibonacci-chain/fbc/libs/tendermint/crypto" 20 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/secp256k1" 21 "github.com/google/uuid" 22 ) 23 24 // EncodeTmKeyToEthKey transfer tendermint key to a ethereum key 25 func EncodeECDSAKeyToTmKey(privateKeyECDSA *ecdsa.PrivateKey, keytype keys.SigningAlgo) (tmcrypto.PrivKey, error) { 26 // Converts key to Ethermint secp256 implementation 27 ethkey := ethcrypto.FromECDSA(privateKeyECDSA) 28 switch keytype { 29 case hd.EthSecp256k1: 30 key := ethsecp256k1.PrivKey(ethkey) 31 return &key, nil 32 case keys.Secp256k1: 33 secpPk := &secp256k1.PrivKeySecp256k1{} 34 copy(secpPk[:], ethkey) 35 return secpPk, nil 36 default: 37 return nil, fmt.Errorf("unknown private key type %s", keytype) 38 } 39 40 } 41 42 // ImportKeyStoreFile Export Key to keystore file 43 func ImportKeyStoreFile(decryptPassword, password, fileName string, keytype keys.SigningAlgo) (privKetArmor string, err error) { 44 filejson, err := ioutil.ReadFile(fileName) 45 if err != nil { 46 return "", err 47 } 48 49 var decrytKey *keystore.Key 50 decrytKey, err = keystore.DecryptKey(filejson, decryptPassword) 51 if err != nil { 52 decrytKey, err = DecryptKeyForWeb3(filejson, decryptPassword) 53 if err != nil { 54 return "", fmt.Errorf("failed to encrypt key: %s", err.Error()) 55 } 56 } 57 58 privkey, err := EncodeECDSAKeyToTmKey(decrytKey.PrivateKey, keytype) 59 60 armor := mintkey.EncryptArmorPrivKey(privkey, password, string(keytype)) 61 62 return armor, nil 63 } 64 65 // CreateKeystoreByTmKey create a eth keystore by accountname from keybase 66 func CreateKeystoreByTmKey(privKey tmcrypto.PrivKey, dir, encryptPassword string) (string, error) { 67 // dir must be absolute 68 if !filepath.IsAbs(dir) { 69 return "", fmt.Errorf("invalid directory") 70 } 71 // converts tendermint key to ethereum key 72 ethKey, err := EncodeTmKeyToEthKey(privKey) 73 if err != nil { 74 return "", fmt.Errorf("invalid private key type, must be Ethereum key: %T", privKey) 75 } 76 77 // export Key to keystore file 78 // if filename isn't set ,use default ethereum name 79 addr := common.BytesToAddress(privKey.PubKey().Address()) 80 fileName := filepath.Join(dir, keyFileName(addr)) 81 err = ExportKeyStoreFile(ethKey, encryptPassword, fileName) 82 return fileName, err 83 } 84 85 // EncodeTmKeyToEthKey transfer tendermint key to a ethereum key 86 func EncodeTmKeyToEthKey(privKey tmcrypto.PrivKey) (*ecdsa.PrivateKey, error) { 87 // Converts key to Ethermint secp256 implementation 88 emintKey, ok := privKey.(ethsecp256k1.PrivKey) 89 if !ok { 90 return nil, fmt.Errorf("invalid private key type, must be Ethereum key: %T", privKey) 91 } 92 93 return emintKey.ToECDSA(), nil 94 } 95 96 // ExportKeyStoreFile Export Key to keystore file 97 func ExportKeyStoreFile(privateKeyECDSA *ecdsa.PrivateKey, encryptPassword, fileName string) error { 98 //new keystore key 99 ethKey, err := newEthKeyFromECDSA(privateKeyECDSA) 100 if err != nil { 101 return err 102 } 103 // encrypt Key to get keystore file 104 content, err := keystore.EncryptKey(ethKey, encryptPassword, keystore.StandardScryptN, keystore.StandardScryptP) 105 if err != nil { 106 return fmt.Errorf("failed to encrypt key: %s", err.Error()) 107 } 108 109 // write to keystore file 110 err = ioutil.WriteFile(fileName, content, os.ModePerm) 111 if err != nil { 112 return fmt.Errorf("failed to write keystore: %s", err.Error()) 113 } 114 return nil 115 } 116 117 // newEthKeyFromECDSA new eth.keystore Key 118 func newEthKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) (*keystore.Key, error) { 119 id, err := uuid.NewRandom() 120 if err != nil { 121 return nil, fmt.Errorf("Could not create random uuid: %v", err) 122 } 123 key := &keystore.Key{ 124 Id: id, 125 Address: ethcrypto.PubkeyToAddress(privateKeyECDSA.PublicKey), 126 PrivateKey: privateKeyECDSA, 127 } 128 return key, nil 129 } 130 131 // keyFileName return the default keystore file name in the ethereum 132 func keyFileName(keyAddr common.Address) string { 133 ts := time.Now().UTC() 134 return fmt.Sprintf("UTC--%s--%s", toISO8601(ts), hex.EncodeToString(keyAddr[:])) 135 } 136 137 func toISO8601(t time.Time) string { 138 var tz string 139 name, offset := t.Zone() 140 if name == "UTC" { 141 tz = "Z" 142 } else { 143 tz = fmt.Sprintf("%03d00", offset/3600) 144 } 145 return fmt.Sprintf("%04d-%02d-%02dT%02d-%02d-%02d.%09d%s", 146 t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), tz) 147 }