英文:
panic: gob: type elliptic.p256Curve has no exported fields
问题
我正在尝试构建一个区块链项目,但在处理gob序列化时遇到了问题。我有一个使用elliptic.P256()曲线结构的Wallet结构体,当我尝试对Wallet进行序列化时,出现了一个没有导出字段的错误。
真的希望能得到一些帮助。
以下是我的代码。
const walletFile = "Wallets.dat"
type Wallets struct {
WalletsMap map[string]*Wallet
}
type Wallet struct {
PrivateKey ecdsa.PrivateKey
PublicKey []byte
}
func (w *Wallets) SaveWallets() {
var content bytes.Buffer
gob.Register(elliptic.P256())
encoder := gob.NewEncoder(&content)
err := encoder.Encode(&w)
if err != nil {
log.Panic(err)
}
err = ioutil.WriteFile(walletFile, content.Bytes(), 0644)
if err != nil {
log.Panic(err)
}
}
func NewWallets() (*Wallets, error) {
if _, err := os.Stat(walletFile); os.IsNotExist(err) {
wallets := &Wallets{}
wallets.WalletsMap = make(map[string]*Wallet)
return wallets, err
}
fileContent, err := ioutil.ReadFile(walletFile)
if err != nil {
log.Panic(err)
}
var wallets Wallets
gob.Register(elliptic.P256())
decoder := gob.NewDecoder(bytes.NewReader(fileContent))
err = decoder.Decode(&wallets)
if err != nil {
log.Panic(err)
}
return &wallets, nil
}
问题:
2022/09/18 19:42:33 gob: type elliptic.p256Curve has no exported fields
panic: gob: type elliptic.p256Curve has no exported fields
英文:
I am trying to build a blockchain project when I'm catching an issue about gob Serialize.
I have a struct Wallet which uses elliptic.P256() Curve struct, and when I'm trying to serialize Wallet, a bug of no exported fields occured.
Really hope for some help.
There is my code.
const walletFile = "Wallets.dat"
type Wallets struct {
WalletsMap map[string]*Wallet
}
type Wallet struct {
PrivateKey ecdsa.PrivateKey
PublicKey []byte
}
func (w *Wallets) SaveWallets() {
var content bytes.Buffer
gob.Register(elliptic.P256())
encoder := gob.NewEncoder(&content)
err := encoder.Encode(&w)
if err != nil {
log.Panic(err)
}
err = ioutil.WriteFile(walletFile, content.Bytes(), 0644)
if err != nil {
log.Panic(err)
}
}
func NewWallets() (*Wallets, error) {
if _, err := os.Stat(walletFile); os.IsNotExist(err) {
wallets := &Wallets{}
wallets.WalletsMap = make(map[string]*Wallet)
return wallets, err
}
fileContent, err := ioutil.ReadFile(walletFile)
if err != nil {
log.Panic(err)
}
var wallets Wallets
gob.Register(elliptic.P256())
decoder := gob.NewDecoder(bytes.NewReader(fileContent))
err = decoder.Decode(&wallets)
if err != nil {
log.Panic(err)
}
return &wallets, nil
}
The issue
2022/09/18 19:42:33 gob: type elliptic.p256Curve has no exported fields
panic: gob: type elliptic.p256Curve has no exported fields
答案1
得分: 1
将您的Go版本更改为1.18.10以减少问题。我遇到了相同的问题,原因是最新的Go版本1.19.5。
我们需要按照旧的方式降级Go版本,因为Go没有提供像版本管理器这样的高级功能。
降级Go版本的步骤如下:
-
卸载现有的Go版本
要卸载Go,请找到Go在您系统上的位置。
$where go
这个命令将定位到用户路径中的程序文件。要卸载,请删除
/usr/local/go
目录或在上一个命令的输出中获得的源目录。使用命令
$ sudo rm -rf /usr/local/go
删除Go目录。要确认是否成功删除Go目录,请运行命令
$ go version
,如果系统提示“command go not found”,则表示您已成功删除Go目录。 -
安装新版本
转到下载页面,下载与您的操作系统和架构兼容的版本发布(选择安装程序而不是存档,以便更轻松地进行操作)。解压缩并提取软件包安装程序,新的Go版本现在已安装在您的系统中。
完成后,您需要重新启动终端以使更改生效。要检查是否成功安装Go,请运行命令$ go version
。该命令会打印安装的Go版本。还请确保GOROOT
和GOPATH
未更改。
英文:
Change your Go version to 1.18.10 for less. I have encountered the same issue due to the latest Go version i.e. 1.19.5
We need to downgrade the Go version the old way because Go doesn't provide anything like a fancy version manager.
Steps to downgrade Go Version:
-
Uninstall the existing Go version
To uninstall go, locate where Go is on your system.
$where go
This command will locate the program
file in the user path.To uninstall, delete the
/usr/local/go
directory or the source
directory which you have received as output in the previous command.
Use command$ sudo rm -rf /usr/local/go
to delete the Go directory.To confirm run the command
$ go version
,
system will prompt "command go not found" if you have successfully deleted Go ditrectory. -
Install the new version
Go to the downloads page and download the version release(choose installer instead of Archive to make things easy for yourself) which is compatible with your OS and Architecture. Unzip and extract the package installer and the new Go version is now installed in your system.
After that, you will need to restart your terminal for the change to take effect.
To check if you have installed Go successfully, run the command $go version
. The command prints the installed version of Go. Also make sure that GOROOT
and GOPATH
haven't changed.
答案2
得分: 1
我这里有一个解决方案
在go1.20中,对god的序列化需要使用反射,而在ecdsa.PrivateKey
类型的属性中有一个接口,可能无法使用。
如何解决呢?Ecdsa.PrivateKey
可能有一个专门的序列化方法。
示例代码如下:
type Wallet struct {
PrivateKey ecdsa.PrivateKey
PublicKey []byte
}
func (w *Wallet) Save() {
filename := filepath.Join(constcoe.Wallets, string(w.Address())+".wlt")
privKeyBytes, err := x509.MarshalECPrivateKey(&w.PrivateKey)
utils.Handle(err)
privKeyFile, err := os.Create(filename)
utils.Handle(err)
err = pem.Encode(privKeyFile, &pem.Block{
// Type: "EC PRIVATE KEY",
Bytes: privKeyBytes,
})
utils.Handle(err)
privKeyFile.Close()
}
func LoadWallet(address string) *Wallet {
filename := filepath.Join(constcoe.Wallets, address+".wlt")
if !utils.FileExists(filename) {
utils.Handle(errors.New("no wallet with such address"))
}
privKeyFile, err := os.ReadFile(filename)
utils.Handle(err)
pemBlock, _ := pem.Decode(privKeyFile)
utils.Handle(err)
privKey, err := x509.ParseECPrivateKey(pemBlock.Bytes)
utils.Handle(err)
publicKey := append(privKey.PublicKey.X.Bytes(), privKey.PublicKey.Y.Bytes()...)
return &Wallet{
PrivateKey: *privKey,
PublicKey: publicKey,
}
}
英文:
I have a solution here
In go1.20, the serialization of god requires reflection, while there is an interface in the attribute of type ecdsa.PrivateKey
, which may not be usable.
How to solve it? Ecdsa.PrivateKey
maybe have a specialized serialization method.
The demo is as follows:
type Wallet struct {
PrivateKey ecdsa.PrivateKey
PublicKey []byte
}
func (w *Wallet) Save() {
filename := filepath.Join(constcoe.Wallets, string(w.Address())+".wlt")
privKeyBytes, err := x509.MarshalECPrivateKey(&w.PrivateKey)
utils.Handle(err)
privKeyFile, err := os.Create(filename)
utils.Handle(err)
err = pem.Encode(privKeyFile, &pem.Block{
// Type: "EC PRIVATE KEY",
Bytes: privKeyBytes,
})
utils.Handle(err)
privKeyFile.Close()
}
func LoadWallet(address string) *Wallet {
filename := filepath.Join(constcoe.Wallets, address+".wlt")
if !utils.FileExists(filename) {
utils.Handle(errors.New("no wallet with such address"))
}
privKeyFile, err := os.ReadFile(filename)
utils.Handle(err)
pemBlock, _ := pem.Decode(privKeyFile)
utils.Handle(err)
privKey, err := x509.ParseECPrivateKey(pemBlock.Bytes)
utils.Handle(err)
publicKey := append(privKey.PublicKey.X.Bytes(), privKey.PublicKey.Y.Bytes()...)
return &Wallet{
PrivateKey: *privKey,
PublicKey: publicKey,
}
}
答案3
得分: 0
你似乎在尝试对crypto/elliptic
包中的P256曲线进行序列化。问题在于P256()
函数返回了一个名为elliptic.Curve
的接口。
这个错误告诉你的是,elliptic.Curve
的底层类型,即elliptic.p256Curve
,没有任何被导出的字段(首字母大写的字段)。Go语言的reflect
包,也就是encoding/gob
使用的包,只能处理被导出的字段。
你可以尝试使用crypto/elliptic
包中的Marshal()
或GenerateKey()
函数。
英文:
What you seem to be trying to do here is serialize a P256 curve from the crypto/elliptic
package. The issue is that the P256()
function returns an interface called elliptic.Curve
.
What this error is telling you is that the underlying type of the elliptic.Curve
, in this case elliptic.p256Curve
, doesn't have any fields that are exported (named with the first letter capitalized). Go's reflect
package, which encoding/gob
uses, only works on exported fields.
You might want to try using crypto/elliptic
's Marshal()
or GenerateKey()
functions.
答案4
得分: -1
这是Go语言1.9.*版本的问题。只需安装1.8.7版本即可,之后一切都会正常工作。
英文:
Its problem in 1.9.* versions of Go. Just install 1.8.7 for example. Everything gonna work fine after this)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论