添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm trying to get an object of rsa.PublicKey and I made these steps:

 ----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")

After this, when I try to x509.ParsePKIXPublicKey(block.Bytes) I get an error:

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

So, I read some blogs and documentations about DER and PEM formats, and they are differents ways to encode an certificate, basicaly one use base64 and other is just bytes.

In x509's package of Golang, the x509.ParsePKIXPublicKey says:

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

And, in the example of this function use the pem.Decode(). I'm very confused about this because this should use pem.Decode or something like der.Decode() ?

Also, what's the real difference between x509.ParsePKCS1PublicKey() and x509.ParsePKIXPublicKey() ? Both do the same job to get a rsa.PublicKey ?

How did you create the keys? I've found that the go libraries can't parse the keys when they're created by openssl. You have to actually create the keys using go's key creation code. It's kind of a weird issue. I'll post a link when I get to work for the go code to do the creation. – Benji Vesterby Feb 19, 2019 at 15:40 This key was created in Ruby's legacy service, and I just tried to encrypt a token with this PublicKey. – Matheus Vinícius de Andrade Feb 19, 2019 at 16:02 Yeah it sounds like the issue is with the ruby generated certificates. Try the solution I posted and see if the certificates that that generates works for you. My guess is that it's the same issue I ran into when creating certificates with openssl. The error looks like the same error I was getting. – Benji Vesterby Feb 19, 2019 at 18:29 @BenjiVesterby The issue you're both experiencing is to do with different encodings. There are multiple ways (PKCS#1 and PKCS#8) to encode RSA keys. – Luke Joshua Park Feb 19, 2019 at 22:03

The issue here is understanding the difference between x509.ParsePKCS1PublicKey (PKCS#1) and x509.ParsePKIXPublicKey (PKCS#8).

Usually when the PEM header has the type as RSA PUBLIC KEY, it is referring to a PKCS#1 encoded RSA public key, which is defined in RFC 8017 (PKCS#1) as:

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

You haven't actually provided the body of your public key (it would be safe to do so), but it is a fair assumption that, if decoding the key using x509.ParsePKIXPublicKey failed, your key is likely in the above format (x509.ParsePKIXPublicKey uses PKCS#8 encoding).

If this is the case, you should be able to get an rsa.PublicKey from the file using the following code (don't forget to add the error handling):

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

If this doesn't solve your problem, try pasting the key you have into this site to see what ASN.1 structure it uses. For reference, the key I used to test this is included here:

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

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

You have to generate the certificates using the code above.

Like this:

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

openssl pkcs8 -topk8 -nocrypt -in key.pem -out privatekey.pcks8

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

This should solve the issue for you and give you the files you need.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.