在Go中生成X.509证书时出错

I'm new using Go and I'm trying to generate an X.509 certificate using this code:

cert, err := x509.CreateCertificate(
    random,
    &certTemplate,
    cert,
    publicKey,
    privateKey
)

where the publicKey variable is typed as interface{} and it is the result of calling x509.ParsePKIXPublicKey(bytes).

The error I'm having is:

x509: only RSA and ECDSA public keys supported

I arrived to the conclusion that this is a consequence of passing the publicKey typed as interface{} to the x509.CreateCertificate function, since it doesn't match the type switch inside that function. I tried passing &publicKey with the same result. I also tried doing a type assertion using the publicKey, like this:

var pk *ecdsa.PublicKey
pk = publicKey.(*ecdsa.PublicKey)

cert, err := x509.CreateCertificate(
    random,
    &certTemplate,
    cert,
    pk,
    privateKey
)

but then I get this error: panic: interface conversion: interface {} is nil, not *ecdsa.PublicKey The same error occurs if I pass &pk as a parameter.

This is how I generate the public key:

// Generate key pair
curve := elliptic.P384()
privateKey := new(ecdsa.PrivateKey)
privateKey, err := ecdsa.GenerateKey(curve, rand.Reader)
publicKey := &privatekey.PublicKey

// Obtain bytes from public key for communication using protobuf
publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)

// Protobuf communication takes place here

receivedPublicKey, err := x509.ParsePKIXPublicKey(publicKeyBytes)

// verification of public key here (the verification ends successfully)
// populate X.509 template

// create certificate
certificate, err := x509.CreateCertificate(
    random,
    &certificateTemplate,
    certificate,
    receivedPublicKey,
    privateKey,
)

If someone can point me in the right direction or knows how to solve this issue it will be really helpful. Thanks in advance!

The crypto/tls package contains a file called generate_cert.go which shows the proper and idiomatic way to generate a self signed certificate.

You can find it here: https://golang.org/src/crypto/tls/generate_cert.go

Or by browsing the files in the tls package directory in the filesystem location where you installed Go.

There are a number of things that should be done correctly and short of enumerating them all, reading, running, modifying and understanding that code is the best way to get to grips with how to use the crypto packages when generating certs.

In particular be careful of what you pass in to the x509.CreateCertificate function as the public and private keys. In the crypto packages keys are of the interface{} type which happily and dangerously turns compile time type checks into runtime type checks.

I got it to work doing something like this:

// Generate key pair
curve := elliptic.P384()
//privateKey := new(ecdsa.PrivateKey)
privateKey, err := ecdsa.GenerateKey(curve, rand.Reader)
publicKey := &privateKey.PublicKey

And the rest as exactly what you wrote, see if you can mirror this and make it work.