获取助记词的地址和私钥

Getting Address and Private Key for Mnemonic

提问人:Gervasius Twinklewinkleson 提问时间:11/13/2023 最后编辑:Jonathan HallGervasius Twinklewinkleson 更新时间:11/14/2023 访问量:72

问:

我基本上是在尝试通过使用 Golang 从以太坊帐户的助记词中派生路径来获取公钥和私钥。我有这个:

package generator

import (
    "fmt"

    "github.com/tyler-smith/go-bip32"
    "github.com/tyler-smith/go-bip39"
)

type HDWallet struct{}

const BIP_PATH = "m/44'/60'/0'/0/0"

func (wallet *HDWallet) GenerateAddressAndPrivateKey(seedPhrase string) (string, string, error) {
    seed, err := bip39.NewSeedWithErrorChecking(seedPhrase, "")
    if err != nil {
        return "", "", err
    }

    masterKey, err := bip32.NewMasterKey(seed)
    if err != nil {
        return "", "", err
    }

    publicKey := masterKey.PublicKey()
    if err != nil {
        return "", "", err
    }

    return ???, ???, nil
}

我有主密钥,但如何获取派生帐户(公钥和私钥)?

以太坊 以太坊 去以太坊

评论


答:

1赞 norym 11/13/2023 #1

为了检索公钥和私钥作为其已知的十六进制字符串(帐户密钥),您需要将生成的主私钥和公钥转换为 ECDSA 十六进制字符串,如下所示。顺便说一句,通常你不会使用主私钥和公钥。

package main

import (
    "crypto/ecdsa"
    "encoding/hex"
    "fmt"

    "github.com/ethereum/go-ethereum/crypto"
    "github.com/tyler-smith/go-bip32"
    "github.com/tyler-smith/go-bip39"
)

func main() {
    // Generate a mnemonic
    entropy, _ := bip39.NewEntropy(256)
    mnemonic, _ := bip39.NewMnemonic(entropy)
    fmt.Println("Mnemonic (gen): ", mnemonic)

    // Generate a Bip32 HD wallet for the mnemonic and a user supplied passphrase
    seed := bip39.NewSeed(mnemonic, "Secret Passphrase")

    masterPrivateKey, _ := bip32.NewMasterKey(seed)
    masterPublicKey := masterPrivateKey.PublicKey()
    fmt.Println("Master private key (gen): ", masterPrivateKey)
    fmt.Println("Master public key (gen): ", masterPublicKey)

    // Use Unsafe to suppress error, otherwise use crypto.ToECDSA
    ecdaPrivateKey := crypto.ToECDSAUnsafe(masterPrivateKey.Key)
    ecdaPublicKey := ecdaPrivateKey.Public().(*ecdsa.PublicKey)
    fmt.Println("ECDA Private key: ", ecdaPrivateKey.D)
    fmt.Println("ECDA Public key: ", ecdaPublicKey.X)

    privateKeyHex := fmt.Sprintf("%x", ecdaPrivateKey.D)
    publicKeyHex := fmt.Sprintf("%x", crypto.CompressPubkey(ecdaPublicKey)) // Encode a public key to the 33-byte compressed format
    fmt.Println("Private key (hex):", privateKeyHex)
    fmt.Println("Public key (hex):", publicKeyHex)
}

您可以按如下方式检查生成的十六进制字符串生成的公钥是否属于私钥十六进制字符串。

    // Decode the private key and public key from hex strings
    privateKey, err := crypto.HexToECDSA(privateKeyHex)
    if err != nil {
        fmt.Println("Invalid private key:", err)
        return
    }

    publicKeyBytes, err := hex.DecodeString(publicKeyHex)
    if err != nil {
        fmt.Println("Invalid public key:", err)
        return
    }

    // Use crypto.DecompressPubkey to decode the public key bytes
    givenPublicKey, err := crypto.DecompressPubkey(publicKeyBytes)
    if err != nil {
        fmt.Println("Invalid public key:", err)
        return
    }

    // Derive the public key from the private key
    derivedPublicKey := privateKey.Public().(*ecdsa.PublicKey)

    // Compare the derived public key with the given public key
    if derivedPublicKey.X.Cmp(givenPublicKey.X) == 0 && derivedPublicKey.Y.Cmp(givenPublicKey.Y) == 0 {
        fmt.Println("The private key matches the public key.")
    } else {
        fmt.Println("The private key does not match the public key.")
    }

--编辑--

不能保证,但请尝试这种方法。

    // BIP44 derivation path format: m / purpose' / coin_type' / account' / change / address_index
    // Example: m/44'/0'/0'/0/0
    purposeKey, _ := masterKey.NewChildKey(bip32.FirstHardenedChild + 44)
    coinTypeKey, _ := purposeKey.NewChildKey(bip32.FirstHardenedChild)
    accountKey, _ := coinTypeKey.NewChildKey(bip32.FirstHardenedChild)
    changeKey, _ := accountKey.NewChildKey(0)
    addressKey, _ := changeKey.NewChildKey(0)

评论

0赞 Gervasius Twinklewinkleson 11/14/2023
谢谢,这很有效。也许您也知道如何获取 m/44'/60'/0'/0/0 的密钥对?
1赞 norym 11/14/2023
看看我更新的答案。
0赞 Gervasius Twinklewinkleson 11/16/2023
不知何故,它没有给我预期的键六边形,但感谢您的帮助