x509 Go软件包-ParsePKIXPublicKey是DER还是PEM?

时间:2019-02-19 15:01:55

标签: go

我正在尝试获取rsa.PublicKey的对象,并执行了以下步骤:

 ----BEGIN RSA PUBLIC KEY----
           ....
 ----END RSA PUBLIC KEY----
package main

import (
   "crypto/rand"
   "crypto/rsa"
   "crypto/x509"
   "encoding/pem"
   "fmt"
   "io/ioutil"
)

func main() {

 key, err := ioutil.ReadFile("./new_public.pem")
 if err != nil {
    fmt.Println(err.Error())
 }

 block, _ := pem.Decode([]byte(key))
 if block == nil {
    fmt.Println("unable to decode publicKey to request")
 }

 pub, err := x509.ParsePKIXPublicKey(block.Bytes)
 if err != nil {
     panic("failed to parse RSA encoded  public key" + err.Error())
 }

 switch pub := pub.(type) {
 case *rsa.PublicKey:
     fmt.Println("pub is of type RSA:", pub)
 default:
     panic("error")
 }

}

此后,当我尝试x509.ParsePKIXPublicKey(block.Bytes)时出现错误:

panic: failed to parse RSA encoded  public keyasn1: 
structure error: tags don't match (16 vs {class:0 tag:2 length:129 isCompound:false}) 
{
 optional:false 
 explicit:false 
 application:false 
 private:false 
 defaultValue:<nil> tag:<nil> 
 stringType:0 
 timeType:0 
 set:false 
 omitEmpty:false
} AlgorithmIdentifier @3

因此,我阅读了一些有关DER和PEM格式的博客和文档,它们是编码证书的不同方法,基本上一个使用base64,而另一个仅使用字节。

在x509的Golang软件包中,x509.ParsePKIXPublicKey表示:

ParsePKIXPublicKey parses a DER-encoded public key. These values are typically found in PEM blocks with "BEGIN PUBLIC KEY"

并且,在此函数的示例中,使用pem.Decode()。我对此很困惑,因为应该使用pem.Decode或类似der.Decode()的东西?

此外,x509.ParsePKCS1PublicKey()x509.ParsePKIXPublicKey()之间的真正区别是什么?两者都做相同的工作来获得rsa.PublicKey吗?

2 个答案:

答案 0 :(得分:1)

这里的问题是了解x509.ParsePKCS1PublicKey(PKCS#1)和x509.ParsePKIXPublicKey(PKCS#8)之间的区别。

通常,当PEM标头的类型为RSA PUBLIC KEY时,它是指PKCS#1编码的RSA公钥,在RFC 8017 (PKCS#1)中定义为:

RSAPublicKey ::= SEQUENCE {
     modulus           INTEGER,  -- n
     publicExponent    INTEGER   -- e
 }

您实际上并未提供公共密钥的主体(这样做是安全的),但是可以合理地假设,如果使用x509.ParsePKIXPublicKey解密密钥失败,那么您的密钥很可能位于上面的格式(x509.ParsePKIXPublicKey使用PKCS#8编码)。

在这种情况下,您应该可以使用以下代码从文件中获取rsa.PublicKey(不要忘记添加错误处理):

rawPem, _ := ioutil.ReadFile("./public.key")
pemBlock, _ := pem.Decode(rawPem)
publicKey, _ := x509.ParsePKCS1PublicKey(pemBlock.Bytes)

如果这不能解决您的问题,请尝试将拥有的密钥粘贴到this site中以查看其使用的ASN.1结构。作为参考,这里包含了我用来测试的密钥:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEApW1W9dnfdFF7FHrq6HPveR/9T+nM70yO7QOGytR0j/chMBJcJBjG
hJOuKPFbkVyS+BE/4M8CojLgvz4ex82Re0sFa5TqnoWvuP5P4vktR6M5W53sTW3y
gUnfF/oHcEmARQ1xKZdgVnlIfrdbpjecPyLi1Ng4HmhEfCFUOW64koxpb4XeH5O5
q+vc/731ExVOYBU8Sl6kPdjpJuVjS3DHKAVgfVEhscXd3JDjDuMDT3w1IYNb5c2s
wHE55q4Jnc1cr42jdynnkXzmuOGo2C6yD95kbBDLp7wSiBxaMA8gbRkzWJ99T+6l
KsKG2zfndMF3jZW1v1wWiEbYRN07qbN0NQIDAQAB
-----END RSA PUBLIC KEY-----

ASN.1 Structure of reference RSA Public Key

答案 1 :(得分:0)

您在这里。

https://golang.org/src/crypto/tls/generate_cert.go

您必须使用上面的代码生成证书。

赞:

./ generate_cert --host =“ source:destination” -rsa-bits 1024

openssl pkcs8 -topk8 -nocrypt-输入key.pem -out privatekey.pcks8

openssl x509 -pubkey -noout -in cert.pem> publickey.pem

这应该可以为您解决问题,并为您提供所需的文件。