如何在 Go 中存储 ECDSA 私钥
Posted
技术标签:
【中文标题】如何在 Go 中存储 ECDSA 私钥【英文标题】:How to store ECDSA private key in Go 【发布时间】:2014-01-24 00:28:51 【问题描述】:我正在使用 ecdsa.GenerateKey
方法在 Go 中生成私钥/公钥对。我想将私钥存储在用户计算机上的文件中,并在程序启动时加载它。有一种方法elliptic.Marshal
可以对公钥进行编组,但对私钥没有任何作用。我应该自己滚动,还是有推荐的方法来存储私钥?
【问题讨论】:
其他使用非对称加密的程序(例如 OpenSSH)通常将私钥存储在一个只有用户才能访问的文件中(在 linux / unix 系统上为 root,在 Windows 上为管理员)。在 Linux / Unix 上,这通常通过chmod 600 ~/private.key
之类的东西来实现。更安全的系统将使用密钥提供者服务或系统从完全独立的系统中提供私钥。这些都带来了一些他们自己的警告和注意事项。
【参考方案1】:
这是一个演示 Go 中键的编码和解码的代码示例。知道您需要连接几个步骤会有所帮助。加密算法是第一步,在本例中为 ECDSA 密钥。然后你需要标准编码,x509是最常用的标准。最后你需要一种文件格式,PEM 也是常用的一种。这是目前最常用的组合,但您可以随意替换任何其他算法或编码。
func encode(privateKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey) (string, string)
x509Encoded, _ := x509.MarshalECPrivateKey(privateKey)
pemEncoded := pem.EncodeToMemory(&pem.BlockType: "PRIVATE KEY", Bytes: x509Encoded)
x509EncodedPub, _ := x509.MarshalPKIXPublicKey(publicKey)
pemEncodedPub := pem.EncodeToMemory(&pem.BlockType: "PUBLIC KEY", Bytes: x509EncodedPub)
return string(pemEncoded), string(pemEncodedPub)
func decode(pemEncoded string, pemEncodedPub string) (*ecdsa.PrivateKey, *ecdsa.PublicKey)
block, _ := pem.Decode([]byte(pemEncoded))
x509Encoded := block.Bytes
privateKey, _ := x509.ParseECPrivateKey(x509Encoded)
blockPub, _ := pem.Decode([]byte(pemEncodedPub))
x509EncodedPub := blockPub.Bytes
genericPublicKey, _ := x509.ParsePKIXPublicKey(x509EncodedPub)
publicKey := genericPublicKey.(*ecdsa.PublicKey)
return privateKey, publicKey
func test()
privateKey, _ := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
publicKey := &privateKey.PublicKey
encPriv, encPub := encode(privateKey, publicKey)
fmt.Println(encPriv)
fmt.Println(encPub)
priv2, pub2 := decode(encPriv, encPub)
if !reflect.DeepEqual(privateKey, priv2)
fmt.Println("Private keys do not match.")
if !reflect.DeepEqual(publicKey, pub2)
fmt.Println("Public keys do not match.")
【讨论】:
可能是一个新手问题——为什么需要对这些密钥进行编码?我创建了我的密钥对,将它们打印到标准输出(基础字段是big.Int
)。然后加载,我初始化了ecdsa.PrivateKey|PublicKey
结构并填充了它们的字段,但这不起作用。但是,当我按照您的解决方案建议进行编码时,它起作用了。
"printing big.Int to stdout" 是一种编码方式。你想出了你自己的。区别基本上是标准编码适用于任何地方,而您的编码特定于 Go 和 big.Int。虽然您可以使用自己的,但使用上述步骤很容易,因此一旦设置好,您就是标准的,而不是发明自己的东西。【参考方案2】:
我相信这些密钥的标准格式是使用 X.509 ASN.1 DER 表示。请参阅http://golang.org/pkg/crypto/x509/#MarshalECPrivateKey 和http://golang.org/pkg/crypto/x509/#ParseECPrivateKey。
【讨论】:
【参考方案3】:我采用了一种非常快速而肮脏的方式来做到这一点,正如 15 年末在我的图书馆 https://github.com/DaveAppleton/ether_go 中的一个 geth 团队所建议的那样@
这是一个更简单的解决方案(但将钥匙放在显而易见的地方)
【讨论】:
以上是关于如何在 Go 中存储 ECDSA 私钥的主要内容,如果未能解决你的问题,请参考以下文章