简体   繁体   English

如何在本机Go中将PEM证书链转换为PKCS7?

[英]How to convert PEM certificate chain to PKCS7 in native Go?

I am looking for any practical method for converting a PEM -encoded x509 certificate chain into PKCS7 format in the Go language. 我正在寻找将Gom语言中将PEM编码的x509证书链转换为PKCS7格式的任何实用方法。

This openssl command line illustrates what I am trying to achieve in native Go. openssl命令行说明了我要在本机Go中实现的目标。

openssl crl2pkcs7 -nocrl -certfile certificate-chain.pem > pkcs7.pem

I am able to run the openssl command line from within a Go program using the exec package, but I am looking for an efficient solution in Go. 我可以使用exec包从Go程序中运行openssl命令行,但是我正在寻找Go中的有效解决方案。

The input file contains a sequence of certificates in PEM format, starting with -----BEGIN CERTIFICATE-----\\n and base64 encoded data. 输入文件包含一系列PEM格式的证书,以----- BEGIN CERTIFICATE ----- \\ n和base64编码的数据开头。 The desired output needs to be in PKCS7 format, starting with -----BEGIN PKCS7-----. 所需的输出必须为PKCS7格式,以----- BEGIN PKCS7 -----开头。

I am looking for an efficient solution, because I am not actually reading and writing files, but handling lots of certificates as strings in memory. 我正在寻找一种有效的解决方案,因为我实际上并不是在读写文件,而是将大量证书作为字符串存储在内存中。

Any suggestions appreciated. 任何建议表示赞赏。

First of all, just to be clear, both the input and output you are requesting are in PEM format. 首先,为了清楚起见,您要求的输入和输出均为PEM格式。 The input is a sequence of PEM-encoded X509 certificates, and the output you request is a PEM-encoded PKCS#7 degenerate "certs only" structure. 输入是PEM编码的X509证书的序列,而您请求的输出是PEM编码的PKCS#7简并的“仅证书”结构。 OpenSSL can output the raw ASN.1 DER for the PKCS#7 structure if you give it the -outform DER option, but it will PEM-encode its output by default. 如果您给它提供-outform DER选项,则OpenSSL可以为PKCS#7结构输出原始的ASN.1 DER,但默认情况下它将对输出进行PEM编码。

There are a number of Go packages out there that can build this kind of PKCS#7 structure. 有很多Go软件包可以构建这种PKCS#7结构。 The following example uses this one . 以下示例使用示例。

If you have your input in a PEM-encoded string, and you want your output to be a PEM-encoded string, then the basic steps are: 如果将输入包含在PEM编码的字符串中,并且希望将输出作为PEM编码的字符串,则基本步骤是:

  1. Extract each PEM-block from your input, decode it, and collect its raw bytes. 从输入中提取每个PEM块,对其进行解码,然后收集其原始字节。
  2. Create a PKCS7 structure from those bytes. 从这些字节创建PKCS7结构。
  3. PEM-encode that structure to an array of bytes. PEM将该结构编码为字节数组。
  4. Convert that array of bytes to a string. 将该字节数组转换为字符串。

Here's a simple example: 这是一个简单的例子:

package main

import (
    "encoding/pem"
    "fmt"
    "log"

    "github.com/fullsailor/pkcs7"
)

var certChain = `-----BEGIN CERTIFICATE-----
MIIEKjCCAhKgAwIBAgIQVUzJj/mbV3n8PS0CHQTfzzANBgkqhkiG9w0BAQsFADBk
MQswCQYDVQQGEwJVUzEWMBQGA1UECBMNTmV3IEhhbXBzaGlyZTETMBEGA1UEBxMK
UG9ydHNtb3V0aDEoMCYGA1UEAxMfU2ltcGxlQ0EgTm9uLVB1YmxpYyBUZXN0IElz
c3VlcjAeFw0xODExMjgyMzMwNDVaFw0xOTAyMjYyMzMwNDVaMBUxEzARBgNVBAMT
CkphbmUgU21pdGgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3iiYS
42eqJOJfF81MekU0w+8UTQgL9D9fh0BYAljgvKx1jvlg6l2CX1OPfNMxOWjDo7DB
ICRrPKxq/FH/tsPumzNWLp6Fsu559MgzkudzRHDVdCF0pa/qujeJeiDLXs7mtekc
rKW6SyrKceknSoPCAwnWr/CEBL09pG3lef7vUMfmkuSMW+L7upHpL/sHyqnyoAnh
9b7IeeQ832rg7b7VOX6zmDcCr6qndhXt6L/neidFbX736wH+fF+iKyTw7XJNflqT
YvifUvnI9rGriDZdAPVa1/a94tKHbFzil/2UEDzNo61mcucbcHqhUL4Iezpi/s5I
iyXqM9oMoMQKPSAlAgMBAAGjJzAlMAsGA1UdDwQEAwIDqDAWBgNVHSUBAf8EDDAK
BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAgEAXe8ipocWVv+Bc78ci6QjAb6N
1DN0n9X7Ai6nvekDP1hqvNUhqKmKhV8pEL7GapyH7Rz3shYJyLEwlV0zUgS3/Uvv
38Ae5xl2uQLl4eoMz4T9NXewZyRmeSyfwz1za93wKGKz6IhoYRepI4EwaPjYowok
nNrocMRFuZHeUysSdLNXtgxKvtRYFI63rjNikJNM7C8mKOzeVobdegZipALxonDb
FcVUhikyu6YkT3Rc5X/oW5I2LfCl9v8mhjbuIPmLsZJyTcDBK81AFIX8g7Iavb8L
buRBIgSTShQISPrunnxbcQg3YimdNCn0n5llDmUP3jxWqiuvEZ7pSAUU6aVY7x8B
fAq9utHTz63FqVCLyl8us/oYZmeYpxpw5HSFhqwujKzJhvO1raaoU+3zsybrsxAy
tzgm05WucSoMTjhOBZFr8OVQxKnMHwgNudwsxuXqqFhUBV5JLkhxWIZxUoH3fhgz
9b2yH0pf/Vgurglfk/onMYR33B0grAT6/NW294oUOKCP9jdwNPQr+eRgoDU6hZ/P
UZMfr+dhVpIHPouSKCrkNXKLrBLFZsg8UiyMXiNB27OBK+mWCH8gUv5EPjW1PUCV
338v19sruqtHRRs7ZnWYMMxGeWosJ4eK/ysTjCespenOeC1HBVEnHQE+H/JvN7Pc
GN3nlK0GRJl5j3y6nmw=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEKzCCAhOgAwIBAgIRAKju/EHi+Hw4PQZENuj9F1AwDQYJKoZIhvcNAQELBQAw
ZDELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU5ldyBIYW1wc2hpcmUxEzARBgNVBAcT
ClBvcnRzbW91dGgxKDAmBgNVBAMTH1NpbXBsZUNBIE5vbi1QdWJsaWMgVGVzdCBJ
c3N1ZXIwHhcNMTgxMTI4MjMzMTQ2WhcNMTkwMjI2MjMzMTQ2WjAVMRMwEQYDVQQD
EwpGcmVkIEpvbmVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt4om
EuNnqiTiXxfNTHpFNMPvFE0IC/Q/X4dAWAJY4LysdY75YOpdgl9Tj3zTMTlow6Ow
wSAkazysavxR/7bD7pszVi6ehbLuefTIM5Lnc0Rw1XQhdKWv6ro3iXogy17O5rXp
HKyluksqynHpJ0qDwgMJ1q/whAS9PaRt5Xn+71DH5pLkjFvi+7qR6S/7B8qp8qAJ
4fW+yHnkPN9q4O2+1Tl+s5g3Aq+qp3YV7ei/53onRW1+9+sB/nxfoisk8O1yTX5a
k2L4n1L5yPaxq4g2XQD1Wtf2veLSh2xc4pf9lBA8zaOtZnLnG3B6oVC+CHs6Yv7O
SIsl6jPaDKDECj0gJQIDAQABoycwJTALBgNVHQ8EBAMCA6gwFgYDVR0lAQH/BAww
CgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggIBAImzRaStB2tb0tCs0x9d0NTy
Z8Q3Fkexvt816xfBGiRS1AtetnV59sJKJvPe9qRoKQDRk7Q+/HO80Iu1o7dWfp7S
h29g9a1uhIVCY1ijr8cW8La9H/OF2KxgGX8TOldrftUl60sA3riJ7lQYOW0NkU+o
wrRsIlMCLhP8NZYjKn2Wf066JtV6Z4Be2CgVpaXkuTIE3h4BOv0kG9OsMvuRMqZw
n7z6EqhduSujwHevB2dIZgixacnE5v5hnpZm1ujzlgbAAZWh7uFthktXL5fBbkW7
heoOv320GOTvqkGVVlc4Pac5kR+P6JWfCDETfIVvtyTtfei5tDm606rBa3BHtiRu
kO4m63fnYziUzRXrF/bDcAzVx5jHQWugpxeI5UcaF6e5psOvhlP6O0sIeN6ThY/I
f+zZN6kf8eZ0OYk+61fVPbbpkF05AFhKkduIRfywUy5+iXrPK4iuQxhM/kRCO0H3
rxXcDlc+9Ol1JiJNNF2lV8+U1APsPFK0gnrxoYLFyRsejCiV8/D67v8oEk0gfiMm
/uZUhC2jYJ05lfK7aGV72Cf82g46zAuNAiH4zwvmxvC/2tcqcaYFyK15D1dQGqOg
z3LR6viX/ncO72ywQWgjRc5hdR5vLinIEXTRlNKm4EW+AoLY3x+Erhmq69EEnGMr
4/GUXRuNB7Is+lFM3JYE
-----END CERTIFICATE-----`

func main() {

    // Decode each PEM block in the input and append the ASN.1
    // DER bytes for each certificate therein to the data slice.

    input := []byte(certChain)
    data := []byte{}

    for len(input) > 0 {
        var block *pem.Block
        block, input = pem.Decode(input)
        data = append(data, block.Bytes...)
    }

    // Build a PKCS#7 degenerate "certs only" structure from
    // that ASN.1 certificates data.

    var err error
    data, err = pkcs7.DegenerateCertificate(data)
    if err != nil {
        log.Fatalf("couldn't create degenerate PKCS7 object: %v", err)
    }

    // Convert the PKCS#7 structure to a PEM-encoded string.

    pemString := string(pem.EncodeToMemory(&pem.Block{
        Type:  "PKCS7",
        Bytes: data,
    }))

    // Print the string, or do whatever you want with it.

    fmt.Printf("%s", pemString)
}

and to show it gives the same output as your OpenSSL command: 并显示它提供与您的OpenSSL命令相同的输出:

paul@mac:certstop7$ cat certs.pem
-----BEGIN CERTIFICATE-----
MIIEKjCCAhKgAwIBAgIQVUzJj/mbV3n8PS0CHQTfzzANBgkqhkiG9w0BAQsFADBk
MQswCQYDVQQGEwJVUzEWMBQGA1UECBMNTmV3IEhhbXBzaGlyZTETMBEGA1UEBxMK
UG9ydHNtb3V0aDEoMCYGA1UEAxMfU2ltcGxlQ0EgTm9uLVB1YmxpYyBUZXN0IElz
c3VlcjAeFw0xODExMjgyMzMwNDVaFw0xOTAyMjYyMzMwNDVaMBUxEzARBgNVBAMT
CkphbmUgU21pdGgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3iiYS
42eqJOJfF81MekU0w+8UTQgL9D9fh0BYAljgvKx1jvlg6l2CX1OPfNMxOWjDo7DB
ICRrPKxq/FH/tsPumzNWLp6Fsu559MgzkudzRHDVdCF0pa/qujeJeiDLXs7mtekc
rKW6SyrKceknSoPCAwnWr/CEBL09pG3lef7vUMfmkuSMW+L7upHpL/sHyqnyoAnh
9b7IeeQ832rg7b7VOX6zmDcCr6qndhXt6L/neidFbX736wH+fF+iKyTw7XJNflqT
YvifUvnI9rGriDZdAPVa1/a94tKHbFzil/2UEDzNo61mcucbcHqhUL4Iezpi/s5I
iyXqM9oMoMQKPSAlAgMBAAGjJzAlMAsGA1UdDwQEAwIDqDAWBgNVHSUBAf8EDDAK
BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAgEAXe8ipocWVv+Bc78ci6QjAb6N
1DN0n9X7Ai6nvekDP1hqvNUhqKmKhV8pEL7GapyH7Rz3shYJyLEwlV0zUgS3/Uvv
38Ae5xl2uQLl4eoMz4T9NXewZyRmeSyfwz1za93wKGKz6IhoYRepI4EwaPjYowok
nNrocMRFuZHeUysSdLNXtgxKvtRYFI63rjNikJNM7C8mKOzeVobdegZipALxonDb
FcVUhikyu6YkT3Rc5X/oW5I2LfCl9v8mhjbuIPmLsZJyTcDBK81AFIX8g7Iavb8L
buRBIgSTShQISPrunnxbcQg3YimdNCn0n5llDmUP3jxWqiuvEZ7pSAUU6aVY7x8B
fAq9utHTz63FqVCLyl8us/oYZmeYpxpw5HSFhqwujKzJhvO1raaoU+3zsybrsxAy
tzgm05WucSoMTjhOBZFr8OVQxKnMHwgNudwsxuXqqFhUBV5JLkhxWIZxUoH3fhgz
9b2yH0pf/Vgurglfk/onMYR33B0grAT6/NW294oUOKCP9jdwNPQr+eRgoDU6hZ/P
UZMfr+dhVpIHPouSKCrkNXKLrBLFZsg8UiyMXiNB27OBK+mWCH8gUv5EPjW1PUCV
338v19sruqtHRRs7ZnWYMMxGeWosJ4eK/ysTjCespenOeC1HBVEnHQE+H/JvN7Pc
GN3nlK0GRJl5j3y6nmw=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEKzCCAhOgAwIBAgIRAKju/EHi+Hw4PQZENuj9F1AwDQYJKoZIhvcNAQELBQAw
ZDELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU5ldyBIYW1wc2hpcmUxEzARBgNVBAcT
ClBvcnRzbW91dGgxKDAmBgNVBAMTH1NpbXBsZUNBIE5vbi1QdWJsaWMgVGVzdCBJ
c3N1ZXIwHhcNMTgxMTI4MjMzMTQ2WhcNMTkwMjI2MjMzMTQ2WjAVMRMwEQYDVQQD
EwpGcmVkIEpvbmVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt4om
EuNnqiTiXxfNTHpFNMPvFE0IC/Q/X4dAWAJY4LysdY75YOpdgl9Tj3zTMTlow6Ow
wSAkazysavxR/7bD7pszVi6ehbLuefTIM5Lnc0Rw1XQhdKWv6ro3iXogy17O5rXp
HKyluksqynHpJ0qDwgMJ1q/whAS9PaRt5Xn+71DH5pLkjFvi+7qR6S/7B8qp8qAJ
4fW+yHnkPN9q4O2+1Tl+s5g3Aq+qp3YV7ei/53onRW1+9+sB/nxfoisk8O1yTX5a
k2L4n1L5yPaxq4g2XQD1Wtf2veLSh2xc4pf9lBA8zaOtZnLnG3B6oVC+CHs6Yv7O
SIsl6jPaDKDECj0gJQIDAQABoycwJTALBgNVHQ8EBAMCA6gwFgYDVR0lAQH/BAww
CgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggIBAImzRaStB2tb0tCs0x9d0NTy
Z8Q3Fkexvt816xfBGiRS1AtetnV59sJKJvPe9qRoKQDRk7Q+/HO80Iu1o7dWfp7S
h29g9a1uhIVCY1ijr8cW8La9H/OF2KxgGX8TOldrftUl60sA3riJ7lQYOW0NkU+o
wrRsIlMCLhP8NZYjKn2Wf066JtV6Z4Be2CgVpaXkuTIE3h4BOv0kG9OsMvuRMqZw
n7z6EqhduSujwHevB2dIZgixacnE5v5hnpZm1ujzlgbAAZWh7uFthktXL5fBbkW7
heoOv320GOTvqkGVVlc4Pac5kR+P6JWfCDETfIVvtyTtfei5tDm606rBa3BHtiRu
kO4m63fnYziUzRXrF/bDcAzVx5jHQWugpxeI5UcaF6e5psOvhlP6O0sIeN6ThY/I
f+zZN6kf8eZ0OYk+61fVPbbpkF05AFhKkduIRfywUy5+iXrPK4iuQxhM/kRCO0H3
rxXcDlc+9Ol1JiJNNF2lV8+U1APsPFK0gnrxoYLFyRsejCiV8/D67v8oEk0gfiMm
/uZUhC2jYJ05lfK7aGV72Cf82g46zAuNAiH4zwvmxvC/2tcqcaYFyK15D1dQGqOg
z3LR6viX/ncO72ywQWgjRc5hdR5vLinIEXTRlNKm4EW+AoLY3x+Erhmq69EEnGMr
4/GUXRuNB7Is+lFM3JYE
-----END CERTIFICATE-----
paul@mac:certstop7$ openssl crl2pkcs7 -nocrl -certfile certs.pem > openssl_p7.pem
paul@mac:certstop7$ ./certstop7 > generated_p7.pem
paul@mac:certstop7$ diff generated_p7.pem openssl_p7.pem
paul@mac:certstop7$ 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM