New account
ECDSA 生成新的地址
要首先生成一个新的钱包,需要导入 go-ethereum crypto
包,该包提供用于生成随机私钥的 GenerateKey
方法
- 生成全新的私钥,并将私钥存储在本地文件
- 基于私钥导出公钥信息
- 基于公钥导出账户地址
package main
import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"log"
"strings"
)
func NewAccount() common.Address {
ecdsaPrivateKey, err := crypto.GenerateKey()
newAddress := EcdsaAddressFromPrivateKey(ecdsaPrivateKey)
}
func AddressFromKey(key string) common.Address {
if strings.HasPrefix(key, "0x") {
key = strings.Trim(key, "0x")
}
ecdsaPrivateKey, err := crypto.HexToECDSA(key)
if err != nil {
log.Fatal(err)
}
rAddress := EcdsaAddressFromPrivateKey(ecdsaPrivateKey)
return rAddress
}
func EcdsaAddressFromPrivateKey(ecdsaPrivateKey *ecdsa.PrivateKey) common.Address {
publicKeyBytes := crypto.FromECDSAPub(ecdsaPrivateKey.Public().(*ecdsa.PublicKey))
pub, err := crypto.UnmarshalPubkey(publicKeyBytes)
if err != nil {
log.Fatal(err)
}
rAddress := crypto.PubkeyToAddress(*pub)
return rAddress
}
生成助记词,从助记词导出新地址
地址胜场方式:
- 生成助记词
- 拼接助记词和
secret
, 构造哈希种子seed
- 基于
seed
逐步生成ecdsa
私钥 - 基于私钥导出钱包地址
导出账户密钥
- 基于助记词导出密钥时:
- 必须提供相匹配的
secret
值 - 拼接出生成账户用的哈希种子
seed
- 基于
seed
产生相同的私钥和地址 - 因此,
secret
用于进一步保证助记词的安全
func main() {
secret := "ert"
mnemonic, address := KeyFromMnemonic(secret)
fmt.Println(mnemonic, address)
KeyFromMnemonicInput(mnemonic, secret)
}
func KeyFromMnemonic(secret string) (string, common.Address) {
// Generate a mnemonic
entropy, _ := bip39.NewEntropy(256)
mnemonic, _ := bip39.NewMnemonic(entropy)
// Generate a Bip32 HD wallet for the mnemonic and a user supplied passphrase
seed := bip39.NewSeed(mnemonic, secret)
masterPrivateKey, _ := bip32.NewMasterKey(seed)
ecdsaPrivateKey := crypto.ToECDSAUnsafe(masterPrivateKey.Key)
address := EcdsaAddressFromPrivateKey(ecdsaPrivateKey)
return mnemonic, address
}
func KeyFromMnemonicInput(mnemonic, secret string) string {
seed := bip39.NewSeed(mnemonic, secret)
masterPrivateKey, _ := bip32.NewMasterKey(seed)
ecdsaPrivateKey := crypto.ToECDSAUnsafe(masterPrivateKey.Key)
privateKeyHex := fmt.Sprintf("%x", ecdsaPrivateKey.D)
address := EcdsaAddressFromPrivateKey(ecdsaPrivateKey)
fmt.Println(address)
return privateKeyHex
}
从Keystore导出地址
- 创建新的钱包地址,账户信息通过
secret
加密存储并导出keystore
文件 - 基于
secret
解密keystore
文件
私钥签名
keystore
直接基于secret
签名数据keystore
可以先基于 secretTimedUnlock
解锁一段时间后可以直接用于签名
import (
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"log"
"os"
)
func NewKeystoreAccount(secret string) common.Address {
ks := keystore.NewKeyStore("./wallets", keystore.StandardScryptN, keystore.StandardScryptP)
account, err := ks.NewAccount(secret)
if err != nil {
log.Fatal(err)
}
return account.Address
}
func AddressFromKeystore(file, secret string) common.Address {
ks := keystore.NewKeyStore("./tmp", keystore.StandardScryptN, keystore.StandardScryptP)
jsonBytes, err := os.ReadFile(file)
if err != nil {
log.Fatal(err)
}
account, err := ks.Import(jsonBytes, secret, secret)
if err != nil {
log.Fatal(err)
}
return account.Address
}
func SignatureFromKeystoreAfterUnlock(file, secret string) string {
ks := keystore.NewKeyStore("./tmp", keystore.StandardScryptN, keystore.StandardScryptP)
jsonBytes, err := os.ReadFile(file)
if err != nil {
checkError(errors.New(fmt.Sprintf("Error in reading keystore, error = %v", err)))
}
account, err := ks.Import(jsonBytes, secret, secret)
if err != nil {
checkError(errors.New(fmt.Sprintf("Error in exporting keystore account, error = %v", err)))
}
err = ks.Unlock(account, secret)
if err != nil {
checkError(errors.New(fmt.Sprintf("Error in unlocking keystore account, error = %v", err)))
}
signatureBytes, err := ks.SignHash(account, []byte("ww"))
return hexutil.Encode(signatureBytes)
}
func SignatureFromKeystore(file, secret string) string {
ks := keystore.NewKeyStore("./tmp", keystore.StandardScryptN, keystore.StandardScryptP)
jsonBytes, err := os.ReadFile(file)
if err != nil {
log.Fatal(err)
}
account, err := ks.Import(jsonBytes, secret, secret)
if err != nil {
log.Fatal(err)
}
signatureBytes, err := ks.SignHashWithPassphrase(account, secret, []byte("ww"))
return hexutil.Encode(signatureBytes)
}