How to load DSA PublicKey using go stdlib

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

How to load DSA PublicKey using go stdlib

问题

我有一个PEM编码的DSA公钥。我需要这个DSA密钥来验证传入的数据。但是我还没有弄清楚如何使用Go加密库加载密钥(我不是加密专家,但从我在网上阅读的内容来看,DSA不再是一个流行的选择)。

我可以将PEM解码为其字节。据我了解,这些字节是DER编码的ASN.1格式。我如何将PEM块放入Go语言的dsa.PublicKey中?

这是一个可运行的示例:http://play.golang.org/p/8Ma2qwhT31

代码如下:

  1. package main
  2. import "fmt"
  3. import "encoding/pem"
  4. import "encoding/asn1"
  5. import "crypto/dsa"
  6. var signingPubKey = []byte(`-----BEGIN PUBLIC KEY-----
  7. MIICIDANBgkqhkiG9w0BAQEFAAOCAg0AMIICCAKCAgEApSmU3y4DzPhjnpOrdpPs
  8. cIosWJ4zSV8h02b0abLW6nk7cnb5jSwBZKLrryAlF4vs+cF1mtMYjX0QKtEYq2V6
  9. WVDnoXj3BeLYVbhsHuvxYmwXmAkNsSnhMfSCxsck9y6zuNeH0ovzBD90nISIJw+c
  10. VAnUt0dzc7YKjBqThHRAvi8HoGZlzB7Ryb8ePSW+Mfr4jcH3Mio5T0OH3HTavN6Y
  11. zpnohzQo0blwtwEXZOwrNPjQNrSigdPDrtvM32+hLTIJ75Z2NbIRLBjNlwznu7dQ
  12. Asb/AiPTHXihxCRDm+dH70dps5JfT5Zg9LKsPhANk6fNK3e4wdN89ybQsBaswp9h
  13. xzORVD3UiG4LuqP4LMCadjoEazShEiiveeRBgyiFlIldybuPwSq/gUuFveV5Jnqt
  14. txNG6DnJBlIeYhVlA25XDMjxnJ3w6mi/pZyn9ZR9+hFic7Nm1ra7hRUoigfD/lS3
  15. 3AsDoRLy0xZqCWGRUbkhlo9VjDxo5znjv870Td1/+fp9QzSaESPfFAUBFcykDXIU
  16. f1nVeKAkmhkEC9/jGF+VpUsuRV3pjjrLMcuI3+IimfWhWK1C56JJakfT3WB6nwY3
  17. A92g4fyVGaWFKfj83tTNL2rzMkfraExPEP+VGesr8b/QMdBlZRR4WEYG3ObD2v/7
  18. jgOS2Ol4gq8/QdNejP5J4wsCAQM=
  19. -----END PUBLIC KEY-----`)
  20. func main() {
  21. block, _ := pem.Decode(signingPubKey)
  22. if block == nil {
  23. fmt.Errorf("expected block to be non-nil", block)
  24. return
  25. }
  26. var pubkey dsa.PublicKey
  27. _,err := asn1.Unmarshal(block.Bytes, &pubkey)
  28. if (err != nil ){
  29. fmt.Errorf("could not unmarshall data: `%s`", err)
  30. }
  31. fmt.Printf("public key param P: %d\n", pubkey.Parameters.P)
  32. fmt.Printf("public key param Q: %d\n", pubkey.Parameters.Q)
  33. fmt.Printf("public key param G: %d\n", pubkey.Parameters.G)
  34. fmt.Printf("public key Y: %d\n", pubkey.Y)
  35. fmt.Printf("done")
  36. }

输出对于所有值都是nil,所以显然Unmarshal调用没有达到我想要的效果(或者在管道中的早期阶段出现了问题)。

英文:

I have a PEM encoded DSA public key. I need this DSA key so I can verify incoming data. But I have yet to figure out how to load the key using go crypto library (I am not a crypto expert but from what I'm reading online, DSA is not a popular choice anymore).

I can decode the PEM in to its bytes. Which, from what I understand, are DER-encoded ASN.1. How can I put the PEM blocks in to a golang dsa.PublicKey?

Here's a runnable sample: http://play.golang.org/p/8Ma2qwhT31

The code:

  1. package main
  2. import "fmt"
  3. import "encoding/pem"
  4. import "encoding/asn1"
  5. import "crypto/dsa"
  6. var signingPubKey = []byte(`-----BEGIN PUBLIC KEY-----
  7. MIICIDANBgkqhkiG9w0BAQEFAAOCAg0AMIICCAKCAgEApSmU3y4DzPhjnpOrdpPs
  8. cIosWJ4zSV8h02b0abLW6nk7cnb5jSwBZKLrryAlF4vs+cF1mtMYjX0QKtEYq2V6
  9. WVDnoXj3BeLYVbhsHuvxYmwXmAkNsSnhMfSCxsck9y6zuNeH0ovzBD90nISIJw+c
  10. VAnUt0dzc7YKjBqThHRAvi8HoGZlzB7Ryb8ePSW+Mfr4jcH3Mio5T0OH3HTavN6Y
  11. zpnohzQo0blwtwEXZOwrNPjQNrSigdPDrtvM32+hLTIJ75Z2NbIRLBjNlwznu7dQ
  12. Asb/AiPTHXihxCRDm+dH70dps5JfT5Zg9LKsPhANk6fNK3e4wdN89ybQsBaswp9h
  13. xzORVD3UiG4LuqP4LMCadjoEazShEiiveeRBgyiFlIldybuPwSq/gUuFveV5Jnqt
  14. txNG6DnJBlIeYhVlA25XDMjxnJ3w6mi/pZyn9ZR9+hFic7Nm1ra7hRUoigfD/lS3
  15. 3AsDoRLy0xZqCWGRUbkhlo9VjDxo5znjv870Td1/+fp9QzSaESPfFAUBFcykDXIU
  16. f1nVeKAkmhkEC9/jGF+VpUsuRV3pjjrLMcuI3+IimfWhWK1C56JJakfT3WB6nwY3
  17. A92g4fyVGaWFKfj83tTNL2rzMkfraExPEP+VGesr8b/QMdBlZRR4WEYG3ObD2v/7
  18. jgOS2Ol4gq8/QdNejP5J4wsCAQM=
  19. -----END PUBLIC KEY-----`)
  20. func main() {
  21. block, _ := pem.Decode(signingPubKey)
  22. if block == nil {
  23. fmt.Errorf("expected block to be non-nil", block)
  24. return
  25. }
  26. var pubkey dsa.PublicKey
  27. _,err := asn1.Unmarshal(block.Bytes, &pubkey)
  28. if (err != nil ){
  29. fmt.Errorf("could not unmarshall data: `%s`", err)
  30. }
  31. fmt.Printf("public key param P: %d\n", pubkey.Parameters.P)
  32. fmt.Printf("public key param Q: %d\n", pubkey.Parameters.Q)
  33. fmt.Printf("public key param G: %d\n", pubkey.Parameters.G)
  34. fmt.Printf("public key Y: %d\n", pubkey.Y)
  35. fmt.Printf("done")
  36. }

Which outputs nil for all values, so obviously the Unmarshal call isn't doing what I want (or something is wrong earlier in the pipeline).

答案1

得分: 1

我知道这是一个旧问题,因为没有答案,我也找不到类似的内容,这是我的实现:

  1. pubKeyPath := "./pubKey.pem"
  2. pubKeyBytes, err := ioutil.ReadFile(pubKeyPath)
  3. if err != nil {
  4. fmt.Println("读取文件时出错。错误信息:", err)
  5. }
  6. pubBlock, _ := pem.Decode(pubKeyBytes)
  7. // 这将返回一个 *dsa.PublicKey,但你的 IDE 可能会报错
  8. // 说它不是这个类型。
  9. pubKey, err := x509.ParsePKIXPublicKey(pubBlock.Bytes)
  10. // 所以,进行类型断言:
  11. dsaPubKey, ok := pubKey.(*dsa.PublicKey)
  12. if !ok {
  13. fmt.Println("类型断言失败")
  14. }
  15. // 使用公钥进行验证
  16. type Person struct {
  17. email string
  18. }
  19. // 假设类似的结构体实例被用于签名
  20. person := Person{ email: "hello@world.com" }
  21. personByteArray, _ := json.Marshal(person)
  22. // r 和 s 是签名后得到的值。在这里用它们进行验证
  23. fmt.Println(dsa.Verify(dsaPubKey, personByteArray, r, s))

上述实现每次运行代码时都会读取公钥的内容。

如果你正在生成一个可执行文件,并希望在运行 go build 时将公钥的内容嵌入二进制文件中,可以使用 Go 标准库中的 embed 包。

  1. import _ from "embed"
  2. //go:embed pubKey.pem
  3. var pubKeyBytes []byte

上述代码片段将在编译时将公钥作为字节加载进来。这样我们就只需要从文件系统中读取一次!

英文:

I know this is an old question, as there has been no answer for this and I couldn't find anything similar, here is my implementation

  1. pubKeyPath := "./pubKey.pem"
  2. pubKeyBytes, err := ioutil.ReadFile(pubKeyPath)
  3. if err != nil {
  4. fmt.Println("Something went wrong when reading the file. Failed with", err)
  5. }
  6. pubBlock, _ := pem.Decode(pubKeyBytes)
  7. // This returns a *dsa.PublicKey, but your IDE might complain
  8. // that its not.
  9. pubKey, err := x509.ParsePKIXPublicKey(pubBlock.Bytes)
  10. // So, type assert:
  11. dsaPubKey, ok := pubKey.(*dsa.PublicKey)
  12. if !ok {
  13. fmt.Println("Failed to type assert")
  14. }
  15. // Verify something with the Public key
  16. type Person struct {
  17. email string
  18. }
  19. // Assuming that a similar instance of the struct was used for signing
  20. person := Person{ email: "hello@world.com" }
  21. personByteArray, _ := json.Marshal(person)
  22. // r and s are what you get after signing. Using it here to verify
  23. fmt.Println(dsa.Verify(dsaPubKey, personByteArray, r, s))

The above implementation reads the contents of the public key everytime the code is run.

If you are generating an executable and would like the contents of the public key to be embedded in the binary when you run go build, use the embed package available in go's stdlib

  1. import _ from "embed"
  2. //go:embed pubKey.pem
  3. var pubKeyBytes []byte

The above code snippet will load the public key as bytes at compile time. This will enable us to read from the file system only once!

huangapple
  • 本文由 发表于 2015年8月13日 09:02:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/31977860.html
匿名

发表评论

匿名网友

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

确定