如何正确生成用于 tls 客户端身份验证的客户端证书

时间:2021-04-30 10:03:14

标签: go ssl

我正在尝试在 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)
    }
}

0 个答案:

没有答案