“tls.X509KeyPair”出现“在证书输入中找不到任何PEM数据”的错误弹窗。

huangapple go评论67阅读模式
英文:

"failed to find any PEM data in certificate input" error popup by tls.X509KeyPair

问题

我正在尝试使用Golang的x509包为HTTPS服务器生成TLS证书,但是遇到了以下错误:

tls: 在证书输入中找不到任何PEM数据

经过一些研究,我按照以下方式创建了我的证书:

func Generatecert() {
	ca := &x509.Certificate{
		SerialNumber: big.NewInt(2023),
		Subject: pkix.Name{
			Organization:       []string{"Company"},
			OrganizationalUnit: []string{"lol"},
			Country:            []string{"US"},
			Province:           []string{""},
			Locality:           []string{"NY"},
			StreetAddress:      []string{"No street"},
			PostalCode:         []string{"77777"},
		},
		NotBefore:             time.Now(),
		NotAfter:              time.Now().AddDate(10, 0, 0),
		SubjectKeyId:          []byte{1, 2, 3, 4, 5},
		BasicConstraintsValid: true,
		IsCA:                  true,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
	}

	certpubl, certpriv, err := ed25519.GenerateKey(rand.Reader)
	if err != nil {
		log.Println("key generate failed", err)
		return
	}

	certCert, err := x509.CreateCertificate(rand.Reader, ca, ca, certpubl, certpriv)
	if err != nil {
		log.Println("create cert failed", err)
		return
	}

	out := &bytes.Buffer{}

	// 编码证书
	certtestpem := &pem.Block{Type: "CERTIFICATE", Bytes: certCert}
	pem.Encode(out, certtestpem)
	publicCert := out.Bytes()
	certDERBlock, publicCert := pem.Decode(publicCert)

	// 检查解码后的证书
	print(certDERBlock.Type, "\n")
	if publicCert != nil {
		print("publicCert nil\n")
	}

	// 编码私钥
	out.Reset()
	privatepem, _ := x509.MarshalPKCS8PrivateKey(certpriv)
	pem.Encode(out, &pem.Block{Type: "PRIVATE KEY", Bytes: privatepem})
	privitKey := out.Bytes()

	// 检查密钥对
	_, err = tls.X509KeyPair(publicCert, privitKey)
	if err != nil {
		print(err.Error())
	}
}

它显示以下错误:

CERTIFICATE

publicCert nil

tls: 在证书输入中找不到任何PEM数据

我尝试在pem.EncodeToMemory之后进行解码,pem.Type是正确的,但变量publicCertnil。我尝试在证书前面添加\n,但没有任何效果,但证书本身不是nil。有人可以帮我解决这个问题吗?

我应该怎么做才能创建一个可用的TLS证书?

英文:

I am trying to make are tls cert for HTTPS server by golang x509 package

and i got this error

> tls: failed to find any PEM data in certificate input

After some research, I create my Cert like this

func Generatecert()  {
ca := &x509.Certificate{
SerialNumber: big.NewInt(2023),
Subject: pkix.Name{
Organization:       []string{"Company"},
OrganizationalUnit: []string{"lol"},
Country:            []string{"US"},
Province:           []string{""},
Locality:           []string{"NY"},
StreetAddress:      []string{"No street"},
PostalCode:         []string{"77777"},
},
NotBefore:             time.Now(),
NotAfter:              time.Now().AddDate(10, 0, 0),
SubjectKeyId:          []byte{1, 2, 3, 4, 5},
BasicConstraintsValid: true,
IsCA:                  true,
ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
}
certpubl, certpriv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
log.Println("key generate failed", err)
return
}
certCert, err := x509.CreateCertificate(rand.Reader, ca, ca, certpubl, certpriv)
if err != nil {
log.Println("create cert failed", err)
return
}
out := &bytes.Buffer{}
//Encoding cert
certtestpem := &pem.Block{Type: "CERTIFICATE", Bytes: certCert}
pem.Encode(out, certtestpem)
publicCert := out.Bytes()
certDERBlock, publicCert := pem.Decode(publicCert)
//Check Decoded cert
print(certDERBlock.Type, "\n")
if publicCert != nil {
print("publicCert nil\n")
}
//Encoding Private Key
out.Reset()
privatepem, _ := x509.MarshalPKCS8PrivateKey(certpriv)
pem.Encode(out, &pem.Block{Type: "PRIVATE KEY", Bytes: privatepem})
privitKey := out.Bytes()
//check KeyPair
_, err = tls.X509KeyPair(publicCert, privitKey)
if err != nil {
print(err.Error())
}
}

it show the error like under

> CERTIFICATE
>
> publicCert nil
>
> tls: failed to find any PEM data in certificate input

I try Decode after pem.EncodeToMemory

the pem.Type are correct, but variable "publicCert" is nil, And I try add are \n begin of the cert, it did nothing, but the cert itself is not nil, Can Somebody Help me with this

What sould I do to make a working Tls???

答案1

得分: 0

经过一些调试,似乎 pem.Encode 函数对我不起作用,

所以我将其更改为 pem.EncodeToMemory,现在它可以工作了,谢谢你的帮助。

英文:

after some debug, it seem like the pem.Encode function not working for me,

so i change it to pem.EncodeToMemory and it working thank you for the help.

答案2

得分: 0

这段代码存在几个问题:

publicCert := out.Bytes()

在这个阶段检查publicCert的内容显示了预期的值。但是接下来的语句会简单地覆盖publicCert

certDERBlock, publicCert := pem.Decode(publicCert)

通过在这个语句之后检查publicCert可以看出这一点。根据文档所述,publicCert现在将显示实际证书之后的数据。

应该改为:

certDERBlock, _ := pem.Decode(publicCert)

在纠正了这个语句之后,检查publicCert的内容再次显示了预期的值。

out.Reset()
privatepem, _ := x509.MarshalPKCS8PrivateKey(certpriv)
pem.Encode(out, &pem.Block{Type: "PRIVATE KEY", Bytes: privatepem})
privitKey := out.Bytes()

这将把预期的值放入privitKey中。但是,它会改变publicCert,因为它只是out的一个切片,而out已经被这些操作改变了。因此,out现在在开头包含privitKey,而不再包含证书的开头部分,这在publicCert的值中反映出来。

另请参阅bytes.Buffer.Bytes的文档

切片只在下一次缓冲区修改之前有效使用(也就是说,只在下一次调用Read、Write、Reset或Truncate等方法之前有效)。

所以,不仅仅重置现有的缓冲区:

out.Reset()

更好的做法是为privitKey创建一个新的缓冲区,并保留现有的缓冲区用于publicCert

out = &bytes.Buffer{}
英文:

There are several problems in this code

> publicCert := out.Bytes()

Checking the content of publicCert at this stage shows the expect value. But the following statement will simply overwrite publicCert:

> certDERBlock, publicCert := pem.Decode(publicCert)

This can be seen by checking publicCert after this statement. As documented publicCert will now show the data after the actual certificate.

It should be instead

certDERBlock, _ := pem.Decode(publicCert)

Checking the content of publicCert after this corrected statement shows the expected value again.

> out.Reset()
> privatepem, _ := x509.MarshalPKCS8PrivateKey(certpriv)
> pem.Encode(out, &pem.Block{Type: "PRIVATE KEY", Bytes: privatepem})
> privitKey := out.Bytes()

This will get the expected value into privitKey. But, it will change publicCert since it is just a slice of out and out has been changed the the operations. Thus out will now contain at the beginning the privitKey and no longer the start of the certificate - and this is reflected in the value of publicCert.

See also the documentation for bytes.Buffer.Bytes

> The slice is valid for use only until the next buffer modification (that is, only until the next call to a method like Read, Write, Reset, or Truncate)

So instead of just resetting the existing buffer

> out.Reset()

it would be better to create a new buffer for privitKey and keep the existing one for publicCert

> out = &bytes.Buffer{}

huangapple
  • 本文由 发表于 2023年1月12日 18:19:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/75094738.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定