我正在尝试在 Go 中生成客户端证书以用于 tls 客户端身份验证。
为此,我使用此模板生成并签署(使用一些根证书)客户端证书:
var clientTemplate = x509.Certificate{
SerialNumber: big.NewInt(1),
NotBefore: time.Now().Add(-10 * time.Second),
NotAfter: time.Now().AddDate(10, 0, 0),
KeyUsage: x509.KeyUsageCRLSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
IsCA: false,
MaxPathLenZero: true,
IPAddresses: []net.IP{net.IP([]byte{10, 10,0,4})},
DNSNames: []string{},
}
但是当我尝试验证此证书时:
verifyOptions := x509.VerifyOptions{
DNSName: "10.10.0.4",
Roots: certPool,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
_, err = ClientCert.Verify(verifyOptions)
我收到错误:
certificate specifies an incompatible key usage
但是我的密钥使用有什么问题?我必须指定什么?
这是一个完整的 go test 我是如何尝试的:
func TestClientCertVerify(t *testing.T) {
// Generate Root CA
var rootTemplate = x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
Country: []string{"DE"},
Organization: []string{"Company Co."},
CommonName: "Root CA",
},
NotBefore: time.Now().Add(-10 * time.Second),
NotAfter: time.Now().AddDate(10, 0, 0),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
IsCA: true,
MaxPathLen: 2,
IPAddresses: []net.IP{},
DNSNames: []string{},
}
rootPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
rootCertBytes, err := x509.CreateCertificate(rand.Reader, &rootTemplate, &rootTemplate, &rootPrivKey.PublicKey, rootPrivKey)
if err != nil {
panic("Failed to create certificate:" + err.Error())
}
rootCert, err := x509.ParseCertificate(rootCertBytes)
if err != nil {
panic("failed to parse certificate:" + err.Error())
}
// Generate client certificate
clientPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
var clientTemplate = x509.Certificate{
SerialNumber: big.NewInt(1),
NotBefore: time.Now().Add(-10 * time.Second),
NotAfter: time.Now().AddDate(10, 0, 0),
KeyUsage: x509.KeyUsageCRLSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
IsCA: false,
MaxPathLenZero: true,
IPAddresses: []net.IP{net.IP([]byte{10, 10,0,4})},
DNSNames: []string{},
}
clientCertBytes, err := x509.CreateCertificate(rand.Reader, &clientTemplate, rootCert, &clientPrivKey.PublicKey, rootPrivKey)
if err != nil {
panic("Failed to create certificate:" + err.Error())
}
ClientCert, err := x509.ParseCertificate(clientCertBytes)
if err != nil {
panic("failed to parse certificate:" + err.Error())
}
// Create cert pool for verification
certPool := x509.NewCertPool()
certPool.AddCert(rootCert)
// Verify a client
verifyOptions := x509.VerifyOptions{
DNSName: "10.10.0.4",
Roots: certPool,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
_, err = ClientCert.Verify(verifyOptions)
if err != nil {
t.Error(err)
}
}