使用自签名证书实现tls.Config.GetCertificate

时间:2016-11-03 22:25:13

标签: http ssl go

我试图找出如何使用自签名证书实现向tls.Config.GetCertificate提供的函数。

我使用此bin源作为基础,https://golang.org/src/crypto/tls/generate_cert.go

还读这个, https://ericchiang.github.io/tls/go/https/2015/06/21/go-tls.html

不幸的是,到目前为止,我仍然坚持这个错误 2016/11/03 23:18:20 http2: server: error reading preface from client 127.0.0.1:34346: remote error: tls: unknown certificate authority

我想我需要生成一个CA证书,然后用它来签名密钥,但我不知道如何继续(....)。

这是我的代码,有人可以帮忙吗?

package gssc

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/tls"
    "crypto/x509"
    "crypto/x509/pkix"
    "github.com/pkg/errors"
    "math/big"
    "net"
    "strings"
    "time"
)

func GetCertificate(arg interface{}) func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
    var opts Certopts
    var err error
    if host, ok := arg.(string); ok {
        opts = Certopts{
            RsaBits:   2048,
            Host:      host,
            ValidFrom: time.Now(),
        }
    } else if o, ok := arg.(Certopts); ok {
        opts = o
    } else {
        err = errors.New("Invalid arg type, must be string(hostname) or Certopt{...}")
    }
    return func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
        if err != nil {
            return nil, err
        }
        return generate(opts)
    }
}

type Certopts struct {
    RsaBits   int
    Host      string
    IsCA      bool
    ValidFrom time.Time
    ValidFor  time.Duration
}

func generate(opts Certopts) (*tls.Certificate, error) {

    priv, err := rsa.GenerateKey(rand.Reader, opts.RsaBits)
    if err != nil {
        return nil, errors.Wrap(err, "failed to generate private key")
    }

    notAfter := opts.ValidFrom.Add(opts.ValidFor)

    serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
    serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
    if err != nil {
        return nil, errors.Wrap(err, "Failed to generate serial number\n")
    }

    template := x509.Certificate{
        SerialNumber: serialNumber,
        Subject: pkix.Name{
            Organization: []string{"Acme Co"},
        },
        NotBefore: opts.ValidFrom,
        NotAfter:  notAfter,

        KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
        ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
        BasicConstraintsValid: true,
    }

    hosts := strings.Split(opts.Host, ",")
    for _, h := range hosts {
        if ip := net.ParseIP(h); ip != nil {
            template.IPAddresses = append(template.IPAddresses, ip)
        } else {
            template.DNSNames = append(template.DNSNames, h)
        }
    }

    if opts.IsCA {
        template.IsCA = true
        template.KeyUsage |= x509.KeyUsageCertSign
    }

    derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
    if err != nil {
        return nil, errors.Wrap(err, "Failed to create certificate")
    }

    return &tls.Certificate{
        Certificate: [][]byte{derBytes},
        PrivateKey:  priv,
    }, nil
}

这是我使用的测试代码

package main

import (
    "crypto/tls"
    "github.com/mh-cbon/gssc"
    "net/http"
)

type ww struct{}

func (s *ww) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte("This is an example server.\n"))
}

func main() {
    s := &http.Server{
        Handler: &ww{},
        Addr:    ":8080",
        TLSConfig: &tls.Config{
            InsecureSkipVerify: true,
            GetCertificate:     gssc.GetCertificate("example.org"),
        },
    }
    s.ListenAndServeTLS("", "")

}

非常感谢!

1 个答案:

答案 0 :(得分:3)

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE); int defaultValue = 0; long highScore = sharedPref.getInt("highscore"), defaultValue); 的实施导致了问题。

每次调用tls.Config.GetCertificate时都会生成证书。您需要生成一次证书,然后在匿名函数中返回它。

tls.Config.GetCertificate

gssc.GetCertificate