如何使用Go创建PKCS#8私钥[重复]

This question already has an answer here:

I want to generate tls certificates.

So first I need a Private Key.

-----BEGIN PRIVATE KEY-----
BASE64 ENCODED DATA
-----END PRIVATE KEY-----

But, I can generate RSA Private Key

// "crypto/rsa"
rsa.GenerateKey(cryptorand.Reader, 2048)

which gives me following

-----BEGIN RSA PRIVATE KEY-----
BASE64 ENCODED DATA
-----END RSA PRIVATE KEY-----

And I can't use it. I need PKCS#8 Private Key start with BEGIN PRIVATE KEY

How can I generate PKCS#8 Private Key?

Or Is there any way to convert PKCS#1 to PKCS#8 Key?

</div>

Here's a solution based on the custom PKCS#8 marshal function in this answer:

package main

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

type PKCS8Key struct {
  Version             int
  PrivateKeyAlgorithm []asn1.ObjectIdentifier
  PrivateKey          []byte
}

func MarshalPKCS8PrivateKey(key *rsa.PrivateKey) ([]byte, error) {
  var pkey PKCS8Key
  pkey.Version = 0
  pkey.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 1)
  pkey.PrivateKeyAlgorithm[0] = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
  pkey.PrivateKey = x509.MarshalPKCS1PrivateKey(key)
  return asn1.Marshal(pkey)
}

func main() {
  // Generate the private key.
  privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
  fatal(err)

  // Encode the private key into PEM data.
  bytes, err := MarshalPKCS8PrivateKey(privateKey)
  fatal(err)
  privatePem := pem.EncodeToMemory(
    &pem.Block{
      Type:  "PRIVATE KEY",
      Bytes: bytes,
    },
  )
  fmt.Printf("%s
", privatePem)
  // -----BEGIN PRIVATE KEY-----
  // MIIEvAIBADALBgkqhkiG9w0BAQEEggSoMIIEpAIBAAKCAQEAz5xD5cdqdE0PMmk1
  // 4YN6Tj0ybTsvS5C95ogQmBJ4bGxiuGPR5JtIc+UmT8bnCHtK5xnHiP+gPWunwmhS
  // ...
  // qpb1NZsMLz2lRXqx+3Pq7Q==
  // -----END PRIVATE KEY-----
}

func fatal(err error) {
  if err != nil {
    panic(err)
  }
}

I don't know how exactly you get literal -----BEGIN RSA PRIVATE KEY----- Go stdlib crypto do not has PKCS#8 marshaller but there is generic asn1.Marchal() in encoding/asn1 and PKCS#8 standard(rfc5208) provide ASN#1 syntax definition, so you can do something like:

import (
    "crypto/rsa"
    "crypto/x509"
    "encoding/asn1"
)
type Pkcs8Key struct {
    Version             int
    PrivateKeyAlgorithm []asn1.ObjectIdentifier
    PrivateKey          []byte
}
func RsaToPkcs8(key *rsa.PrivateKey) ([]byte, error) {
    var pkey Pkcs8Key
    pkey.Version = 0
    pkey.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 1)
    pkey.PrivateKeyAlgorithm[0] = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
    pkey.PrivateKey = x509.MarshalPKCS1PrivateKey(key)

    return asn1.Marshal(pkey)
}