Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 如何从PKCS#12容器中提取私钥并将其保存为PKCS#8格式?_Go_Pkcs#12_Pkcs#8 - Fatal编程技术网

Go 如何从PKCS#12容器中提取私钥并将其保存为PKCS#8格式?

Go 如何从PKCS#12容器中提取私钥并将其保存为PKCS#8格式?,go,pkcs#12,pkcs#8,Go,Pkcs#12,Pkcs#8,我希望能够使用AWS SNS和AWSgolangSDK发送iOS APNS推送通知。我按照以下说明创建了一个p12文件: 现在,为了获得私钥和证书,我需要实现以下与openssl等效的命令: openssl pkcs12 -in MyCertificates.p12 -out MyCer.pem -clcerts -nokeys openssl pkcs12 -in MyCertificates.p12 -out MyKey.pem -nocerts -nodes openssl pkcs8 -

我希望能够使用AWS SNS和AWSgolangSDK发送iOS APNS推送通知。我按照以下说明创建了一个p12文件: 现在,为了获得私钥和证书,我需要实现以下与openssl等效的命令:

openssl pkcs12 -in MyCertificates.p12 -out MyCer.pem -clcerts -nokeys
openssl pkcs12 -in MyCertificates.p12 -out MyKey.pem -nocerts -nodes
openssl pkcs8 -topk8 -inform pem -in MyKey.pem -outform pem -nocrypt -out MyKeyCorrectFormat.pem
我在歌朗找不到这样做的方法,任何帮助都将不胜感激。问题似乎在于将私钥转换为pkcs8格式

编辑:

这就是我一直试图做的(为了编译,您需要将github.com/youmark/pkcs8中的第一个导入更改为golang.org/x/crypto/pbkdf2):


打印转换后的密钥时会出现乱码,所以我想我的解码过程可能出了问题。

我想你在那里。您已将密钥转换为PKCS#8格式,但它显示为乱码,因为它是以二进制形式打印的。密钥只需要以pem格式进行编码

测试这一点的一种方法是创建自己的pkcs#12文件,其中包含一个。一个好处是,您可以更改到期期限以执行证书到期错误处理:

go run generate_cert.go -ca -duration 30m -host gooble.com
它生成key.pem和cert.pem。组合密钥和证书:

cat key.pem cert.pem > both.pem
捆绑成pkcs#12:

这里bundle.12是一个二进制形式的pkcs#12文件,包含证书和私钥,并受密码保护

运行go程序(请参阅下面的源代码)以提取证书和密钥:

go run pk.go -in bundle.12 -outkey key8.pem -outcert outcert.pem -password 123456
提取的证书与原始证书相同。提取的私钥与原始私钥类似,但现在为pkcs#8格式

您可以从pkcs8文件中提取原始rsa密钥。原始key.pem与key.final.pem相同:

openssl rsa -in key8.pem -out key.final.pem
您还可以验证提取的pkcs#8私钥与原始证书具有相同的模数:

openssl x509 -in cert.pem -noout -modulus
Modulus=AEB5770C4DA8D...05E12398BE1

openssl rsa -in key8.pem -noout -modulus
Modulus=AEB5770C4DA8D...05E12398BE1
请注意,提取的pkcs#8私钥未加密;这可能不是你想要的,这取决于钥匙的使用方式

下面是对围棋程序(pk.go)稍加修改的版本:


希望能有所帮助。

为什么每次都要这样做?仅转换一次证书并始终使用转换后的格式还不够吗?当然,我不会每次都进行转换。但是你知道怎么做吗?在你已经在命令行中做了之后,为什么还要在围棋中做呢?对不起,我现在理解你的评论了。我需要能够通过我们的golang web服务器对许多应用程序进行编程。既然您提出了要求,似乎您搜索了
golang+“pkcs#8”
,然后搜索了
golang+“pkcs#12”
,然后发现,您试图让它们一起工作,但失败了,对吗?那么到底是什么不起作用呢?反过来怎么办?在这里,您将pkcs12容器拆分为它包含的私钥和公钥。我想在围棋中用另一种方式。使用公钥和私钥创建pkcs12容器。等效的
openssl
命令如下所示:
opensslpkcs12-export-clcerts-inkey-input.key-in-input.crt-out-output.p12-name“foo”
。在go中如何做到这一点?据我所知,go中没有实现@xh3b4sd编码。PEM对你来说是一个可能的选择吗?PKCS#12的另一种更简单的替代格式是PEM,它仅将证书和可能的私钥列为文本文件中的基64字符串。或者可能在openssl中作为外部命令运行导出?我已经有PEM编码的证书。我想使用这些创建pkcs12容器,您可以将其添加到浏览器中。我还发现go中不支持对pkcs12容器的写支持。看到了吗?可以连接PEM文件并将其导入浏览器吗?
openssl rsa -in key8.pem -out key.final.pem
openssl x509 -in cert.pem -noout -modulus
Modulus=AEB5770C4DA8D...05E12398BE1

openssl rsa -in key8.pem -noout -modulus
Modulus=AEB5770C4DA8D...05E12398BE1
package main

import (
    "crypto/x509"
    "encoding/pem"
    "errors"
    "flag"
    "github.com/youmark/pkcs8"
    "golang.org/x/crypto/pkcs12"
    "io/ioutil"
    "log"
    "os"
)

var (
    in       = flag.String("in", "", "pkcs#12 input file (private key and certificate only)")
    password = flag.String("password", "", "to unlock the pkcs#12 bundle")
    outkey   = flag.String("outkey", "", "output filename of private key in pkcs#8 PEM format")
    outcert  = flag.String("outcert", "", "output filename of certificate in PEM format")
)

func main() {
    flag.Parse()

    if *in == "" || *password == "" || *outkey == "" || *outcert == "" {
        flag.Usage()
        os.Exit(1)
    }

    data, err := ioutil.ReadFile(*in)
    if err != nil {
        log.Fatal(err)
    }

    privateKey, certificate, err := pkcs12.Decode(data, *password)
    if err != nil {
        log.Fatal(err)
    }

    if err := verify(certificate); err != nil {
        log.Fatal(err)
    }

    keyBytes, err := pkcs8.ConvertPrivateKeyToPKCS8(privateKey)
    if err != nil {
        log.Fatal(err)
    }

    //could write private key as binary DER encoded (instead of pem below)
    //_, err = ioutil.WriteFile(*outkey,keyBytes,0644)

    //write private key as pem
    keyFile, err := os.Create(*outkey)
    if err != nil {
        log.Fatal(err)
    }
    defer keyFile.Close()
    err = pem.Encode(keyFile, &pem.Block{Type: "PRIVATE KEY", Bytes: keyBytes})
    if err != nil {
        log.Fatal(err)
    }

    certFile, err := os.Create(*outcert)
    if err != nil {
        log.Fatal(err)
    }
    defer certFile.Close()
    err = pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: certificate.Raw})
    if err != nil {
        log.Fatal(err)
    }
}

// verify checks if a certificate has expired
func verify(cert *x509.Certificate) error {
    _, err := cert.Verify(x509.VerifyOptions{})
    if err == nil {
        return nil
    }

    switch e := err.(type) {
    case x509.CertificateInvalidError:
        switch e.Reason {
        case x509.Expired:
            return ErrExpired
        default:
            return err
        }
    case x509.UnknownAuthorityError:
        // Apple cert isn't in the cert pool
        // ignoring this error
        return nil
    default:
        return err
    }
}

// Certificate errors
var (
    ErrExpired = errors.New("certificate has expired or is not yet valid")
)