将加密/rsa私钥保存到磁盘并从磁盘加载

huangapple go评论127阅读模式
英文:

Save and load crypto/rsa PrivateKey to and from the disk

问题

我正在使用crypto/rsa,并尝试找到一种正确保存和加载密钥的方法。是否有一种正确的方法可以从rsa.PrivateKey创建一个[]byte?如果是这样,是否有一种正确的方法可以为rsa.PublicKey做到这一点?

非常感谢大家。

英文:

I'm using crypto/rsa, and trying to find a way to properly save and load a key. Is there a correct way to create a []byte from an rsa.PrivateKey. If so, is there a way to properly do so for an rsa.PublicKey?

Thank you all very much.

答案1

得分: 99

你需要一种格式来将密钥编组。Go标准库支持的一种格式可以在这里找到:http://golang.org/pkg/crypto/x509/#MarshalPKCS1PrivateKey

  1. func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte

逆函数是http://golang.org/pkg/crypto/x509/#ParsePKCS1PrivateKey。

  1. func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)

然而,将编组的密钥编码为PEM文件是相对标准的做法。

  1. pemdata := pem.EncodeToMemory(
  2. &pem.Block{
  3. Type: "RSA PRIVATE KEY",
  4. Bytes: x509.MarshalPKCS1PrivateKey(key),
  5. },
  6. )

你可以在这里找到一个完整的示例:这里

英文:

You need some sort of format to marshal the key into. One format supported by the Go standard library can be found here: http://golang.org/pkg/crypto/x509/#MarshalPKCS1PrivateKey

  1. func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte

The inverse function is http://golang.org/pkg/crypto/x509/#ParsePKCS1PrivateKey.

  1. func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)

However, it is relatively standard to encode the marshaled key into a PEM file.

  1. pemdata := pem.EncodeToMemory(
  2. &pem.Block{
  3. Type: "RSA PRIVATE KEY",
  4. Bytes: x509.MarshalPKCS1PrivateKey(key),
  5. },
  6. )

You can find a full example here.

答案2

得分: 66

这是一个代码片段,展示了公钥和私钥的导入和导出。它基于其他非常有用的答案,以及官方文档的复制粘贴。

  1. package main
  2. import (
  3. "crypto/rand"
  4. "crypto/rsa"
  5. "crypto/x509"
  6. "encoding/pem"
  7. "errors"
  8. "fmt"
  9. )
  10. func GenerateRsaKeyPair() (*rsa.PrivateKey, *rsa.PublicKey) {
  11. privkey, _ := rsa.GenerateKey(rand.Reader, 4096)
  12. return privkey, &privkey.PublicKey
  13. }
  14. func ExportRsaPrivateKeyAsPemStr(privkey *rsa.PrivateKey) string {
  15. privkey_bytes := x509.MarshalPKCS1PrivateKey(privkey)
  16. privkey_pem := pem.EncodeToMemory(
  17. &pem.Block{
  18. Type: "RSA PRIVATE KEY",
  19. Bytes: privkey_bytes,
  20. },
  21. )
  22. return string(privkey_pem)
  23. }
  24. func ParseRsaPrivateKeyFromPemStr(privPEM string) (*rsa.PrivateKey, error) {
  25. block, _ := pem.Decode([]byte(privPEM))
  26. if block == nil {
  27. return nil, errors.New("failed to parse PEM block containing the key")
  28. }
  29. priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  30. if err != nil {
  31. return nil, err
  32. }
  33. return priv, nil
  34. }
  35. func ExportRsaPublicKeyAsPemStr(pubkey *rsa.PublicKey) (string, error) {
  36. pubkey_bytes, err := x509.MarshalPKIXPublicKey(pubkey)
  37. if err != nil {
  38. return "", err
  39. }
  40. pubkey_pem := pem.EncodeToMemory(
  41. &pem.Block{
  42. Type: "RSA PUBLIC KEY",
  43. Bytes: pubkey_bytes,
  44. },
  45. )
  46. return string(pubkey_pem), nil
  47. }
  48. func ParseRsaPublicKeyFromPemStr(pubPEM string) (*rsa.PublicKey, error) {
  49. block, _ := pem.Decode([]byte(pubPEM))
  50. if block == nil {
  51. return nil, errors.New("failed to parse PEM block containing the key")
  52. }
  53. pub, err := x509.ParsePKIXPublicKey(block.Bytes)
  54. if err != nil {
  55. return nil, err
  56. }
  57. switch pub := pub.(type) {
  58. case *rsa.PublicKey:
  59. return pub, nil
  60. default:
  61. break // fall through
  62. }
  63. return nil, errors.New("Key type is not RSA")
  64. }
  65. func main() {
  66. // 创建密钥对
  67. priv, pub := GenerateRsaKeyPair()
  68. // 导出密钥为pem字符串
  69. priv_pem := ExportRsaPrivateKeyAsPemStr(priv)
  70. pub_pem, _ := ExportRsaPublicKeyAsPemStr(pub)
  71. // 从pem字符串导入密钥
  72. priv_parsed, _ := ParseRsaPrivateKeyFromPemStr(priv_pem)
  73. pub_parsed, _ := ParseRsaPublicKeyFromPemStr(pub_pem)
  74. // 导出新导入的密钥
  75. priv_parsed_pem := ExportRsaPrivateKeyAsPemStr(priv_parsed)
  76. pub_parsed_pem, _ := ExportRsaPublicKeyAsPemStr(pub_parsed)
  77. fmt.Println(priv_parsed_pem)
  78. fmt.Println(pub_parsed_pem)
  79. // 检查导出/导入的密钥是否与原始密钥匹配
  80. if priv_pem != priv_parsed_pem || pub_pem != pub_parsed_pem {
  81. fmt.Println("Failure: Export and Import did not result in same Keys")
  82. } else {
  83. fmt.Println("Success")
  84. }
  85. }
英文:

Here's code snippet that shows the import and export of both public and private keys. It's based on the other answers which were super helpful, as well as copy-pasta from the official docs.

  1. package main
  2. import (
  3. "crypto/rand"
  4. "crypto/rsa"
  5. "crypto/x509"
  6. "encoding/pem"
  7. "errors"
  8. "fmt"
  9. )
  10. func GenerateRsaKeyPair() (*rsa.PrivateKey, *rsa.PublicKey) {
  11. privkey, _ := rsa.GenerateKey(rand.Reader, 4096)
  12. return privkey, &privkey.PublicKey
  13. }
  14. func ExportRsaPrivateKeyAsPemStr(privkey *rsa.PrivateKey) string {
  15. privkey_bytes := x509.MarshalPKCS1PrivateKey(privkey)
  16. privkey_pem := pem.EncodeToMemory(
  17. &pem.Block{
  18. Type: "RSA PRIVATE KEY",
  19. Bytes: privkey_bytes,
  20. },
  21. )
  22. return string(privkey_pem)
  23. }
  24. func ParseRsaPrivateKeyFromPemStr(privPEM string) (*rsa.PrivateKey, error) {
  25. block, _ := pem.Decode([]byte(privPEM))
  26. if block == nil {
  27. return nil, errors.New("failed to parse PEM block containing the key")
  28. }
  29. priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  30. if err != nil {
  31. return nil, err
  32. }
  33. return priv, nil
  34. }
  35. func ExportRsaPublicKeyAsPemStr(pubkey *rsa.PublicKey) (string, error) {
  36. pubkey_bytes, err := x509.MarshalPKIXPublicKey(pubkey)
  37. if err != nil {
  38. return "", err
  39. }
  40. pubkey_pem := pem.EncodeToMemory(
  41. &pem.Block{
  42. Type: "RSA PUBLIC KEY",
  43. Bytes: pubkey_bytes,
  44. },
  45. )
  46. return string(pubkey_pem), nil
  47. }
  48. func ParseRsaPublicKeyFromPemStr(pubPEM string) (*rsa.PublicKey, error) {
  49. block, _ := pem.Decode([]byte(pubPEM))
  50. if block == nil {
  51. return nil, errors.New("failed to parse PEM block containing the key")
  52. }
  53. pub, err := x509.ParsePKIXPublicKey(block.Bytes)
  54. if err != nil {
  55. return nil, err
  56. }
  57. switch pub := pub.(type) {
  58. case *rsa.PublicKey:
  59. return pub, nil
  60. default:
  61. break // fall through
  62. }
  63. return nil, errors.New("Key type is not RSA")
  64. }
  65. func main() {
  66. // Create the keys
  67. priv, pub := GenerateRsaKeyPair()
  68. // Export the keys to pem string
  69. priv_pem := ExportRsaPrivateKeyAsPemStr(priv)
  70. pub_pem, _ := ExportRsaPublicKeyAsPemStr(pub)
  71. // Import the keys from pem string
  72. priv_parsed, _ := ParseRsaPrivateKeyFromPemStr(priv_pem)
  73. pub_parsed, _ := ParseRsaPublicKeyFromPemStr(pub_pem)
  74. // Export the newly imported keys
  75. priv_parsed_pem := ExportRsaPrivateKeyAsPemStr(priv_parsed)
  76. pub_parsed_pem, _ := ExportRsaPublicKeyAsPemStr(pub_parsed)
  77. fmt.Println(priv_parsed_pem)
  78. fmt.Println(pub_parsed_pem)
  79. // Check that the exported/imported keys match the original keys
  80. if priv_pem != priv_parsed_pem || pub_pem != pub_parsed_pem {
  81. fmt.Println("Failure: Export and Import did not result in same Keys")
  82. } else {
  83. fmt.Println("Success")
  84. }
  85. }

答案3

得分: 30

由于您的问题中的公钥部分没有得到回答,而我刚好遇到了同样的问题并解决了它,所以在这里是解决方法:

请注意MarshalPKIXPublicKey参数前面的&

  1. Priv := rsa.GenerateKey(rand.Reader, 4096)
  2. pubASN1, err := x509.MarshalPKIXPublicKey(&Priv.PublicKey)
  3. if err != nil {
  4. // 处理错误
  5. }
  6. pubBytes := pem.EncodeToMemory(&pem.Block{
  7. Type: "RSA PUBLIC KEY",
  8. Bytes: pubASN1,
  9. })
  10. ioutil.WriteFile("key.pub", pubBytes, 0644)

相关阅读:

  • MarshalPKIXPublicKey(pub interface{}) ([]byte, error) godoc
  • EncodeToMemory(b *Block) []byte godoc
  • Block godoc

PS: MarshalPKIXPublicKey也接受ECDSA密钥,根据需要调整pem头部。

英文:

Since the public key part of your question wasn't answered and I just ran into the same problem and solved it, here it is:

Note the & in front of the Argument to MarshalPKIXPublicKey

  1. Priv := rsa.GenerateKey(rand.Reader, 4096)
  2. pubASN1, err := x509.MarshalPKIXPublicKey(&Priv.PublicKey)
  3. if err != nil {
  4. // do something about it
  5. }
  6. pubBytes := pem.EncodeToMemory(&pem.Block{
  7. Type: "RSA PUBLIC KEY",
  8. Bytes: pubASN1,
  9. })
  10. ioutil.WriteFile("key.pub", pubBytes, 0644)

Relevant reads:

  • MarshalPKIXPublicKey(pub interface{}) ([]byte, error) godoc
  • EncodeToMemory(b *Block) []byte godoc
  • Block godoc

PS: MarshalPKIXPublicKey also accepts ECDSA keys, ajust the pem header appropriately.

huangapple
  • 本文由 发表于 2012年11月26日 04:20:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/13555085.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定