具有自定义 CA 的客户端-服务器 TLS

Client-server TLS with custom CA

我写了一个小测试程序来创建

  1. 自定义的自签名 CA 证书#1
  2. 创建由该 CA 颁发的服务器证书#2 - 根证书#1
  3. 使用证书#2 创建服务器
  4. 使用指向证书#1 的 RootCA 创建客户端
  5. 客户端尝试连接到服务器并收到错误:

Get "https://localhost:2000": x509: certificate signed by unknown authority (possibly because of "x509: Ed25519 verification failure" while trying to verify candidate authority certificate "test-ca")

据我所知,这样的例子有几十个。我以为我已经很接近他们了,但我却在这里。我在这里只展示最相关的结构,但 the full text of the program can be found here:

    ...
    templateCA := &x509.Certificate{
        Subject: pkix.Name{
            CommonName:   "test-ca",
            Organization: []string{"test ca"},
            Country:      []string{"USA"},
            Province:     []string{"NY"},
            Locality:     []string{"New York City"},
        },
        SerialNumber:          serialNumber,
        NotBefore:             time.Now(),
        NotAfter:              time.Now().AddDate(0, 0, 1),
        BasicConstraintsValid: true,
        IsCA:                  true,
        SubjectKeyId:          caSubjectKeyID[:],
        DNSNames:              []string{"test-ca"},
        KeyUsage:              x509.KeyUsageCertSign
    }
    ...
    certBytes, _ := x509.CreateCertificate(rand.Reader, templateCA, templateCA, privKey.Public(), privKey)
    ...
    templateServer := &x509.Certificate{
        Subject: pkix.Name{
            CommonName:   "localhost",
            Organization: []string{"Server"},
            Country:      []string{"USA"},
            Province:     []string{"NY"},
            Locality:     []string{"New York City"},
        },
        SerialNumber:          serialNumber,
        NotBefore:             time.Now(),
        NotAfter:              time.Now().AddDate(0, 0, 1),
        BasicConstraintsValid: true,
        SubjectKeyId:          servSubjectKeyID[:],
        AuthorityKeyId:        caSubjectKeyID[:],
        DNSNames:              []string{"localhost"},
        IPAddresses:           []net.IP{{127, 0, 0, 1}},
        KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
        ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
    }
    ...
    certBytes, _ = x509.CreateCertificate(rand.Reader, templateServer, caCert, privKey.Public(), privKey)
    ...
var (
    tlsMinVersion = uint16(tls.VersionTLS12)
    tlsMaxVersion = uint16(tls.VersionTLS13)
    cipherSuites  = []uint16{
        tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
        tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
        tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
        tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
        tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
        tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
    }
    curvePreferences = []tls.CurveID{
        tls.X25519,
        tls.CurveP256,
        tls.CurveP384,
        tls.CurveP521,
    }
)
    ...
    tlsServerConfig := &tls.Config{
        Certificates:             []tls.Certificate{*tlsSrvCert},
        MinVersion:               tlsMinVersion,
        MaxVersion:               tlsMaxVersion,
        CurvePreferences:         curvePreferences,
        CipherSuites:             cipherSuites,
        PreferServerCipherSuites: true,
    }
    ...
    tlsClientConfig := &tls.Config{
        ServerName:               "localhost",
        RootCAs:                  x509.NewCertPool(),
        MinVersion:               tlsMinVersion,
        MaxVersion:               tlsMaxVersion,
        CurvePreferences:         curvePreferences,
        CipherSuites:             cipherSuites,
        PreferServerCipherSuites: true,
    }
    tlsClientConfig.RootCAs.AddCert(caCert)
    

我错过了什么或做错了什么?

您可以使用私钥解密数据并加密散列数据以创建数字签名。

您可以使用public密钥加密数据并解密数字签名来验证它。

你需要做的是,使用一个密钥对(public/private密钥)生成CA证书并使用该证书+相同的密钥对生成您服务器的一个或多个证书。

如果您想使用浏览器/curl 作为客户端,您需要在根密钥库中添加 CA 证书。

感谢@djoudat 指出我的错误。我在这里粘贴上面更正的代码片段。希望有一天,他们可以帮助某人。

...
templateCA := &x509.Certificate{
    Subject: pkix.Name{
        CommonName:   "test-ca",
        Organization: []string{"test ca"},
        Country:      []string{"USA"},
        Province:     []string{"NY"},
        Locality:     []string{"New York City"},
    },
    SerialNumber:          serialNumber,
    NotBefore:             time.Now(),
    NotAfter:              time.Now().AddDate(0, 0, 1),
    BasicConstraintsValid: true,
    IsCA:                  true,
    KeyUsage:              x509.KeyUsageCertSign
    DNSNames:              []string{"test-ca"},
}
...
certBytes, _ := x509.CreateCertificate(rand.Reader, templateCA, templateCA, privKeyCA.Public(), privKeyCA)
...
templateServer := &x509.Certificate{
    Subject: pkix.Name{
        CommonName:   "localhost",
        Organization: []string{"Server"},
        Country:      []string{"USA"},
        Province:     []string{"NY"},
        Locality:     []string{"New York City"},
    },
    SerialNumber:          serialNumber,
    NotBefore:             time.Now(),
    NotAfter:              time.Now().AddDate(0, 0, 1),
    BasicConstraintsValid: true,
    KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
    ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
    DNSNames:              []string{"localhost"},
}
...
certBytes, _ = x509.CreateCertificate(rand.Reader, templateServer, caCert, privKeyServer.Public(), privKeyCA)
...
var (
    tlsMinVersion = uint16(tls.VersionTLS12)
    tlsMaxVersion = uint16(tls.VersionTLS13)
    cipherSuites  = []uint16{
        tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
        tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
        tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
        tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
        tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
        tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
    }
    curvePreferences = []tls.CurveID{
        tls.X25519,
        tls.CurveP256,
        tls.CurveP384,
        tls.CurveP521,
    }
)
...
tlsServerConfig := &tls.Config{
    Certificates:             []tls.Certificate{*tlsSrvCert},
    MinVersion:               tlsMinVersion,
    MaxVersion:               tlsMaxVersion,
    CurvePreferences:         curvePreferences,
    CipherSuites:             cipherSuites,
    PreferServerCipherSuites: true,
}
...
tlsClientConfig := &tls.Config{
    ServerName:               "localhost",
    RootCAs:                  x509.NewCertPool(),
    MinVersion:               tlsMinVersion,
    MaxVersion:               tlsMaxVersion,
    CurvePreferences:         curvePreferences,
    CipherSuites:             cipherSuites,
    PreferServerCipherSuites: true,
}
tlsClientConfig.RootCAs.AddCert(caCert)