How to load DSA PublicKey using go stdlib

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

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

代码如下:

package main

import "fmt"
import "encoding/pem"
import "encoding/asn1"
import "crypto/dsa"

var signingPubKey = []byte(`-----BEGIN PUBLIC KEY-----
MIICIDANBgkqhkiG9w0BAQEFAAOCAg0AMIICCAKCAgEApSmU3y4DzPhjnpOrdpPs
cIosWJ4zSV8h02b0abLW6nk7cnb5jSwBZKLrryAlF4vs+cF1mtMYjX0QKtEYq2V6
WVDnoXj3BeLYVbhsHuvxYmwXmAkNsSnhMfSCxsck9y6zuNeH0ovzBD90nISIJw+c
VAnUt0dzc7YKjBqThHRAvi8HoGZlzB7Ryb8ePSW+Mfr4jcH3Mio5T0OH3HTavN6Y
zpnohzQo0blwtwEXZOwrNPjQNrSigdPDrtvM32+hLTIJ75Z2NbIRLBjNlwznu7dQ
Asb/AiPTHXihxCRDm+dH70dps5JfT5Zg9LKsPhANk6fNK3e4wdN89ybQsBaswp9h
xzORVD3UiG4LuqP4LMCadjoEazShEiiveeRBgyiFlIldybuPwSq/gUuFveV5Jnqt
txNG6DnJBlIeYhVlA25XDMjxnJ3w6mi/pZyn9ZR9+hFic7Nm1ra7hRUoigfD/lS3
3AsDoRLy0xZqCWGRUbkhlo9VjDxo5znjv870Td1/+fp9QzSaESPfFAUBFcykDXIU
f1nVeKAkmhkEC9/jGF+VpUsuRV3pjjrLMcuI3+IimfWhWK1C56JJakfT3WB6nwY3
A92g4fyVGaWFKfj83tTNL2rzMkfraExPEP+VGesr8b/QMdBlZRR4WEYG3ObD2v/7
jgOS2Ol4gq8/QdNejP5J4wsCAQM=
-----END PUBLIC KEY-----`)

func main() {
    block, _ := pem.Decode(signingPubKey)
    if block == nil {
        fmt.Errorf("expected block to be non-nil", block)
        return
    }
    
    var pubkey dsa.PublicKey
    
    _,err := asn1.Unmarshal(block.Bytes, &pubkey)
    if (err != nil ){
        fmt.Errorf("could not unmarshall data: `%s`", err)
    }
    
    fmt.Printf("public key param P: %d\n", pubkey.Parameters.P)
    fmt.Printf("public key param Q: %d\n", pubkey.Parameters.Q)
    fmt.Printf("public key param G: %d\n", pubkey.Parameters.G)
    fmt.Printf("public key Y: %d\n", pubkey.Y)
    
    fmt.Printf("done")
}

输出对于所有值都是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:

package main

import "fmt"
import "encoding/pem"
import "encoding/asn1"
import "crypto/dsa"

var signingPubKey = []byte(`-----BEGIN PUBLIC KEY-----
MIICIDANBgkqhkiG9w0BAQEFAAOCAg0AMIICCAKCAgEApSmU3y4DzPhjnpOrdpPs
cIosWJ4zSV8h02b0abLW6nk7cnb5jSwBZKLrryAlF4vs+cF1mtMYjX0QKtEYq2V6
WVDnoXj3BeLYVbhsHuvxYmwXmAkNsSnhMfSCxsck9y6zuNeH0ovzBD90nISIJw+c
VAnUt0dzc7YKjBqThHRAvi8HoGZlzB7Ryb8ePSW+Mfr4jcH3Mio5T0OH3HTavN6Y
zpnohzQo0blwtwEXZOwrNPjQNrSigdPDrtvM32+hLTIJ75Z2NbIRLBjNlwznu7dQ
Asb/AiPTHXihxCRDm+dH70dps5JfT5Zg9LKsPhANk6fNK3e4wdN89ybQsBaswp9h
xzORVD3UiG4LuqP4LMCadjoEazShEiiveeRBgyiFlIldybuPwSq/gUuFveV5Jnqt
txNG6DnJBlIeYhVlA25XDMjxnJ3w6mi/pZyn9ZR9+hFic7Nm1ra7hRUoigfD/lS3
3AsDoRLy0xZqCWGRUbkhlo9VjDxo5znjv870Td1/+fp9QzSaESPfFAUBFcykDXIU
f1nVeKAkmhkEC9/jGF+VpUsuRV3pjjrLMcuI3+IimfWhWK1C56JJakfT3WB6nwY3
A92g4fyVGaWFKfj83tTNL2rzMkfraExPEP+VGesr8b/QMdBlZRR4WEYG3ObD2v/7
jgOS2Ol4gq8/QdNejP5J4wsCAQM=
-----END PUBLIC KEY-----`)

func main() {
	block, _ := pem.Decode(signingPubKey)
	if block == nil {
		fmt.Errorf("expected block to be non-nil", block)
		return
	}
	
	var pubkey dsa.PublicKey
	
	_,err := asn1.Unmarshal(block.Bytes, &pubkey)
	if (err != nil ){
		fmt.Errorf("could not unmarshall data: `%s`", err)
	}
	
	fmt.Printf("public key param P: %d\n", pubkey.Parameters.P)
	fmt.Printf("public key param Q: %d\n", pubkey.Parameters.Q)
	fmt.Printf("public key param G: %d\n", pubkey.Parameters.G)
	fmt.Printf("public key Y: %d\n", pubkey.Y)
	
	fmt.Printf("done")
}

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

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

pubKeyPath := "./pubKey.pem"
pubKeyBytes, err := ioutil.ReadFile(pubKeyPath)

if err != nil {
   fmt.Println("读取文件时出错。错误信息:", err)
}

pubBlock, _ := pem.Decode(pubKeyBytes)

// 这将返回一个 *dsa.PublicKey,但你的 IDE 可能会报错
// 说它不是这个类型。
pubKey, err := x509.ParsePKIXPublicKey(pubBlock.Bytes)

// 所以,进行类型断言:
dsaPubKey, ok := pubKey.(*dsa.PublicKey)

if !ok {
   fmt.Println("类型断言失败")
}

// 使用公钥进行验证
type Person struct {
  email  string 
}

// 假设类似的结构体实例被用于签名
person := Person{ email: "hello@world.com" }
personByteArray, _ := json.Marshal(person)

// r 和 s 是签名后得到的值。在这里用它们进行验证
fmt.Println(dsa.Verify(dsaPubKey, personByteArray, r, s))

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

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

import _ from "embed"

//go:embed pubKey.pem
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


pubKeyPath := "./pubKey.pem"
pubKeyBytes, err := ioutil.ReadFile(pubKeyPath)

if err != nil {
   fmt.Println("Something went wrong when reading the file. Failed with", err)
}

pubBlock, _ := pem.Decode(pubKeyBytes)

// This returns a *dsa.PublicKey, but your IDE might complain
// that its not.
pubKey, err := x509.ParsePKIXPublicKey(pubBlock.Bytes)

// So, type assert:
dsaPubKey, ok := pubKey.(*dsa.PublicKey)

if !ok {
   fmt.Println("Failed to type assert")
}

// Verify something with the Public key
type Person struct {
  email  string 
}

// Assuming that a similar instance of the struct was used for signing
person := Person{ email: "hello@world.com" }
personByteArray, _ := json.Marshal(person)

// r and s are what you get after signing. Using it here to verify
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

import _ from "embed"

//go:embed pubKey.pem
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:

确定